Re: [Tutor] Why is an OrderedDict not sliceable?
On 20/01/2016 13:33, Albert-Jan Roskam wrote: Hi, Like the subject says: Why is an OrderedDict not sliceable? (From the collections library). Was that an intentional omission, or a mistake? [1] Plenty of answers on this all ready, but... Background: I do not use OrderedDict very often, but I thought I could use it to look up street and city names using postcodes ([0-9]{4} [a-z]{2} format). I needed it to be ordered because I also wanted to be able to use bisect, which is needed when the postcode letters are missing. In short: a fast dict lookup for complete postcodes and less fast bisect lookup for in complete postcodes. You appear to be confusing ordered and sorted. There is no way that you can use bisect on an OrderedDict unless it is sorted in the first place. [1] http://stackoverflow.com/questions/30975339/slicing-a-python-ordereddict Thanks! Albert-Jan -- My fellow Pythonistas, ask not what our language can do for you, ask what you can do for our language. Mark Lawrence ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
[Tutor] No connection could be made because the target machine actively refused it (despite mongod running) and unable to insert data into MongoDB
Hello everyone, I have been trying to insert data (a 'hello world' string) from PLC into MongoDB using Python API (which pulls the data from PLC and pushes it into MongoDB). I have been getting the error message '*line 222, in meth return getattr(self._sock,name)(*args) error: [Errno 10061] No connection could be made because the target machine actively refused it*' despite having mongod running in the Services background for the code I have written below. Also, the server IP address on which MongoDB is present is 10.52.124.186 and address of PLC (which I am using it on my PC) is 10.52.124.135. I am have tried almost everything to sort it out and yet I haven't got a clue as to how to get past it. Where am I going wrong? #!/usr/bin/python import socket import socket import pymongo from pymongo import MongoClient import datetime # Connection to server (PLC) on port 27017 server = socket.socket() host = '10.52.124.135' port = 27017 server.connect((host, port)) print server.recv(1024) server.close #Connection to Client (Mongodb) on port 27017 IP = '10.52.124.186' PORT = 27017 BUFFER_SIZE = 1024 client = MongoClient('10.52.124.186', 27017) db = client.RXMMongoDB s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.bind((IP, PORT)) s.listen(1) #connections loop while True: conn, addr = s.accept() print 'Connection address:',addr try: # read loop while True: data = server.recv(BUFFER_SIZE) if not data: break # send to Mongo mongodoc = { "data": data, "date" : datetime.datetime.utcnow() } db..insert(mongodoc) finally: conn.close() -- Mit freundlichen Grüßen / Thanks and Regards, *Arjun Srivatsa* ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
[Tutor] Extract several arrays from a large 2D array
Thank you all for your help. I am a decent programmer in another language but new to Python and I have some issues with a project I am working on. Some suggested using pandas but I am barley starting on Numpy. The suggestions were very helpful, however, I decided to replace the 2D array with several single arrays b/c the arrays are of different data types. I ran into another problems and am almost done but got stuck. Part of my code is below. The question is how to put the variables for each j into a 14 by 6 array by a statement at the end of this code. I was hoping to get an array like this one below: [2013 TT1 TT2 TT3 TT4 TT5 TT6] [2012TT1 TT2 TT3 TT4 TT5 TT6] . . [1999TT1 TT2 TT3 TT4 TT5 TT6] for j in range(14) for i in range(200): if TYear[i]==2013-j: if TTrea[i]=='T1': TT1+=TTemp[i] elif TTrea[i]=='T2': TT2+=TTemp[i] elif TTrea[i]=='T3': TT3+=TTemp[i] elif TTrea[i]=='T4': TT4+=TTemp[i] elif TTrea[i]=='T5': TT5+=TTemp[i] elif TTrea[i]=='T6': TT6+=TTemp[i] ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] No connection could be made because the target machine actively refused it (despite mongod running) and unable to insert data into MongoDB
On 21/01/16 22:06, Arjun Srivatsa wrote: > Hello everyone, > > I have been trying to insert data (a 'hello world' string) from PLC into > MongoDB using Python API (which pulls the data from PLC and pushes it into > MongoDB). I have been getting the error message '*line 222, in meth return > getattr(self._sock,name)(*args) error: [Errno 10061] No connection could be > made because the target machine actively refused it*' despite having mongod > running in the Services background for the code I have written below. Also, > the server IP address on which MongoDB is present is 10.52.124.186 and > address of PLC (which I am using it on my PC) is 10.52.124.135. I am have > tried almost everything to sort it out and yet I haven't got a clue as to > how to get past it. Where am I going wrong? This looks more like a MongoDB issue than a Python one. Can you connect from the same machine using the Mongo command line tools and options? You might have more success asking on a Mongo support forum/list. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Extract several arrays from a large 2D array
Ek Esawi wrote: > Thank you all for your help. I am a decent programmer in another language > but new to Python and I have some issues with a project I am working on. > Some suggested using pandas but I am barley starting on Numpy. The > suggestions were very helpful, however, I decided to replace the 2D array > with several single arrays b/c the arrays are of different data types. I > ran into another problems and am almost done but got stuck. > > > > Part of my code is below. The question is how to put the variables for > each j into a 14 by 6 array by a statement at the end of this code. I was > hoping to get an array like this one below: > > [2013 TT1 TT2 TT3 TT4 TT5 TT6] > > [2012TT1 TT2 TT3 > TT4 TT5 TT6] > > . > > . > > [1999TT1 TT2 TT3 > TT4 TT5 TT6] > > for j in range(14) > > for i in range(200): As a rule of thumb, if you are iterating over individual array entries in numpy you are doing something wrong ;) > > if TYear[i]==2013-j: > > if TTrea[i]=='T1': > > TT1+=TTemp[i] > > elif TTrea[i]=='T2': > > TT2+=TTemp[i] > > elif TTrea[i]=='T3': > > TT3+=TTemp[i] > > elif TTrea[i]=='T4': > > TT4+=TTemp[i] > > elif TTrea[i]=='T5': > > TT5+=TTemp[i] > > elif TTrea[i]=='T6': > TT6+=TTemp[i] This looks like you are manually building a pivot table. If you don't want to use a spreadsheet (like Excel or Libre/OpenOffice Calc) you can do it with pandas, too: import pandas import numpy df = pandas.DataFrame( [ [2013, "T1", 42], [2013, "T2", 12], [2012, "T1", 1], [2012, "T1", 2], [2012, "T2", 10], [2012, "T3", 11], [2012, "T4", 12], ], columns=["year", "t", "v"]) print( pandas.pivot_table(df, cols="t", rows="year", aggfunc=numpy.sum) ) Here's a generic Python solution for educational purposes. It uses nested dicts to model the table. The outer dict is used for the rows, the inner dicts for the cells in a row. An extra set keeps track of the column labels. data = [ [2013, "T1", 42], [2013, "T2", 12], [2012, "T1", 1], [2012, "T1", 2], [2012, "T2", 10], [2012, "T3", 11], [2012, "T4", 12], ] table = {} columns = set() for year, t, v in data: columns.add(t) row = table.setdefault(year, {}) row[t] = row.get(t, 0) + v columns = sorted(columns) print("", *["{:>5}".format(c) for c in columns]) for year, row in sorted(table.items(), reverse=True): print(year, *["{:5}".format(row.get(c, 0)) for c in columns]) ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] No connection could be made because the target machine actively refused it (despite mongod running) and unable to insert data into MongoDB
On 1/21/2016 2:06 PM, Arjun Srivatsa wrote: Hello everyone, I have been trying to insert data (a 'hello world' string) from PLC into MongoDB using Python API (which pulls the data from PLC and pushes it into MongoDB). I have been getting the error message '*line 222, in meth return getattr(self._sock,name)(*args) error: [Errno 10061] No connection could be made because the target machine actively refused it*' despite having mongod running in the Services background for the code I have written below. Also, the server IP address on which MongoDB is present is 10.52.124.186 and address of PLC (which I am using it on my PC) is 10.52.124.135. I am have tried almost everything to sort it out and yet I haven't got a clue as to how to get past it. Where am I going wrong? The error you're getting means that the firewall running on the mongod host machine is not properly configured to allow mongod traffic into it. Talk to the machines firewall administrator. Emile ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Tutor Digest, Vol 143, Issue 77
Semantic errors are when a program acts incorrectly and doesn't give a error, this came up yesterday. Samuel Kirwin Samvelk On Fri, Jan 22, 2016 at 9:02 AM -0800, wrote: Send Tutor mailing list submissions to tutor@python.org To subscribe or unsubscribe via the World Wide Web, visit https://mail.python.org/mailman/listinfo/tutor or, via email, send a message with subject or body 'help' to tutor-requ...@python.org You can reach the person managing the list at tutor-ow...@python.org When replying, please edit your Subject line so it is more specific than "Re: Contents of Tutor digest..." Today's Topics: 1. Re: No connection could be made because the target machine actively refused it (despite mongod running) and unable to insert data into MongoDB (Emile van Sebille) -- Message: 1 Date: Fri, 22 Jan 2016 06:37:19 -0800 From: Emile van Sebille To: tutor@python.org Subject: Re: [Tutor] No connection could be made because the target machine actively refused it (despite mongod running) and unable to insert data into MongoDB Message-ID: Content-Type: text/plain; charset=utf-8; format=flowed On 1/21/2016 2:06 PM, Arjun Srivatsa wrote: > Hello everyone, > > I have been trying to insert data (a 'hello world' string) from PLC into > MongoDB using Python API (which pulls the data from PLC and pushes it into > MongoDB). I have been getting the error message '*line 222, in meth return > getattr(self._sock,name)(*args) error: [Errno 10061] No connection could be > made because the target machine actively refused it*' despite having mongod > running in the Services background for the code I have written below. Also, > the server IP address on which MongoDB is present is 10.52.124.186 and > address of PLC (which I am using it on my PC) is 10.52.124.135. I am have > tried almost everything to sort it out and yet I haven't got a clue as to > how to get past it. Where am I going wrong? The error you're getting means that the firewall running on the mongod host machine is not properly configured to allow mongod traffic into it. Talk to the machines firewall administrator. Emile -- Subject: Digest Footer ___ Tutor maillist - Tutor@python.org https://mail.python.org/mailman/listinfo/tutor -- End of Tutor Digest, Vol 143, Issue 77 ** ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
[Tutor] Combine Scripts to Work Together...
Hi,I am new to Python, but learning. (Hopefully the layout is readable) I am having trouble getting two scripts to work together. What I want to do is have the combinded script do the following: 1. Read through a directory of xml files, not a single file, but many xml files.2. Read each files contents.3. Pull out the element content (words between open and close tag) * For example: Sam was here. * The script would pull out the content "Sam was here" and print it to a file. My scripts so far:--Script to get content--import xml.etree.ElementTree as ET tree = ET.parse('TEST.xml') root = tree.getroot()for uicontrol in root.iter('uicontrol'): print(uicontrol.text) --Script to read through the files:--import sys import glob import errnopath ='/Users/sastarfa/Documents/Projects/Script-projects/Scripts/Pull-out-terms-between-elements/*.xml' files = glob.glob(path) for name in files: # 'file' is a builtin type, 'name' is a less-ambiguousvariable name. try: with open(name) as f: # Noneed to specify 'r': this is the default. sys.stdout.write(f.read()) This is the area I get stuck. I can understand, write a script to run on one a single file you input into the script, but getting a script to run on a directory I am not understanding how to do this. Thanks in advance for any and all help.Really appreciate the help. Sam ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
[Tutor] Semantic error (was: Re: Tutor Digest, Vol 143, Issue 77)
On 22/01/16 17:05, samuel kirwin wrote: > Semantic errors are when a program acts incorrectly and doesn't give a error, > this came up yesterday. > > Samuel Kirwin Hi Sam, Thanks for participating. However, it will make your comments more meaningful if you reply with the subject line set to whatever tread you were responding to. Also if using the digest please delete all irrelevant messages/content. That way we can see the context. We've all seen them already and some of us pay by the byte. As it is, the above statement just seems like a fairly random comment. After all, the word semantic does not occur anywhere within the glossary messages you forwarded. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Combine Scripts to Work Together...
On Fri, Jan 22, 2016 at 1:16 PM, Sam Starfas via Tutor wrote: > > > > Hi,I am new to Python, but learning. (Hopefully the layout is readable) > I am having trouble getting two scripts to work together. What I want to > do is have the combinded script do the following: > 1. Read through a directory of xml files, not a single file, but many xml > files.2. Read each files contents.3. Pull out the element > content (words between open and close tag) >* For example: Sam was here. >* The script would pull out the content "Sam was here" and print it to > a file. > > My scripts so > far:--Script to get > > content--import > xml.etree.ElementTree as ET > tree = ET.parse('TEST.xml') > root = tree.getroot()for uicontrol in root.iter('uicontrol'): > print(uicontrol.text) > Make the above a function def get_uicontrol(f): > tree = ET.parse(f)) > root = tree.getroot()for uicontrol in root.iter('uicontrol'): > print(uicontrol.text) > --Script to read > through the > files:--import sys > import glob > import errnopath > ='/Users/sastarfa/Documents/Projects/Script-projects/Scripts/Pull-out-terms-between-elements/*.xml' > files = glob.glob(path) > for name in files: # 'file' is a builtin type, 'name' is a > less-ambiguousvariable name. > try: >with open(name) as f: # Noneed to specify 'r': this is the > default. >sys.stdout.write(f.read()) > > Make the above a function: def get_files(path): glob.glob(path) for name in files: try: with open(name) as f get_uicontrol(f) then at the end of your file do this: if __name__ == '__main__': get_files('/your/path/goes/here') get_files will loop to open each file, then call get_uicontrol on that open file. get_uicontrol will find your tag, collect the text and print it I haven't tested this, but it is at least close > This is the area I get stuck. I can understand, write a script to run on > one a single file you input into the script, but getting a script to run on > a directory I am not understanding how to do this. > Thanks in advance for any and all help.Really appreciate the help. > Sam > > > ___ > Tutor maillist - Tutor@python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor > -- Joel Goldstick http://joelgoldstick.com/stats/birthdays ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Combine Scripts to Work Together...
On Fri, Jan 22, 2016 at 1:48 PM, Joel Goldstick wrote: > > > On Fri, Jan 22, 2016 at 1:16 PM, Sam Starfas via Tutor > wrote: > >> >> >> >> Hi,I am new to Python, but learning. (Hopefully the layout is readable) >> I am having trouble getting two scripts to work together. What I want to >> do is have the combinded script do the following: >> 1. Read through a directory of xml files, not a single file, but many xml >> files.2. Read each files contents.3. Pull out the element >> content (words between open and close tag) >>* For example: Sam was here. >>* The script would pull out the content "Sam was here" and print it to >> a file. >> >> My scripts so >> far:--Script to get >> >> content--import >> xml.etree.ElementTree as ET >> tree = ET.parse('TEST.xml') >> root = tree.getroot()for uicontrol in root.iter('uicontrol'): >> print(uicontrol.text) >> > > Make the above a function > def get_uicontrol(f): > >> tree = ET.parse(f)) >> root = tree.getroot()for uicontrol in root.iter('uicontrol'): >> print(uicontrol.text) >> > > --Script to read >> through the >> files:--import sys >> import glob >> import errnopath >> ='/Users/sastarfa/Documents/Projects/Script-projects/Scripts/Pull-out-terms-between-elements/*.xml' >> files = glob.glob(path) >> for name in files: # 'file' is a builtin type, 'name' is a >> less-ambiguousvariable name. >> try: >>with open(name) as f: # Noneed to specify 'r': this is the >> default. >>sys.stdout.write(f.read()) >> >> > Make the above a function: > > def get_files(path): > glob.glob(path) > for name in files: > try: > with open(name) as f: > get_uicontrol(f) > > oops, edited above two lines > then at the end of your file do this: > > if __name__ == '__main__': > get_files('/your/path/goes/here') > > get_files will loop to open each file, then call get_uicontrol on that > open file. get_uicontrol will find your tag, collect the text and print it > > I haven't tested this, but it is at least close > > >> This is the area I get stuck. I can understand, write a script to run on >> one a single file you input into the script, but getting a script to run on >> a directory I am not understanding how to do this. >> Thanks in advance for any and all help.Really appreciate the help. >> Sam >> >> >> ___ >> Tutor maillist - Tutor@python.org >> To unsubscribe or change subscription options: >> https://mail.python.org/mailman/listinfo/tutor >> > > > > -- > Joel Goldstick > http://joelgoldstick.com/stats/birthdays > -- Joel Goldstick http://joelgoldstick.com/stats/birthdays ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
[Tutor] mock
Some weeks (perhaps months) ago, I posted a question about testing and got many responses but had trouble grasping the concepts so I settled on the suggestion that I thought would be the easiest to implement (using unittest.mock.) Here it is- """ from Peter Otten: I find Ben's example instructive, but when you're just starting you might prefer a simpler approach: import unittest from unittest import mock import mycode class TestCollectData(unittest.TestCase): def test(self): with mock.patch( "builtins.input", side_effect=["foo", "bar", "baz"]): self.assertEqual( mycode.collect_data(), dict(first="foo", last="bar", phone="baz")) if __name__ == "__main__": unittest.main() """ I've successfully implemented mock.patch parameters but don't understand how to implement the parameters for the assertEqual call as it pertains to my particular situation. My current code sort of does the job but determinating success or failure is not really automated. It's Python 3 on Ubuntu 14.4LTS. My test code and the tested code follow. Any suggestions would be most welcome. Thanks in advance. Alex Test Code: #!../../venv/bin/python # -*- coding: utf-8 -*- # vim: set file encoding=utf-8 """ Attempt to automate testing of menu module. """ import unittest from unittest import mock import menu class MenuTests(unittest.TestCase): def test_create_new(self): with mock.patch("builtins.input", side_effect=['1', 'testentity', '', '0']): menu.menu() if __name__ == '__main__': # code block to run the application unittest.main() Tested code: #!../../venv/bin/python # -*- coding: utf-8 -*- # vim: set file encoding=utf-8 """ A simple menu model used to format a question about how to test using unittest.mock. """ class Entities(object): """ Keep track of the entities including a default. Expect only one instance which will be a global. """ def __init__(self, list_of_entities, default=''): self._list = list_of_entities self.default = default def get_default(self): return self.default def reset_default(self, default=''): self.default = default def get_list(self): return self._list def add(self, new_entity, set_default=False): """ Adds another entity returning it to signal success. Returns None if entity is unacceptable. """ if (not new_entity in self._list and new_entity.isalnum() and new_entity[0:1].isalpha()): self._list.append(new_entity) if set_default: self.reset_default(new_entity) return new_entity else: print("Failing to add an invalid entity: '{}'." .format(new_entity)) def get_new_entity(self): """ Prompts user for a new entity which, if valid, is returned after being appended to list and set as default. Returns None if fails to create a new entity. """ while True: new_entity = input("Pick name for new entity: ") if not new_entity: return if new_entity != self.add(new_entity, set_default=True): continue else: return new_entity def remove(self, entity2remove): if not entity2remove in self.get_list(): print("Can't remove '{}': not in the list." .format(entity2remove)) return if entity2remove == self.get_default(): self.reset_default() self._list = [entity for entity in self._list if entity!=entity2remove] def show_listing(self): """ Returns a string listing the available entities. Empty string if there are no entities. """ return ''.join(["\n\t{}".format(entity) for entity in self.get_list()]) def entity_choice(self, set_default=False): """ Prompts the user to choose from the list. Returns a valid choice or None. Can optionally set the default to the chosen entity. """ list_of_entities= self.get_list() if not list_of_entities: print("There are no entities from which to choose.") return default_line = '' if self.default: default_line = ("\n\t_: Default is '{}', just hit enter." .format(self.default)) menu = ('\n'.join(["\t{}: {}".format(n, entity) for (n, entity) in enumerate(list_of_entities, 1)]) + default_line) while True: option = input( """Choose one of the following: {} \t0: to exit. Pick an entity: """.format(menu)) default = self.get_default() if (option=='' or option=='_') and default:
Re: [Tutor] Why do I not get an error when I mistakenly type "humdrum.sigh_strenght" instead of the correct "humdrum.sigh_strength"?
On Thu, Jan 21, 2016 at 4:57 AM, Steven D'Aprano wrote: > On Wed, Jan 20, 2016 at 09:54:32PM -0800, Danny Yoo wrote: > >> Just to be explicit: you are pointing out that: >> >> humdrum.sigh_strenght = 'high' >> >> was a typo, and it would have been nice if it could be caught as an error. >> >> If that's the case, then yes, I agree. Unfortunately, this isn't a >> runtime error because Python allows us to add arbitrary attributes to >> objects: it's a deliberate design feature. > > Danny is correct. And it is a useful feature too. For instance, we can > add attributes to functions: > > def spam(x, y): > ... > > spam.extra_info = "whatever" A new thing that I did not suspect I could do. This bothers me for two reasons: 1) It does not seem right adding attributes to functions outside of its definition. 2) spam.extra_info appears to be global: >>> spam.extra_info = "whatever" >>> z = 'WOW!' >>> def print_global_stuff(): print('z =', z) print('spam.extra_info =', spam.extra_info) >>> print_global_stuff() z = WOW! spam.extra_info = whatever And I imagine I am being dense about something that is quite obvious to you: How is this a useful feature to have? What does it give me that is more useful than just saying something like: just_another_global variable = "whatever" ? And what bothered me about my original example that started this thread is that when my typo humdrum.sigh_strenght = 'high' was accepted and did not generate an error, it seemed to mean to me that I was violating my object's data encapsulation. It just seems to me that I should not be able to arbitrarily add new attributes from outside the class definition that created my object. That seems similar to having a class Dog, to which from outside the class' definition, I decide to add a new Dog attribute that all dogs in this class can now have a tail sticking out of their noses. I have no qualms about subclassing Dog with a MutantDog subclass, but adding new attributes from outside the class definition? That just does not seem right to at this point of my understanding. As in your function example, I am sure that I am missing something quite obvious, but I am just not seeing it now. Keep in mind, that I am just now this past week starting to study classes. All of my programming experience has been strictly procedural Other than dabbling in Tkinter at work.). I have no pre-experience with Java or C++, other than casual reading, so any preconceptions I have come from my procedural background ages ago in FORTRAN. > Other advantages of this way of doing things include that you aren't > forced to put all your initialisation code in a single, special place, > you can factor parts of it out into alternative methods: > > class X: >def __init__(self, x): >self.setup(x) >def setup(self, x): >process(x) >self.attribute = x > I have seen this before and agree that this is both useful and desirable. But I am comfortable with this because it is happening *inside* the class definition. > It also means that Python doesn't require a magic "undefined" value, > like Javascript has, or require declarations ahead of time, like static > languages such as Pascal and C require. I have come to enjoy this feature of Python as well! boB ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Why do I not get an error when I mistakenly type "humdrum.sigh_strenght" instead of the correct "humdrum.sigh_strength"?
On 22Jan2016 22:14, boB Stepp wrote: On Thu, Jan 21, 2016 at 4:57 AM, Steven D'Aprano wrote: Danny is correct. And it is a useful feature too. For instance, we can add attributes to functions: def spam(x, y): ... spam.extra_info = "whatever" A new thing that I did not suspect I could do. This bothers me for two reasons: 1) It does not seem right adding attributes to functions outside of its definition. Have you tried to do it from inside? Anyway, a function is just another object. What do you think it should be particularly special? 2) spam.extra_info appears to be global: spam.extra_info = "whatever" z = 'WOW!' def print_global_stuff(): print('z =', z) print('spam.extra_info =', spam.extra_info) No, "spam" is global. So you can name it anywhere in that module; therefore you can name anything inside it. Again, like any other object. print_global_stuff() z = WOW! spam.extra_info = whatever And I imagine I am being dense about something that is quite obvious to you: How is this a useful feature to have? What does it give me that is more useful than just saying something like: just_another_global variable = "whatever" spam.extra_info = "blah" snot = spam print(snot.extra_info) Consider if you passed "snot" (or "spam") to a function: def print_extra_info(obj): print(obj.extra_info) This is not something you could do with just_another_global_variable. Consider: this is information you want assicated with a specific object. Therefore it really _is_ an arribute of the object so that it can follow it around. And what bothered me about my original example that started this thread is that when my typo humdrum.sigh_strenght = 'high' was accepted and did not generate an error, it seemed to mean to me that I was violating my object's data encapsulation. It just seems to me that I should not be able to arbitrarily add new attributes from outside the class definition that created my object. That seems similar to having a class Dog, to which from outside the class' definition, I decide to add a new Dog attribute that all dogs in this class can now have a tail sticking out of their noses. I have no qualms about subclassing Dog with a MutantDog subclass, but adding new attributes from outside the class definition? That just does not seem right to at this point of my understanding. As in your function example, I am sure that I am missing something quite obvious, but I am just not seeing it now. All you're missing is realising that setting an attribute is not a special operation. To take an anecdote from elsewhere: UNIX was not designed to stop you from doing stupid things, because that would also stop you from doing clever things. - Doug Gwyn There's no need to prevent you setting "sigh_strenght". There probably is benefit in linting tools reporting to you about attributes which are set but apparently never used. Cheers, Cameron Simpson ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Why is the name "self" optional instead of mandatory?
On Thu, Jan 21, 2016 at 5:49 AM, Steven D'Aprano wrote: > On Wed, Jan 20, 2016 at 09:42:29PM -0600, boB Stepp wrote: > >> So I really only have one question: Why not make Python's >> *traditional* name, "self", mandatory? Why give the programmer this >> kind of choice? [OK, that was two questions.] > > Why bother making it mandatory? That just makes more work for the > compiler -- it has to decide that a function is inside a class, and > therefore apply a restriction to the first argument. Most of the time, > giving the programmer more freedom is less work. > > And what happens if you do this? > > class X: > pass > > def func(this): > print("instance %r called method" % this) > > X.method = func Am I understanding this correctly? It appears to me that you have successfully added a method to class X from outside of class X! If this is the case, then this clarifies some things I was wondering about in my other thread. > And what are we supposed to do with classmethods and staticmethods? They > shouldn't take a "self" argument at all, but they start off life as a > regular function, just like ordinary instance methods. > > And of course, there are Metaclasses. You might need a metaclass method > that needs to deal with all three levels of the hierarchy: the > metaclass, the class it creates, and the instance of that class. > > class Meta(type): > def metamethod(meta, cls, self): > ... I scanned the article that Danny gave a link to. I am not ready to go in depth into these concepts at this time, but I cannot help but wonder about the possibilities these concepts open up? At work I find myself writing Python to generate correct scripting language commands for the proprietary software I use at work. What if I could write a Python program which thoroughly captured the entire proprietary scripting language into a much easier to use interface? Their scripting language has an underlying OO structure that is not exposed to my prying eyes. But *if* I could create a class structure that was sufficiently similar to theirs that it seamlessly generated the correct messages that their OOP style uses, then things might be much easier for my projects. Hmm... I guess I am trying to wrap my mind around this incredible power and flexibility that Python provides. I thought I had asked a relatively harmless question. But it generated some strong responses! It seemed like "self" had a similar utility of use as "print" to me. After all, we can't redefine "print", can we? But now I realize that I can do exactly that if I so choose. That is both fascinating and scary! ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Why do I not get an error when I mistakenly type "humdrum.sigh_strenght" instead of the correct "humdrum.sigh_strength"?
On Fri, Jan 22, 2016 at 11:04 PM, Cameron Simpson wrote: > On 22Jan2016 22:14, boB Stepp wrote: [...] > Consider: this is information you want assicated with a specific object. > Therefore it really _is_ an arribute of the object so that it can follow it > around. > >> And what bothered me about my original example that started this >> thread is that when my typo >> >> humdrum.sigh_strenght = 'high' >> >> was accepted and did not generate an error, it seemed to mean to me >> that I was violating my object's data encapsulation. It just seems to >> me that I should not be able to arbitrarily add new attributes from >> outside the class definition that created my object. That seems >> similar to having a class Dog, to which from outside the class' >> definition, I decide to add a new Dog attribute that all dogs in this >> class can now have a tail sticking out of their noses. I have no >> qualms about subclassing Dog with a MutantDog subclass, but adding new >> attributes from outside the class definition? That just does not seem >> right to at this point of my understanding. As in your function >> example, I am sure that I am missing something quite obvious, but I am >> just not seeing it now. > > > All you're missing is realising that setting an attribute is not a special > operation. I guess no matter how new one is to OOP, one nevertheless brings one's preconceptions, however malformed, into the learning process. In my case, one of mine was that once a class is coded, any given instance of a class is forevermore responsible for managing its *internals*, so that any change in these would be managed by the object when one of its (meant to be) publicly available methods is called. In the case of attributes, I was thinking/expecting something like the following would have to be done: >>> class Dog(object): def __init__(self, name, breed): self.name = name self.breed = breed self.number_legs = 4 self.number_tails = 1 self.number_eyes = 2 self.attributes = { 'name': self.name, 'breed': self.breed, 'number of legs': self.number_legs, 'number of tails': self.number_tails, 'number of eyes': self.number_eyes} def add_attribute(self, new_attribute_name, new_attribute_value): self.new_attribute_name = new_attribute_name self.new_attribute_value = new_attribute_value self.attributes[self.new_attribute_name] = self.new_attribute_value def show_attributes(self): print("The object,", self.name, "has the following attributes:") for attribute_name, attribute_value in self.attributes.items(): print(attribute_name, "=", attribute_value) >>> our_dog = Dog('Copper', 'beagle') >>> our_dog.show_attributes() The object, Copper has the following attributes: number of tails = 1 number of legs = 4 breed = beagle name = Copper number of eyes = 2 >>> our_dog.add_attribute('unique marking', 'blue right eye') >>> our_dog.show_attributes() The object, Copper has the following attributes: number of legs = 4 breed = beagle unique marking = blue right eye number of tails = 1 name = Copper number of eyes = 2 I suspect there are probably better ways to do what I am trying to demonstrate [I am trying to use a dict to simulate adding new instance variables after the fact.], perhaps with built-in functions that I have not read about yet. But I hope my code illustrates my previous expectations. I guess I was expecting that access to an object's internals would be more strictly regulated. But, thinking about it, I already knew that even if name mangling is done for a method's name, it can still be directly accessed from outside of that object's class definition. But if I am understanding everyone's comments correctly, Python allows me write my classes in such a way, that public access to my object's internals is controlled, in the sense that Python has coding conventions that tell all of the quite intelligent, respectful, consenting adults that might use my code how I intend that code to be used. And that I, despite my intentions, must respect that users of my code may have very valid reasons for deviating from my intentions. Have I captured the Pythonic spirit of what everyone has been trying to tell me? Thanks for your patience, now and in the future, as I try to learn OOP in Python! Cheers! boB ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor