Re: Style question: Importing modules from packages - 'from' vs 'as'
On Fri, Dec 5, 2014 at 9:10 AM, Wolfgang Maier wrote: > which I read as there has been a stepwise transition between 2.5 and 2.7 so > that 2.7 now behaves like Python 3 even without the __future__ statement. > OTOH, I believe you, of course, if you're saying implicit relative imports > are working just fine in 2.7, but then how to interpret the "In Python 2.7 > the __future__ statement is not needed." above ? Hmm. To be honest, I'm not sure. The Python 2.7 __future__ module claims that absolute_import became standard in 3.0, not 2.7, which seems to conflict with what you're seeing. ChrisA -- https://mail.python.org/mailman/listinfo/python-list
Re: Style question: Importing modules from packages - 'from' vs 'as'
On 04.12.2014 22:30, Chris Angelico wrote: On Fri, Dec 5, 2014 at 7:56 AM, Wolfgang Maier wrote: On 04.12.2014 19:05, Chris Angelico wrote: With os.path it definitely is. With the actual code in question, it's a Python 2.7 project that mostly uses relative imports - inside package.module1 is "import module2" etc - and I was writing an external script that calls on one of the modules. What ? I'm usually thinking Python 3 not 2 and I'm never sure which Python 2.x has backported which feature of 3, but I thought implicit relative imports like you seem to describe are not working in 2.7 ? Hmm, I'm not sure, but certainly it does seem to work that way. Typing "import foo" from inside a package will import foo.py from the package directory. I haven't dug into the details of _why_, and if ever the project shifts to Python 3 (which I would like it to), we might have to change some of the import lines, but I'd still like to be able to reference "foo.bar" as meaning the "bar" top-level object in foo.py. I checked what the docs say about this and it is totally confusing (at least me): https://docs.python.org/3/howto/pyporting.html#from-future-import-absolute-import says: " from __future__ import absolute_import Implicit relative imports (e.g., importing spam.bacon from within spam.eggs with the statement import bacon) do not work in Python 3. This future statement moves away from that and allows the use of explicit relative imports (e.g., from . import bacon). In Python 2.5 you must use the __future__ statement to get to use explicit relative imports and prevent implicit ones. In Python 2.6 explicit relative imports are available without the statement, but you still want the __future__ statement to prevent implicit relative imports. In Python 2.7 the __future__ statement is not needed. In other words, unless you are only supporting Python 2.7 or a version earlier than Python 2.5, use this __future__ statement. " which I read as there has been a stepwise transition between 2.5 and 2.7 so that 2.7 now behaves like Python 3 even without the __future__ statement. OTOH, I believe you, of course, if you're saying implicit relative imports are working just fine in 2.7, but then how to interpret the "In Python 2.7 the __future__ statement is not needed." above ? Wolfgang -- https://mail.python.org/mailman/listinfo/python-list
Re: Style question: Importing modules from packages - 'from' vs 'as'
On Fri, Dec 5, 2014 at 7:56 AM, Wolfgang Maier wrote: > On 04.12.2014 19:05, Chris Angelico wrote: >> >> >> With os.path it definitely is. With the actual code in question, it's >> a Python 2.7 project that mostly uses relative imports - inside >> package.module1 is "import module2" etc - and I was writing an >> external script that calls on one of the modules. > > > What ? I'm usually thinking Python 3 not 2 and I'm never sure which Python > 2.x has backported which feature of 3, but I thought implicit relative > imports like you seem to describe are not working in 2.7 ? Hmm, I'm not sure, but certainly it does seem to work that way. Typing "import foo" from inside a package will import foo.py from the package directory. I haven't dug into the details of _why_, and if ever the project shifts to Python 3 (which I would like it to), we might have to change some of the import lines, but I'd still like to be able to reference "foo.bar" as meaning the "bar" top-level object in foo.py. ChrisA -- https://mail.python.org/mailman/listinfo/python-list
Re: Style question: Importing modules from packages - 'from' vs 'as'
On 04.12.2014 19:05, Chris Angelico wrote: With os.path it definitely is. With the actual code in question, it's a Python 2.7 project that mostly uses relative imports - inside package.module1 is "import module2" etc - and I was writing an external script that calls on one of the modules. What ? I'm usually thinking Python 3 not 2 and I'm never sure which Python 2.x has backported which feature of 3, but I thought implicit relative imports like you seem to describe are not working in 2.7 ? Wolfgang -- https://mail.python.org/mailman/listinfo/python-list
Re: Style question: Importing modules from packages - 'from' vs 'as'
On Fri, Dec 5, 2014 at 4:36 AM, Jean-Michel Pichavant wrote: > I know you specifically stated you didn't want to do this but > > import os > > os.path.isfile() > > is the best option imo, especially from the reader point of view ("Namespaces > are one honking great idea"). With os.path it definitely is. With the actual code in question, it's a Python 2.7 project that mostly uses relative imports - inside package.module1 is "import module2" etc - and I was writing an external script that calls on one of the modules. So it makes sense to reference it through the code the exact same way, as "module.blah" rather than "package.module.blah". ChrisA -- https://mail.python.org/mailman/listinfo/python-list
Re: Style question: Importing modules from packages - 'from' vs 'as'
On 12/03/2014 03:02 AM, Chris Angelico wrote: > > Throughout the code, I want to refer to "path.split()", > "path.isfile()", etc, without the "os." in front of them. I could do > either of these: > > import os.path as path > from os import path > > Which one would you recommend? Does it depend on context? I recommend the one with less typing. ;) -- ~Ethan~ signature.asc Description: OpenPGP digital signature -- https://mail.python.org/mailman/listinfo/python-list
Re: Style question: Importing modules from packages - 'from' vs 'as'
On 12/04/2014 09:36 AM, Jean-Michel Pichavant wrote: > > I know you specifically stated you didn't want to do this but > > import os > > os.path.isfile() > > is the best option imo, especially from the reader point of view ("Namespaces > are one honking great idea"). But, "Flat is better than nested" ! ;) -- ~Ethan~ signature.asc Description: OpenPGP digital signature -- https://mail.python.org/mailman/listinfo/python-list
Re: Style question: Importing modules from packages - 'from' vs 'as'
- Original Message - > From: "Chris Angelico" > To: python-list@python.org > Sent: Wednesday, 3 December, 2014 12:02:17 PM > Subject: Style question: Importing modules from packages - 'from' vs 'as' > > When importing a module from a subpackage, it's sometimes convenient > to refer to it throughout the code with a one-part name rather than > two. I'm going to use 'os.path' for the examples, but my actual > use-case is a custom package where the package name is, in the > application, quite superfluous. > > Throughout the code, I want to refer to "path.split()", > "path.isfile()", etc, without the "os." in front of them. I could do > either of these: > > import os.path as path > from os import path > > Which one would you recommend? Does it depend on context? > > An "as" import works only if it's a module in a package, where the > "from" import can also import other objects (you can't go "import > pprint.pprint as pprint"). I'm fairly sure that's an argument... on > one side or another. :) > > Thoughts? > > ChrisA > -- > https://mail.python.org/mailman/listinfo/python-list > I know you specifically stated you didn't want to do this but import os os.path.isfile() is the best option imo, especially from the reader point of view ("Namespaces are one honking great idea"). -- IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you. -- https://mail.python.org/mailman/listinfo/python-list
Re: Style question: Importing modules from packages - 'from' vs 'as'
On 12/03/2014 12:02 PM, Chris Angelico wrote: When importing a module from a subpackage, it's sometimes convenient to refer to it throughout the code with a one-part name rather than two. I'm going to use 'os.path' for the examples, but my actual use-case is a custom package where the package name is, in the application, quite superfluous. Throughout the code, I want to refer to "path.split()", "path.isfile()", etc, without the "os." in front of them. I could do either of these: import os.path as path from os import path Which one would you recommend? Does it depend on context? One argument not yet brought up by anyone else: if you ever wanted to make the module part of your own package and turn the import into a relative one, only the second, but not the first form lets you replace the package name with . : from . import path (while import .path is a SyntaxError, so you'd need a slightly more complicated rewrite). Wolfgang -- https://mail.python.org/mailman/listinfo/python-list
Re: Style question: Importing modules from packages - 'from' vs 'as'
On 12/3/2014 6:02 AM, Chris Angelico wrote: When importing a module from a subpackage, it's sometimes convenient to refer to it throughout the code with a one-part name rather than two. I'm going to use 'os.path' for the examples, but my actual use-case is a custom package where the package name is, in the application, quite superfluous. Throughout the code, I want to refer to "path.split()", "path.isfile()", etc, without the "os." in front of them. I could do either of these: import os.path as path from os import path Which one would you recommend? Does it depend on context? I confirmed that they do the same thing for submodules. >>> import os.path as pth >>> from os import path >>> pth >>> path >>> id(pth) 4319096 >>> id(path) 4319096 I and most code I have seen uses "from tkinter import ttk". An "as" import works only if it's a module in a package, where the "from" import can also import other objects (you can't go "import pprint.pprint as pprint"). I'm fairly sure that's an argument... on one side or another. "import tkinter.ttk as ttk" makes it clear that ttk is a module rather than, say, a class. That might make things easier for the reader. On the other hand, duplication implies that there might be a real renaming, so having to compare to see that there is not, is extra work. from idlelib import EditorWindow import idlelib.EditorWindow as EditorWindow -- Terry Jan Reedy -- https://mail.python.org/mailman/listinfo/python-list
Re: Style question: Importing modules from packages - 'from' vs 'as'
On Dec 3, 2014 4:34 AM, "Chris Angelico" wrote: > > On Wed, Dec 3, 2014 at 10:27 PM, Peter Otten <__pete...@web.de> wrote: > > Don't repeat yourself, so > > > > from os import path > > > > always. On the other hand I have never thought about actual renames, e. g. > > > > from os import path as stdpath > > > > versus > > > > import os.path as stdpath > > > > I think I'd use the latter as it looks simpler. > > Thanks, Peter and Tim. Keeping DRY is worth doing (the more so as it's > raining as I type this...), and I won't be renaming in this, so the > from-import wins - but as Tim says, it's a close race. To offer a counterpoint, the from import is also less explicit. With "import os.path as path", path must be a module. With the from import, path could be either a module or just any attribute of the os module. My preference when importing modules is to use the fully qualified name -- os.path, not path. If I do a submodule import, I'm probably assigning a local name anyway, so I still prefer the "import as" over the "from import as". -- https://mail.python.org/mailman/listinfo/python-list
Re: Style question: Importing modules from packages - 'from' vs 'as'
On Wed, Dec 3, 2014 at 10:27 PM, Peter Otten <__pete...@web.de> wrote: > Don't repeat yourself, so > > from os import path > > always. On the other hand I have never thought about actual renames, e. g. > > from os import path as stdpath > > versus > > import os.path as stdpath > > I think I'd use the latter as it looks simpler. Thanks, Peter and Tim. Keeping DRY is worth doing (the more so as it's raining as I type this...), and I won't be renaming in this, so the from-import wins - but as Tim says, it's a close race. I do like the turn-around times on this list. Although, of course, it's entirely possible there'll be a week's worth of posts coming when someone hits on a controversial subaspect of the question somewhere; any volunteers? :) :) ChrisA -- https://mail.python.org/mailman/listinfo/python-list
Re: Style question: Importing modules from packages - 'from' vs 'as'
Chris Angelico wrote: > When importing a module from a subpackage, it's sometimes convenient > to refer to it throughout the code with a one-part name rather than > two. I'm going to use 'os.path' for the examples, but my actual > use-case is a custom package where the package name is, in the > application, quite superfluous. > > Throughout the code, I want to refer to "path.split()", > "path.isfile()", etc, without the "os." in front of them. I could do > either of these: > > import os.path as path > from os import path > > Which one would you recommend? Does it depend on context? Don't repeat yourself, so from os import path always. On the other hand I have never thought about actual renames, e. g. from os import path as stdpath versus import os.path as stdpath I think I'd use the latter as it looks simpler. > An "as" import works only if it's a module in a package, where the > "from" import can also import other objects (you can't go "import > pprint.pprint as pprint"). I'm fairly sure that's an argument... on > one side or another. :) In theory you could sometimes catch erroneous assumptions about pprint.pprint's type. But I don't care. -- https://mail.python.org/mailman/listinfo/python-list
Re: Style question: Importing modules from packages - 'from' vs 'as'
On 3 December 2014 at 22:02, Chris Angelico wrote: > > import os.path as path > from os import path > Bah - deleted the list and sent directly to Chris ... time to go to bed. The advantage of the former is that if you want to use a different name, it's a smaller change. But the disadvantage of the former is that if you *don't* want to rename, it violates DRY (don't repeat yourself). The difference is so marginal that I'd leave it to personal preference, and wouldn't pull someone up for either in a code review. Tim Delaney -- https://mail.python.org/mailman/listinfo/python-list
Re: Style question -- plural of class name?
On 2013-05-08 21:20, Roy Smith wrote: FooEntry is a class. How would you describe a list of these in a docstring? "A list of FooEntries" "A list of FooEntrys" "A list of FooEntry's" "A list of FooEntry instances" The first one certainly sounds the best, but it seems wierd to change the spelling of the class name to make it plural. I'm using services like Github more and more to talk about code, so I have taken to adopting its inline markup for `code` when referring to identifiers. Thus, I will often write A list of `FooEntry`s But I don't mind A list of FooEntries Hopefully there isn't also a `FooEntries` class. -- Robert Kern "I have come to believe that the whole world is an enigma, a harmless enigma that is made terrible by our own mad attempt to interpret it as though it had an underlying truth." -- Umberto Eco -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question -- plural of class name?
On 2013-05-09, Jussi Piitulainen wrote: > Neil Cerutti writes: >> If there's no chance for confusion between a class named >> FooEntry and another named FooEntries, then the first attempt >> seems best. Pluralize a class name by following the usual >> rules, e.g., "strings" and "ints". > > Like "strings" would be "foo entries". Which might work well. > > (I mean, isn't the class named "str"?) Yeah, that's not such a good Python example. I used it to replace "chars" and felt good at the time. ;) -- Neil Cerutti -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question -- plural of class name?
Neil Cerutti writes: > If there's no chance for confusion between a class named FooEntry > and another named FooEntries, then the first attempt seems best. > Pluralize a class name by following the usual rules, e.g., > "strings" and "ints". Like "strings" would be "foo entries". Which might work well. (I mean, isn't the class named "str"?) -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question -- plural of class name?
On 2013-05-08, Denis McMahon wrote: > On Wed, 08 May 2013 16:20:48 -0400, Roy Smith wrote: > >> FooEntry is a class. How would you describe a list of these in a >> docstring? >> >> "A list of FooEntries" >> >> "A list of FooEntrys" >> >> "A list of FooEntry's" >> >> "A list of FooEntry instances" >> >> The first one certainly sounds the best, but it seems wierd to change >> the spelling of the class name to make it plural. > > I wouldn't use an apostrophe for pluralisation. If there's no chance for confusion between a class named FooEntry and another named FooEntries, then the first attempt seems best. Pluralize a class name by following the usual rules, e.g., "strings" and "ints". -- Neil Cerutti -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question -- plural of class name?
Am 09.05.2013 02:38 schrieb Colin J. Williams: On 08/05/2013 4:20 PM, Roy Smith wrote: "A list of FooEntry's" +1 Go back to school. Both of you... That is NOT the way to build a plural form... Thomas -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question -- plural of class name?
On 09May2013 00:02, Steven D'Aprano wrote: | On Wed, 08 May 2013 16:20:48 -0400, Roy Smith wrote: | > "A list of FooEntry's" | | "Here come's an S! Quick, jam on an apostrophe!" | | This is called the grocer's apostrophe, and is universally held in | contempt no matter what variant of English you write in. Don't do this. | | The only acceptable use of an apostrophe to make a plural is if the thing | being pluralised is a single letter. E.g. one a, two a's. Frankly, not even then for me. I spell that "one A, two As". | > "A list of FooEntry instances" | | This is also acceptable, although a little wordy. Do you write "a list of | strings" or "a list of str instances"? How about "a FooEntry list"? -- Cameron Simpson Yes Officer, yes Officer, I will Officer. Thank you. -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question -- plural of class name?
On 08/05/2013 4:20 PM, Roy Smith wrote: FooEntry is a class. How would you describe a list of these in a docstring? "A list of FooEntries" 0 "A list of FooEntrys" -1 "A list of FooEntry's" +1 "A list of FooEntry instances" No FooEntry is specified as a class. The first one certainly sounds the best, but it seems wierd to change the spelling of the class name to make it plural. Colin W. -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question -- plural of class name?
On Wed, 08 May 2013 15:33:07 -0500, Skip Montanaro wrote: > This one: > >> "A list of FooEntry instances" > > Besides the obvious spelling issues in the others, it's not immediately > clear if the list contains just FooEntry instances, FooEntry classes > (perhaps subclasses) or a mix of the two. #4 makes it clear. I don't think this is a real issue. There isn't normally any ambiguity between instances and subclasses. When you read "a list of ints", do you assume that the list looks like [int, MyInt, AnotherInt, FooInt] or do you expect it to look like [2, 7, 6, 1]? The normal interpretation of "one or more Foo" is that we're talking about Foo *instances*, not subclasses of Foo. If that is not that case, then the onus is on the author of the documentation to make it clear that they are talking about subclasses. -- Steven -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question -- plural of class name?
On Thu, May 9, 2013 at 6:20 AM, Roy Smith wrote: > "A list of FooEntry's" Only if you put another apostrophe in: "A list of 'FooEntry's" But the delimited style is almost never of use. I'd go for this only if there were some sort of automated markup being applied - if the word FooEntry were turned into a hyperlink or something. ChrisA -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question -- plural of class name?
On Wed, 08 May 2013 16:20:48 -0400, Roy Smith wrote: > FooEntry is a class. How would you describe a list of these in a > docstring? Which language are you writing your docstrings in? Obey the normal rules of spelling, grammar and punctuation for your language, which I assume is English. > "A list of FooEntries" Perfectly acceptable. > "A list of FooEntrys" There is no standard variant or dialect of English (British English, American English, etc.) that pluralises Entry as Entrys, so that would be "absolutely not". > "A list of FooEntry's" "Here come's an S! Quick, jam on an apostrophe!" This is called the grocer's apostrophe, and is universally held in contempt no matter what variant of English you write in. Don't do this. The only acceptable use of an apostrophe to make a plural is if the thing being pluralised is a single letter. E.g. one a, two a's. > "A list of FooEntry instances" This is also acceptable, although a little wordy. Do you write "a list of strings" or "a list of str instances"? > The first one certainly sounds the best, but it seems wierd to change > the spelling of the class name to make it plural. No weirder (note spelling) than changing any other noun. Whether you change "int" to "ints" or FooEntry" to "FooEntries", you're still changing it. That's how you make it plural. -- Steven -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question -- plural of class name?
On Wed, 08 May 2013 16:20:48 -0400, Roy Smith wrote: > FooEntry is a class. How would you describe a list of these in a > docstring? > > "A list of FooEntries" > > "A list of FooEntrys" > > "A list of FooEntry's" > > "A list of FooEntry instances" > > The first one certainly sounds the best, but it seems wierd to change > the spelling of the class name to make it plural. I wouldn't use an apostrophe for pluralisation. The Normal pluralisation of FooEntry would be FooEntries. Who are you expecting to read the docstring? English majors, grammar nazis, wikipedia editors, programmers, or all 4? -- Denis McMahon, denismfmcma...@gmail.com -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question -- plural of class name?
On Wed, May 8, 2013 at 2:37 PM, John Downs wrote: > On Wed, May 8, 2013 at 4:20 PM, Roy Smith wrote: >> >> FooEntry is a class. How would you describe a list of these in a >> docstring? >> >> "A list of FooEntries" >> >> "A list of FooEntrys" >> >> "A list of FooEntry's" >> >> "A list of FooEntry instances" >> >> The first one certainly sounds the best, but it seems wierd to change >> the spelling of the class name to make it plural. >> -- >> http://mail.python.org/mailman/listinfo/python-list > > > How about: "A list with elements of type FooEntry"? I also like the last > one: "A list of FooEntry instances". list *ducks* -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question -- plural of class name?
On Wed, May 8, 2013 at 4:20 PM, Roy Smith wrote: > FooEntry is a class. How would you describe a list of these in a > docstring? > > "A list of FooEntries" > > "A list of FooEntrys" > > "A list of FooEntry's" > > "A list of FooEntry instances" > > The first one certainly sounds the best, but it seems wierd to change > the spelling of the class name to make it plural. > -- > http://mail.python.org/mailman/listinfo/python-list > How about: "A list with elements of type FooEntry"? I also like the last one: "A list of FooEntry instances". -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question -- plural of class name?
This one: > "A list of FooEntry instances" Besides the obvious spelling issues in the others, it's not immediately clear if the list contains just FooEntry instances, FooEntry classes (perhaps subclasses) or a mix of the two. #4 makes it clear. Skip -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question: metaclass self vs cls?
On Tue, 17 Jul 2012 05:23:22 -0700, Michele Simionato wrote: > The standard is to use `cls`. In the __new__ method you can use `mcl` or > `meta`. Thanks to everyone who answered. I think I will stick with "meta" and "cls". -- Steven -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question: metaclass self vs cls?
On Tue, Jul 17, 2012 at 12:10 AM, alex23 wrote: > On Jul 17, 1:29 am, Steven D'Aprano +comp.lang.pyt...@pearwood.info> wrote: >> Here's a style question for you: in a metaclass, what should I call the >> instance parameter of methods, "cls" or "self"? > > Maybe portmanteu it as "clasself"? :) What is this, 1st edition D&D? Elf is a race, not a class. -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question: metaclass self vs cls?
On Tue, Jul 17, 2012 at 6:23 AM, Michele Simionato wrote: > The standard is to use `cls`. In the __new__ method you can use `mcl` or > `meta`. I've also seen `mcs` a fair amount. -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question: metaclass self vs cls?
The standard is to use `cls`. In the __new__ method you can use `mcl` or `meta`. -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question: metaclass self vs cls?
On 7/16/2012 11:29 AM, Steven D'Aprano wrote: Here's a style question for you: in a metaclass, what should I call the instance parameter of methods, "cls" or "self"? class ExampleMeta(type): def method(self, *args): ... I'm not quite sure if that feels right. On the one hand, self is the ExampleMeta instance alright... but on the other, self is actually a class, so I feel I want to call it "cls" rather than "self", which makes it more obvious that you're looking at a metaclass. I have never seriously written a metaclass, but as a reader I would prefer 'cls'. On the third-hand, it may be confusing that the argument is called "cls" but not decorated with classdecorator. To me, that reinforces 'looking as a metaclass'. An @classmethod in a class is a class method specific to the particular class. A method in a metaclass is a method common to all classes of the metaclass. They could be written differently, yet calling the first param 'cls' either way seems reasonable. I'm very slightly leaning towards writing metaclasses like this: class ExampleMeta(type): def __new__(meta, *args): ... def method(cls, *args): ... class Example(metaclass=ExampleMeta): def another_method(self): ... What do others do? Not too many people write real metaclasses. Python lets you chose. Have you looked at the C code of type? (Not that you are bound by it.) -- Terry Jan Reedy -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question (Poll)
On Wednesday, 14 March 2012 21:16:05 UTC, Terry Reedy wrote: > On 3/14/2012 4:49 PM, Arnaud Delobelle wrote: > > On 14 March 2012 20:37, Croepha wrote: > >> Which is preferred: > >> > >> for value in list: > >> if not value is another_value: > >> value.do_something() > >> break > > Do you really mean 'is' or '=='? > > If you mean x is not y, write it that way. > 'not x is y' can be misread and misunderstood, depending on whether > the 'is' is true or not. > > >>> not 1 is 1 > False > >>> not (1 is 1) > False > >>> (not 1) is 1 > False > > Does not matter how read. > > >>> not (1 is 0) > True > >>> (not 1) is 0 > False > >>> not 1 is 0 > True > > Does matter how read. > > >> if list and not list[0] is another_value: > >> list[0].do_something() > > Or > try: >value = mylist[0] >if value is not another_value: value.dosomething > except IndexError: >pass > > I would not do this in this case of index 0, but if the index were a > complicated expression or expensive function call, making 'if list' an > inadequate test, I might. > > > Hard to say, since they don't do the same thing :) > > > > I suspect you meant: > > > > for value in list: > > if not value is another_value: > > value.do_something() > > break > > > > I always feel uncomfortable with this because it's misleading: a loop > > that never loops. > > I agree. Please do not do this in public ;-). > > -- > Terry Jan Reedy I'm not sure it's efficient or even if I like it, but it avoids try/except and the use of a for loop. if next( iter(mylist), object() ) is not another_value: # ... Just my 2p, Jon. -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question (Poll)
On Thu, Mar 15, 2012 at 7:37 AM, Croepha wrote: > Which is preferred: > > for value in list: > if not value is another_value: > value.do_something() > break > > --or-- > > if list and not list[0] is another_value: > list[0].do_something() > > Comments are welcome, Thanks General principle: Make the code look like what it's doing. I don't mean text art and making code in the shape of pi that prints the digits of pi (although that can be awesome too), but more that a loop should not be used when you don't intend for it to loop. Consider the For-Case Paradigm[1] and the amazing confusion value that it can offer. A loop needn't execute more than once (it needn't even execute the first time), but it should at least have the _potential_ to execute the same code multiple times, otherwise it's hardly a loop. I had a particularly nasty example of a loop-that-wasn't-a-loop at work a while ago; it was PHP, not Python, so I won't share it here, but it had a do-while loop and an insidious bug in it. Very tricky. ChrisA [1] http://thedailywtf.com/Articles/The_FOR-CASE_paradigm.aspx -- http://mail.python.org/mailman/listinfo/python-list
RE: Style question (Poll)
> > Only use 'is' if you are looking for objects like True, > > False, None or something that MUST be exactly the same object. > > I've rarely seen valid uses of 'is True' or 'is False'. It can be useful when you think something might be None or False. Although, I suppose you could always just use 'is None' instead. >>> 1 == True True >>> 1 is True False >>> 0 == False True >>> 0 is False False Granted, the above example is a pretty facetious case; not sure I can come up with a reasonably real world use case. Ramit Ramit Prasad | JPMorgan Chase Investment Bank | Currencies Technology 712 Main Street | Houston, TX 77002 work phone: 713 - 216 - 5423 -- This email is confidential and subject to important disclaimers and conditions including on offers for the purchase or sale of securities, accuracy and completeness of information, viruses, confidentiality, legal privilege, and legal entity disclaimers, available at http://www.jpmorgan.com/pages/disclosures/email. -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question (Poll)
On 14 March 2012 22:15, Prasad, Ramit wrote: > Only use 'is' if you are looking for objects like True, > False, None or something that MUST be exactly the same object. I've rarely seen valid uses of 'is True' or 'is False'. -- Arnaud -- http://mail.python.org/mailman/listinfo/python-list
RE: Style question (Poll)
> >> Which is preferred: > >> > >> for value in list: > >> if not value is another_value: > >> value.do_something() > >> break > > Do you really mean 'is' or '=='? Let me expound on how 'is' and '==' are very different. It may work for some comparisons but often not for others. Certain examples work because of the Python implementation. >>> c = 1 >>> d = 1 >>> c is d # This only works because CPython caches small values. True >>> c == d True >>> a = 10 >>> b = 10 >>> a is b False >>> a == b True >>> 10 is 10 True '10 is 10' works because the interpreter caches the number because it is on the same line. Only use 'is' if you are looking for objects like True, False, None or something that MUST be exactly the same object. In general, use '=='. Ramit Ramit Prasad | JPMorgan Chase Investment Bank | Currencies Technology 712 Main Street | Houston, TX 77002 work phone: 713 - 216 - 5423 -- This email is confidential and subject to important disclaimers and conditions including on offers for the purchase or sale of securities, accuracy and completeness of information, viruses, confidentiality, legal privilege, and legal entity disclaimers, available at http://www.jpmorgan.com/pages/disclosures/email. -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question (Poll)
On 3/14/2012 4:49 PM, Arnaud Delobelle wrote: On 14 March 2012 20:37, Croepha wrote: Which is preferred: for value in list: if not value is another_value: value.do_something() break Do you really mean 'is' or '=='? If you mean x is not y, write it that way. 'not x is y' can be misread and misunderstood, depending on whether the 'is' is true or not. >>> not 1 is 1 False >>> not (1 is 1) False >>> (not 1) is 1 False Does not matter how read. >>> not (1 is 0) True >>> (not 1) is 0 False >>> not 1 is 0 True Does matter how read. if list and not list[0] is another_value: list[0].do_something() Or try: value = mylist[0] if value is not another_value: value.dosomething except IndexError: pass I would not do this in this case of index 0, but if the index were a complicated expression or expensive function call, making 'if list' an inadequate test, I might. Hard to say, since they don't do the same thing :) I suspect you meant: for value in list: if not value is another_value: value.do_something() break I always feel uncomfortable with this because it's misleading: a loop that never loops. I agree. Please do not do this in public ;-). -- Terry Jan Reedy -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question (Poll)
On 14 March 2012 20:37, Croepha wrote: > Which is preferred: > > for value in list: > if not value is another_value: > value.do_something() > break > > --or-- > > if list and not list[0] is another_value: > list[0].do_something() Hard to say, since they don't do the same thing :) I suspect you meant: for value in list: if not value is another_value: value.do_something() break I always feel uncomfortable with this because it's misleading: a loop that never loops. -- Arnaud -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question: Nicknames for deeply nested objects
Gerald Britton wrote: Nope. it's nothing to do with imports. It's about objects passed to methods at run time. Complicated objects with many levels. Not about modules at all. Who is providing these objects ? - Your code ? => as said before, you can fix your design with a proper object model - 3rd party libraries ? => I'd be curious to know which one, because they usually do a good job providing a clean minimal public interface. However, do not redesign anything to get only shorter names. You can easily live with that, the way you're doing it is up to you and suggestions have been given. But keep in mind that you should'nt have got nested names that long in the first pace, no matter how complicated the internal implementation. JM -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question: Nicknames for deeply nested objects
Gerald Britton wrote: however, considering what "import a.module.that.is.quite.nested as myModule" Won't work since I get the objects at run time myModule = __import__('whatever.module.imported.at.run.time', globals(), locals(), [], -1) See http://docs.python.org/library/functions.html#__import__ JM -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question: Nicknames for deeply nested objects
Gerald Britton wrote: Hi all, Today I was thinking about a problem I often encounter. [snip] 1. You need to call this thing many times with different arguments, so you wind up with: x = some.deeply.nested.object.method(some.other.deeply.nested.object.value1) y = some.deeply.nested.object.method(some.other.deeply.nested.object.value2) z = some.deeply.nested.object.method(some.other.deeply.nested.object.value3) [snip] -- Gerald Britton This is not solved by style but by design. You simply don't use too much nested objects. That's a sign of something wrong in your overall object model. Since I do not encounter this problem as often as you are, I guess it is a matter of habbits. however, considering what "import a.module.that.is.quite.nested as myModule" is doing, I guess using a local variable to store your nested method is just fine. JM -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question: Nicknames for deeply nested objects
On 1/30/11 1:13 PM, rantingrick wrote: > On Jan 30, 12:53 pm, Stephen Hansen wrote: >> OH MY GOD. How can someone be expected to understand what a function does! > > Yes, and also how decorators word and generators work, and ... > >> Be serious! You can't expect that of them. > > I don't. I don't expect anyone to write 10 lines of obfuscation code > when just two will suffice. Maybe you should join the perl group as > they would proud! Riiight. "suffice" doesn't mean what you think it means. Generally, if something suffices -- it actually, you know, ... works. My four lines of setup can get put into a library and treated as a recipe if they don't want to get into understanding generators or decorators: then its two lines to use, and those two lines are exactly like your two lines except for two little details: 1. They add a function call to the syntax. 2. They actually work. The OP doesn't have to understand decorators or generators if he doesn't want to: though I encourage him to do so, as they are beautiful and elegant tools that can very clearly and concisely help solve a lot of problems. Now, me? I wouldn't use the recipe, as I originally said in my response. I'd just use a local variable. But the OP didn't like that, and he wanted some indenting and whitespace to clearly demarcate where he intended to use the local. So I gave him a way to do that. You gave him... uh, what was it again? Oh, right. Nothing. As usual. -- Stephen Hansen ... Also: Ixokai ... Mail: me+list/python (AT) ixokai (DOT) io ... Blog: http://meh.ixokai.io/ signature.asc Description: OpenPGP digital signature -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question: Nicknames for deeply nested objects
On Sun, 30 Jan 2011 12:51:20 -0500, Gerald Britton wrote: > Hi all, > > Today I was thinking about a problem I often encounter. Say that I have > (seems I often do!) a deeply nested object, by which I mean object > within object with object, etc. > > For example: > > x = > some.deeply.nested.object.method (some.other.deeply.nested.object.value) > > Well, that's extreme but I've worked with code approaching that level of > nested-ness. Then you're probably living in a state of sin, programming-wise, and you should stop doing that! You are violating the Law of Demeter. One dot, good. Two, acceptable. Three is a code smell. Four is a code reek. The Law of Demeter (more of a guideline than a law, really) says: If you want to get your dog to walk, call the dog. Don't talk to its legs, it confuses the dog and doesn't get it anywhere. http://en.wikipedia.org/wiki/Law_of_Demeter Another analogy: if you have to pay the paperboy for delivering the newspaper, you don't let him reach into your pocket, take out your wallet, open the wallet, take out whatever money he feels like, and put the wallet back. http://www.ccs.neu.edu/research/demeter/demeter-method/LawOfDemeter/paper- boy/demeter.pdf Despite my comment above, the Law of Demeter is not *really* a dot- counting exercise, although that's a handy short-cut for detecting potential problems. It can also apply to other data structures. If you've every seen C or Pascal code where you have a pointer to a pointer to a pointer to a pointer to a pointer to a pointer to some data, you've seen a violation. Consider your example: some.other.deeply.nested.object.value This is very tightly coupled code: the caller, who knows about the object `some`, needs to know the internal details of not just `some` but also `other`, `deeply`, `nested`, and `object`. As a basic principle, this is poor design! Which would you rather deal with? car.start() car.ignition.turn(key).connect(car.starter(battery), car.spark_plug) In particular, using temporary variables merely disguises the problem: temp = some.other temp = temp.deeply.nested x = temp.object.value Even though you never use more than two dots, you still have tight coupling. The point of Demeter is not to save dots (they're a renewable resource) but to reduce tight coupling. -- Steven -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question: Nicknames for deeply nested objects
> > I don't. I don't expect anyone to write 10 lines of obfuscation code > when just two will suffice. Maybe you should join the perl group as > they would proud! But Stephen's 10 lines of somewhat obscure code actually works, and your two lines of code doesn't. I know which one I would prefer. -- Jerry -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question: Nicknames for deeply nested objects
On Jan 30, 12:53 pm, Stephen Hansen wrote: > On 1/30/11 10:35 AM, rantingrick wrote: > > > Well congratulations Stephen, you win the obfuscation prize of the > > year! > > Yes, > > On 1/30/11 10:09 AM, rantingrick wrote: > > > Here is how a pythonic local block would look > > > with this as localvar: > > localvar.do_something() > > verses > > with my(this) as localvar: > localvar.do_something() > > Is dreadfully more, er, obfuscated. Absolutely! > I mean someone would have to know what the 'my' function does to > understand what's going on! Yes, and also how decorators word and generators work, and ... > OH MY GOD. How can someone be expected to understand what a function does! Yes, and also how decorators word and generators work, and ... > Be serious! You can't expect that of them. I don't. I don't expect anyone to write 10 lines of obfuscation code when just two will suffice. Maybe you should join the perl group as they would proud! -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question: Nicknames for deeply nested objects
On 30/01/2011 17:51, Gerald Britton wrote: Hi all, Today I was thinking about a problem I often encounter. Say that I have (seems I often do!) a deeply nested object, by which I mean object within object with object, etc. For example: x = some.deeply.nested.object.method(some.other.deeply.nested.object.value) Well, that's extreme but I've worked with code approaching that level of nested-ness. Now, consider two scenarios: 1. You need to call this thing many times with different arguments, so you wind up with: x = some.deeply.nested.object.method(some.other.deeply.nested.object.value1) y = some.deeply.nested.object.method(some.other.deeply.nested.object.value2) z = some.deeply.nested.object.method(some.other.deeply.nested.object.value3) Neither. You should tell. Don't ask if you can avoid it. Compare... queen.getButter() and queen.dairymaid.alderney.getButter() see http://www.timelessteacherstuff.com/readerstheater/KingsBreakfast.pdf king doesn't care where or how the butter is brought. Neither should your code! What are you doing with value1, value2 and value3 when you have them anyway? Stuffing them 3 levels deep into something else? Stop writing procedural code, and write object oriented code instead! If you you make some tell deeply.nested.object about other.deeply.nested.object it can fetch its own values, but it might be better to have some tell other.deeply.nested.object about deeply.nested.object to it can issue the correct commands. Then you tell some to do Somthing by writing some.takeMeaningfullAction() and it all happens "under the covers". Regards Ian -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question: Nicknames for deeply nested objects
On 1/30/11 10:35 AM, rantingrick wrote: > Well congratulations Stephen, you win the obfuscation prize of the > year! Yes, On 1/30/11 10:09 AM, rantingrick wrote: > Here is how a pythonic local block would look > > with this as localvar: > localvar.do_something() verses with my(this) as localvar: localvar.do_something() Is dreadfully more, er, obfuscated. I mean someone would have to know what the 'my' function does to understand what's going on! OH MY GOD. How can someone be expected to understand what a function does! Be serious! You can't expect that of them. -- Stephen Hansen ... Also: Ixokai ... Mail: me+list/python (AT) ixokai (DOT) io ... Blog: http://meh.ixokai.io/ signature.asc Description: OpenPGP digital signature -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question: Nicknames for deeply nested objects
On Jan 30, 12:23 pm, Stephen Hansen wrote: > --- start > from contextlib import contextmanager > > class Item(object): pass > > deeply = Item() > deeply.nested = Item() > deeply.nested.thing = Item() > > @contextmanager > def my(thing): > yield thing > > with my(deeply.nested.thing) as o: > o.hello = 1 > > print deeply.nested.thing.hello > --- end Well congratulations Stephen, you win the obfuscation prize of the year! -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question: Nicknames for deeply nested objects
On 1/30/11 9:51 AM, Gerald Britton wrote: > 1. If you had to choose between approaches 1 and 2, which one would > you go for, and why? Neither. Ideally, I'd tweak the API around so the deeply nested structure isn't something I need to access regularly. But! If you can't do that, I'd do something like: --- start from contextlib import contextmanager class Item(object): pass deeply = Item() deeply.nested = Item() deeply.nested.thing = Item() @contextmanager def my(thing): yield thing with my(deeply.nested.thing) as o: o.hello = 1 print deeply.nested.thing.hello --- end That's a dummy context-manager which basically does nothing: it just "abuses" the context manager protocol to basically make a local variable and indent its usage. Its really just a run-around and slightly less efficient to do: >_o = some.deeply.nested.object >_o.method(_o.value) But with the whitespace added on. Personally, I'd usually just make a local variable and skip any tricks. -- Stephen Hansen ... Also: Ixokai ... Mail: me+list/python (AT) ixokai (DOT) io ... Blog: http://meh.ixokai.io/ signature.asc Description: OpenPGP digital signature -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question: Nicknames for deeply nested objects
In article , Gerald Britton wrote: > 1. You need to call this thing many times with different arguments, so > you wind up with: > > x = > some.deeply.nested.object.method(some.other.deeply.nested.object.value1) > y = > some.deeply.nested.object.method(some.other.deeply.nested.object.value2) > z = > some.deeply.nested.object.method(some.other.deeply.nested.object.value3) I would probably turn that into: object = some.deeply.nested.object object.method(object.value1) object.method(object.value2) object.method(object.value3) i.e. make the temporary variable have the exact same name as the last component of the deeply nested thing you're trying to refactor. If the scope of use is small and the meaning is obvious from context, sometimes I'll shorten the name, i.e. obj = some.deeply.nested.object or even o = some.deeply.nested.object but I tend to avoid doing that. I'd rather be a little more verbose in preference to being a little more cryptic. -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question: Nicknames for deeply nested objects
On Jan 30, 11:51 am, Gerald Britton wrote: [...] > that I might confuse with the first. To make it look better I might do this: > > _o = some.deeply.nested.object > _o.method(_o.value) > > which is fine, I suppose. It is very fine. And you "supposed" correctly! > Then, putting on my company hat, I remembered that, from VBA, you could do > this: > > with some.deeply.nested.object > .method(.value) > end with > > I like the structure of this, since the subordinate block can be > indented, which makes it stand out. Also, it avoids temporary > variables. Yes it is a good idea! Well forgetting the horrendous VBA syntax this is. I brought this up many moons back as a feature request: Local Blocks. Here is how a pythonic local block would look with this as localvar: localvar.do_something() > So, I was thinking of how to get close to this in Python. I came up > with two approaches: > > 1. > > _o = some.deeply.nested.object > if 1: > _o.method(_o.value) bad idea! > 2. > > for _o in [some.deeply.nested.object]: > _o.method(_o.value) even worse idea! > I have a couple of questions: > > 1. If you had to choose between approaches 1 and 2, which one would > you go for, and why? neither! Stick with the original. -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question for conditional execution
On Nov 25, 7:43 am, Paul Rubin wrote: > Gerald Britton writes: > > if v: > > f() > > > I might, however, think more in a functional-programming direction. > > Then I might write: > > > v and f() > > Python has conditional expressions. The above would be: > > f() if v else None > > using "and" is bug-prone. Using 'and' is indeed bug-prone when used in combination with 'or' to achieve a ternary conditional op, as was done the pre PEP308 days, eg "val = cond and a or b" because of the possibility that 'a' was itself not true, (thus requiring the ugly 'val = (cond and [a] or [b])[0]'). But no such bug could occur with this particular idiom. What could possibly go wrong here? :) That being said, I agree with previous posters that "if cond : fn()" wins in terms of readability. -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question for conditional execution
Gerald Britton writes: > if v: > f() > > I might, however, think more in a functional-programming direction. > Then I might write: > > v and f() Python has conditional expressions. The above would be: f() if v else None using "and" is bug-prone. -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question for conditional execution
Gerald Britton writes: > Writing in Python gives me the luxury of choosing different paradigms > for similar operations. Lately I've been thinking about a minor > detail that peaked my interest and am curious what others think: > > Say that I have some function "f" that I will execute if some variable > "v" evaluates true. Using a classical procedural approach, I might > write: > > if v: > f() > > I might, however, think more in a functional-programming direction. > Then I might write: > > v and f() > > Interestingly, this second expression compiles smaller (though only by > a little) in both Python 2.6 and 3.1, which I currently have > installed. If I had thousands of such expressions, I could boast > about a measurable difference but practically speaking, it is not > significant. > > What I _am_ interested in, however, is feedback from a style perspective. > > What do the rest of you think about this? > > Have you used the second approach and, if so, what was your motivation? > > Is there a good/bad reason to choose one over the other? I would use the if: form every time but it's interesting that the "JUMP_FORWARD 0" instruction below doesn't get optimised away. If it did, both forms would be the same compiled lengths. >>> def g(): ... if v: f() ... >>> dis.dis(g2) 2 0 LOAD_GLOBAL 0 (v) 3 POP_JUMP_IF_FALSE 16 6 LOAD_GLOBAL 1 (f) 9 CALL_FUNCTION0 12 POP_TOP 13 JUMP_FORWARD 0 (to 16) >> 16 LOAD_CONST 0 (None) 19 RETURN_VALUE -- Arnaud -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question for conditional execution
Both paradigms are in the bash shell. Using a test switch (like -x for executiable) mixed with an && or ||. Example: [-x /usr/bin/firefox ] || exit I think it's very clear, to old hands, but not so much for a new or intermediate users. It certainly is the 'cleaner' form. Like the C style increment " x++ " or the insidious " x += 4 ". However I often found myself looking for places to use "x += 4" instead of just using the clear: "x = x + 4 ". Unless there is a significant compiler/executable improvement it just there to amuse yourself. The if v: f() structure is clearer. Which is the only reason to use indents, braces and the like. I suppose that's my vote/opinion. Given a choice between clean or clear, take clear. sph On 11/24/2010 10:46 AM, Gerald Britton wrote: Writing in Python gives me the luxury of choosing different paradigms for similar operations. Lately I've been thinking about a minor detail that peaked my interest and am curious what others think: Say that I have some function "f" that I will execute if some variable "v" evaluates true. Using a classical procedural approach, I might write: if v: f() I might, however, think more in a functional-programming direction. Then I might write: v and f() Interestingly, this second expression compiles smaller (though only by a little) in both Python 2.6 and 3.1, which I currently have installed. If I had thousands of such expressions, I could boast about a measurable difference but practically speaking, it is not significant. What I _am_ interested in, however, is feedback from a style perspective. What do the rest of you think about this? Have you used the second approach and, if so, what was your motivation? Is there a good/bad reason to choose one over the other? -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question for conditional execution
On Nov 24, 2010, at 1:46 PM, Gerald Britton wrote: > Say that I have some function "f" that I will execute if some variable > "v" evaluates true. Using a classical procedural approach, I might > write: > >if v: >f() > > I might, however, think more in a functional-programming direction. > Then I might write: > >v and f() > > Interestingly, this second expression compiles smaller (though only by > a little) in both Python 2.6 and 3.1, which I currently have > installed. If I had thousands of such expressions, I could boast > about a measurable difference but practically speaking, it is not > significant. > > What I _am_ interested in, however, is feedback from a style perspective. > > What do the rest of you think about this? Readability is key. The first is instantly understandable; the second only if you are familiar with that particular programming construct. Explicit is better than implicit, so I'd go with the first form. -- Ed Leafe -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question for conditional execution
On Nov 24, 11:46 am, Gerald Britton wrote: > Say that I have some function "f" that I will execute if some variable > "v" evaluates true. Using a classical procedural approach, I might > write: > > if v: > f() > > I might, however, think more in a functional-programming direction. > Then I might write: > > v and f() The idea that "if" is inherently procedural is mistaken. Functional programming emphasizes the use of functions (in the mathematical sense) over changes in state. Assuming that f has no side effects, either of the above could equally be viewed as functional. (Of course, the fact that the return value is simply discarded in both of the above cases suggests that f *does* have side effects, in which case neither of the above should be viewed as functional.) That said, the 'if' version is clearer, so I would nearly always go with that. The rare exception would be if I were genuinely interested in capturing the value of "v" if it evaluated false. I can't remember the last time that was the case. Cheers, Ian -- http://mail.python.org/mailman/listinfo/python-list
RE: Style question - defining immutable class data members
I said: >> > My intent was to fix an obvious omission: a special case >> was discussed in >> > the "Augmented assignment statements" section, but an >> almost-identical >> > special case was omitted from the "Assignment statements" section. After finally getting registered at bugs.python.org (as described in another thread), I submitted my suggested change to the Python documentation. It's issue 5621. -John E-mail message checked by Spyware Doctor (6.0.0.386) Database version: 5.12080 http://www.pctools.com/en/spyware-doctor-antivirus/ -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question - defining immutable class data members
John Posner wrote: > [snip] > >> > If the object is a class instance and the attribute reference > occurs > >> > on both sides of the assignment operator; for example:: > >> > > >> > self.x = self.x + 1 > >> > > >> > ... in the RHS expression, ``self.x`` is evaluated with > >> > ``getattr()``, which can access either an instance attribute or > (if > >> > no instance attribute exists) a class attribute. The LHS target > >> > ``self.x`` is assigned with ``setattr()``, which *always* accesses > > >> > an instance attribute, creating it if necessary. Thus, the two > > Steve Holden said: > > >> Is this true in the case of read-write properties? This > >> seems a little > >> simplistic for what's actually a pretty complex piece of logic. > > It's not true for the read-write property example in the official property() > function description: > > class C(object): > def __init__(self): > self._x = None > > def getx(self): > return self._x > def setx(self, value): > self._x = value > def delx(self): > del self._x > x = property(getx, setx, delx, "I'm the 'x' property.") > > > But it *is* true if you revise this class definition to follow the pattern > under discussion: a class attribute provides the "initial value" of an > instance attribute: > > class C(object): > _x = 0 > > def __init__(self): > pass > def getx(self): > return self._x > def setx(self, value): > self._x = value > x = property(getx, setx) > > > My intent was to fix an obvious omission: a special case was discussed in > the "Augmented assignment statements" section, but an almost-identical > special case was omitted from the "Assignment statements" section. > > Neither section currently mentions property attributes. Do you think both > sections should be changed to cover property attributes? Or maybe it would > be simpler just to revise my first sentence: > > from: If the object is a class instance > to: If the object is a (non-property) class instance > That amendment would probably be least confusing to new readers, though it would help when in hypermedia to link "property" to some discussion of properties as they apply on the various Python versions. regards Steve -- Steve Holden +1 571 484 6266 +1 800 494 3119 Holden Web LLC http://www.holdenweb.com/ Want to know? Come to PyCon - soon! http://us.pycon.org/ -- http://mail.python.org/mailman/listinfo/python-list
RE: Style question - defining immutable class data members
[snip] >> > If the object is a class instance and the attribute reference occurs >> > on both sides of the assignment operator; for example:: >> > >> > self.x = self.x + 1 >> > >> > ... in the RHS expression, ``self.x`` is evaluated with >> > ``getattr()``, which can access either an instance attribute or (if >> > no instance attribute exists) a class attribute. The LHS target >> > ``self.x`` is assigned with ``setattr()``, which *always* accesses >> > an instance attribute, creating it if necessary. Thus, the two Steve Holden said: >> Is this true in the case of read-write properties? This >> seems a little >> simplistic for what's actually a pretty complex piece of logic. It's not true for the read-write property example in the official property() function description: class C(object): def __init__(self): self._x = None def getx(self): return self._x def setx(self, value): self._x = value def delx(self): del self._x x = property(getx, setx, delx, "I'm the 'x' property.") But it *is* true if you revise this class definition to follow the pattern under discussion: a class attribute provides the "initial value" of an instance attribute: class C(object): _x = 0 def __init__(self): pass def getx(self): return self._x def setx(self, value): self._x = value x = property(getx, setx) My intent was to fix an obvious omission: a special case was discussed in the "Augmented assignment statements" section, but an almost-identical special case was omitted from the "Assignment statements" section. Neither section currently mentions property attributes. Do you think both sections should be changed to cover property attributes? Or maybe it would be simpler just to revise my first sentence: from: If the object is a class instance to: If the object is a (non-property) class instance E-mail message checked by Spyware Doctor (6.0.0.386) Database version: 5.12050 http://www.pctools.com/en/spyware-doctor-antivirus/ -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question - defining immutable class data members
John Posner wrote: > On Mon Mar 16 03:42:42, I said: > >> RTFM, in section "Augmented assignment statements" of python301.chm: >> >> --- >> For targets which are attribute references, the initial value is retrieved > >> with a getattr() and the result is assigned with a setattr(). Notice that > the >> two methods do not necessarily refer to the same variable. When getattr() >> refers to a class variable, setattr() still writes to an instance > variable. >> For example: >> >> class A: >> x = 3# class variable >> a = A() >> a.x += 1 # writes a.x as 4 leaving A.x as 3 >> --- >> >> So, this case is closed ... almost. I believe a similar explanation, with > a >> similar example, should appear in the preceding/parent section, > "Assignment >> statements". Here's my proposed example: >> >>class A: >>x = 3 # class variable >>a = A() >>a.x = a.x + 1 # a.x on RHS gets value of class variable (3) >> # a.x on LHS creates instance variable with >>value of RHS expression (4) > > Following is a draft of my proposed addendum to the "Assignment statements" > section of the Python documentation (for both Python 2 and Python 3). I've > included reStructured Text markup. The first paragraph is what's already in > the documentation. Everything else is mine: > > * If the target is an attribute reference: The primary expression in > the reference is evaluated. It should yield an object with > assignable attributes; if this is not the case, TypeError is raised. > That object is then asked to assign the assigned object to the given > attribute; if it cannot perform the assignment, it raises an > exception (usually but not necessarily AttributeError). > > If the object is a class instance and the attribute reference occurs > on both sides of the assignment operator; for example:: > > self.x = self.x + 1 > > ... in the RHS expression, ``self.x`` is evaluated with > ``getattr()``, which can access either an instance attribute or (if > no instance attribute exists) a class attribute. The LHS target > ``self.x`` is assigned with ``setattr()``, which *always* accesses > an instance attribute, creating it if necessary. Thus, the two Is this true in the case of read-write properties? This seems a little simplistic for what's actually a pretty complex piece of logic. > occurrences of ``self.x`` do not necessarily refer to the same > variable. If the RHS expression refers to a class attribute, the LHS > creates a new instance attribute as the target of the assignment. > > See section "Augmented assignment statements" for a similar note on > attribute references. > > > If anyone would like to suggest changes to this write-up, have at it. I plan > to submit a SourceForge issue within a day or so. > > (BTW, I searched through the existing issues, to see if it has already been > reported. AFAIK, it hasn't. But #4246 is a cousin, referencing > UnboundLocalError exceptions. > regards Steve -- Steve Holden +1 571 484 6266 +1 800 494 3119 Holden Web LLC http://www.holdenweb.com/ Want to know? Come to PyCon - soon! http://us.pycon.org/ -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question - defining immutable class data members
On Mon Mar 16 03:42:42, I said: > RTFM, in section "Augmented assignment statements" of python301.chm: > > --- > For targets which are attribute references, the initial value is retrieved > with a getattr() and the result is assigned with a setattr(). Notice that the > two methods do not necessarily refer to the same variable. When getattr() > refers to a class variable, setattr() still writes to an instance variable. > For example: > > class A: > x = 3# class variable > a = A() > a.x += 1 # writes a.x as 4 leaving A.x as 3 > --- > > So, this case is closed ... almost. I believe a similar explanation, with a > similar example, should appear in the preceding/parent section, "Assignment > statements". Here's my proposed example: > >class A: >x = 3 # class variable >a = A() >a.x = a.x + 1 # a.x on RHS gets value of class variable (3) > # a.x on LHS creates instance variable with >value of RHS expression (4) Following is a draft of my proposed addendum to the "Assignment statements" section of the Python documentation (for both Python 2 and Python 3). I've included reStructured Text markup. The first paragraph is what's already in the documentation. Everything else is mine: * If the target is an attribute reference: The primary expression in the reference is evaluated. It should yield an object with assignable attributes; if this is not the case, TypeError is raised. That object is then asked to assign the assigned object to the given attribute; if it cannot perform the assignment, it raises an exception (usually but not necessarily AttributeError). If the object is a class instance and the attribute reference occurs on both sides of the assignment operator; for example:: self.x = self.x + 1 ... in the RHS expression, ``self.x`` is evaluated with ``getattr()``, which can access either an instance attribute or (if no instance attribute exists) a class attribute. The LHS target ``self.x`` is assigned with ``setattr()``, which *always* accesses an instance attribute, creating it if necessary. Thus, the two occurrences of ``self.x`` do not necessarily refer to the same variable. If the RHS expression refers to a class attribute, the LHS creates a new instance attribute as the target of the assignment. See section "Augmented assignment statements" for a similar note on attribute references. If anyone would like to suggest changes to this write-up, have at it. I plan to submit a SourceForge issue within a day or so. (BTW, I searched through the existing issues, to see if it has already been reported. AFAIK, it hasn't. But #4246 is a cousin, referencing UnboundLocalError exceptions. -John E-mail message checked by Spyware Doctor (6.0.0.386) Database version: 5.12040 http://www.pctools.com/en/spyware-doctor-antivirus/ -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question - defining immutable class data members
In article , Maxim Khitrov wrote: > >Very simple question on the preferred coding style. I frequently write >classes that have some data members initialized to immutable values. >For example: > >class Test(object): >def __init__(self): >self.some_value = 0 >self.another_value = None > >Similar effect can be achieved by defining some_value and >another_value for the entire class, like so: > >class Test(object): >some_value = 0 >another_value = None > >The advantage of doing this is that the assignments are evaluated once >and thus the creation of that class is a bit faster. Access is still >performed through self.some_value and self.another_value. Is there a >reason to prefer the first style over the second? Well, as you can see from reading this whole thread, it can be the source of some confusion. Nevertheless, I personally sometimes use the style of initializing at the class level. I think it's probably worth creating a style guide entry for this issue if you're using Python for your employer. -- Aahz (a...@pythoncraft.com) <*> http://www.pythoncraft.com/ "At Resolver we've found it useful to short-circuit any doubt and just refer to comments in code as 'lies'. :-)" --Michael Foord paraphrases Christian Muirhead on python-dev, 2009-3-22 -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question - defining immutable class data members
On Mon, 16 Mar 2009 09:31:59 -, Aaron Brady wrote: [snippety snip] Otherwise, either /1, every instance has its own entries for class functions, and subsequent changes to the class don't affect existing instances, or /2, every method call is of the form x.__class__.foo ( ). They're both bad. (...unless that's a false dilemma.) I must admit I was envisaging a horribly inefficient (in space terms) version of (1) in which the instance entries were binding stubs that referenced the class entries, but that still falls over when new methods get dynamically added to the class. I blame having two hours of sleep in three days for this particular bit of dimness, sorry. P.S. Do you pronounce 'wildebeeste' like 'vildebeeste'? No, with a "w" not a "v". It's just one of those titles that stick with you no matter what you do. -- Rhodri James *-* Wildebeeste Herder to the Masses -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question - defining immutable class data members
On Mar 15, 9:54 pm, "Rhodri James" wrote: > On Sun, 15 Mar 2009 23:26:04 -, Aaron Brady > wrote: > > > > > > > On Mar 15, 1:50 pm, "Rhodri James" > > wrote: > >> On Sun, 15 Mar 2009 17:55:25 -, Aaron Brady > >> wrote: > > >> > On Mar 15, 12:39 pm, John Posner wrote: > >> >> (My apologies if the thread has already covered this.) I believe I > >> >> understand the WHAT in this situation, but I don't understand the >> > >> WHY > [snip] > >> > Yes. If you access an attribute, you want the search to go like this: > > >> > - check instance for attribute > >> > - check class for attribute > >> > - check base classes for attribute > > >> But do you, though? The only occasion I can think of that I'd want > >> the search to go past the instance is this "auto-initialisation", > >> and frankly I'd rather do that in an __init__ anyway. Perhaps > >> static methods or class methods work that way, I don't know how > >> the innards of the interpreter handle that. > > > As Bruno stated, yes, for resolving 'self.method', and other > > descriptors. You acknowledge that 'foo.jam' would need to identify > > itself as coming from an instance, class, or base, since the only > > entries in 'foo's dictionary are those attributes which are particular > > to 'foo'. > > No, I don't acknowledge that. (Note that John's original question > was *WHY*, and you effectively gave him a *HOW* answer by asserting > that it's what he wants. I'm playing Devil's Advocate to an extent.) Very valid. Evidently I thought that the 'how' would justify it. However, a *WHAT* in this case is pretty close to a 'why'. You can access instance attributes and class attributes with the same syntax. It has the advantage that you can mix two statements into one: attr= x.attr <> if 'attr' in x.__dict__: attr= x.__dict__[ 'attr' ] else: attr= x.__class__.__dict__[ 'attr' ] Otherwise, either /1, every instance has its own entries for class functions, and subsequent changes to the class don't affect existing instances, or /2, every method call is of the form x.__class__.foo ( ). They're both bad. (...unless that's a false dilemma.) > "self.method" is not the same object as "Class.method"; one's bound > and the other isn't, for starters. It's therefore by no means > obvious that method lookup isn't being done via the instance's > dictionary. No. What makes it obvious is that subsequent changes to the class affect existing instances. > After all, some kind of binding has to be done at > instance creation time. If you're telling me that it's time- > efficient (or at least space-efficient and not horribly time- > inefficient) to use the class dictionary and magically know to > wrapper the call, then we've that makes things different and > gives us a reason for wanting that search order. It's more space efficient. However, the additional time involved in the 'instance-first-class-second' search, plus the process of creating the bound method (once per access, by the way, currently), can counterweigh or outweigh that. > It's the same story with descriptors; in fact they mask rather > more of the detail of what they're doing and look at first glance > more tightly bound to the instance than the class. Further steps > get you to the same "why" answer, but they are further steps. No, I did leave some of the steps to the analysis tacit. My mistake. > > Class attributes are grouped together in the class dictionary, > > instance attributes are grouped together in the instance dictionary, > > and instances need to see both. > > True, but they don't need to see both with instance attribute > syntax. That they can is what we're trying to justify here. As above, the alternatives (explicit class access and redundant instance membership) are bad. > > If you have a counter-proposal, either for a wishlist for behavior, or > > a way of arranging its implementation, I for one would entertain it, > > even on the c-l-python newsgroup, and even though it wouldn't have > > much of a chance of making it in to Python. > > Nope, no proposal. Mildly considering one, but I thought I'd try > understanding why what happens is considered a good thing before I > let my hare-brainedness off the leash. I know... that was just a tactic to get you to do the work of enumerating the alternatives. Bah. > > As a side note, this argument of 'whose methods am I seeing?' has an > > inconvenient artifact: the behavior of 'foo.method'. 'foo.method' > > needs to refer to an instance method, due to not needing the 'self' > > attribute respecified; while 'foo.__class__.method' needs to refer to > > a plain function. Python's solution is a skeleton type, that just > > redirects 'foo.method( )' to an append of the arguments plus call. > > As I said, this inconvenient artefact is exactly why I didn't think > assuming instance method lookup happened via the *class* dictionary > was safe! It's not. If you assign a function to an instance attribute, the
Re: Style question - defining immutable class data members
John Posner wrote: Matthew Woodcraft said: I doubt it's because anyone particularly wanted this behaviour; it just falls out of the way '+=' is defined. At the point where 'inst.x += 1' is compiled, Python doesn't know whether 'inst.x' is going to turn out to be a class attribute or an instance attribute or a property. So really the only thing it can do is generate code to read inst.x in the usual way and then assign to inst.x in the usual way (where 'the usual way' for CPython is LOAD_ATTR and STORE_ATTR). That sounds reasonable to me. Matthew Woodcraft also said: Is there any actual advantage to self.attribute picking up Class.attribute instead of raising a NameError? You use that any time you call an ordinary method using syntax like 'self.foo()'. Yes, but that's performing a read (and call) operation on an attribute. My question concerned itself with potential confusion when you perform a write operation on an attribute. Bruno Desthuilliers said: My question is ... WHY does the interpreter silently create the instance attribute at this point, Becaause that's how you create instance attributes in Python. Why do you think 'self' - that is, a reference to some object - is mandatory in "methods" (really, functions) arguments list ? Or do you mean that the existence of a synonym class attribute should be checked on each instance variable assignement ? This would probably be a big performance hit, ... Yes, Bruno, I'm persuaded by this argument. Ideally, I'd like the interpreter to prevent the programmer from shooting him/herself in the foot, but it's not worth the performance hit. and it would make per-instance method overloading impossible (remember that OOP is about objects, not classes). Yes again. While I was writing the above comment ("write operation on an attribute"), it *did* cross my mind that you might want to write self.attribute, even if it names a method, not a data-item. Summary: I no longer suspect that "Python is broken". I *do* think that there's a situation that is potentially quite confusing: * In the statement "self.x = self.x + 1", the two "self.x" names can sometimes refer to different objects. * Even worse, in the equivalent statement "self.x += 1", the single name "self.x" can sometimes refer to two different objects! I think this situation should be handled in documentation. (I'm a tech writer in my day job ... oh wait, I forgot ... I got laid off from my day job in December.) I'll look into what the standard Python doc set says on this matter. What's broken here is trying to have a class variable and an instance variable of the same name and expecting Python to get it right. Both of these problems become non-issues if you follow the "best practice" for defining instance variables: That is, set instance variables to their initial value in the __init__ method.And if you need a class default value, name it differently: For example: class C: default_x = 123 def __init__(self): self.x = self.default_x def inc(self): self.x += 1 // behaves as expected Then self.x or inst=C() and inst.x will always refer to a instance variable, the code is clear, and no confusion ensues. Gary Herron -John -- http://mail.python.org/mailman/listinfo/python-list -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question - defining immutable class data members
John Posner wrote: (My apologies if the thread has already covered this.) I believe I understand the WHAT in this situation, but I don't understand the WHY ... Given this class definition: class Cls(object): x = 345 ... I observe the following, using IDLE 2.6.1: inst = Cls() Cls.x is inst.x True Cls.x += 1 Cls.x is inst.x True inst.x += 1 Cls.x is inst.x False My question is ... WHY does the interpreter silently create the instance attribute at this point, causing a "surprising decoupling" from the class attribute? WHY doesn't the interpreter behave as it would with a simple, non-instance variable: > python Python 2.6.1 ... Type "help", "copyright", "credits" or "license" for more information. >>> x += 1 Traceback (most recent call last): File "", line 1, in NameError: name 'x' is not defined Is there a beneficial effect of silently creating the instance attribute, which outweighs the detrimental effects: (1) inconsistency, (2) the "surprising" decoupling? I wouldn't call it "silently" because "inst.x = ..." is quite explicit about "x" being an attribute of "inst". The rules for creating a variable are simple and very consistent. Each of Cls.x = ... inst.x = ... x = ... will create a variable (if it does not already exist) in a class, instance or local name space respectively. Retrieving a value is more complex as Python may look through several namespaces in succession to find a value: (For example, inst.x will check the instance , then the class ...) The problem here is that inst.x += 1 is really inst.x = inst.x+1 which according to those rules, (if inst.x is not yet defined) has both an instance and a class reference in the same statement. After that, x.inst is defined in the instance, so both sides refer to that. Gary Herron Tx, John -- http://mail.python.org/mailman/listinfo/python-list -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question - defining immutable class data members
On Mon, 2009-03-16 at 04:02 +, Tim Wintle wrote: > On Sun, 2009-03-15 at 10:39 -0700, John Posner wrote: Doh, reply out of thread there - I meant to reply to Rhodi's comment further down. > Is there any actual advantage to self.attribute picking up > Class.attribute instead of raising a NameError? -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question - defining immutable class data members
On Sun, 2009-03-15 at 10:39 -0700, John Posner wrote: > (My apologies if the thread has already covered this.) I believe I understand > the WHAT in this situation, but I don't understand the WHY ... > Is there a beneficial effect of silently creating the instance attribute, > which outweighs the detrimental effects: (1) inconsistency, (2) the > "surprising" decoupling? >From an end-user point of view (rather than the point of accessing class methods others mentioned), here are two more reasons: 1) To save memory - there's only one object stored, where an instance variable will require the same memory every instance (normally) 2) referencing Zope objects (although any persistent object storage will have the same argument): (Zope is a web framework that stores data as instances of python classes in a persistent database.) let's say you have the class (missing all the boilerplate) {{{ class ZMyUser(): def __init__(self): self.lookuplanguage = {\ "EN": "English" } self.language = "EN" def get_friendly_name(self): return self.lookuplanguage.get(self.language,"--") }}} And you create loads of these objects. But then you want to add French as an option. How do you do that? All the objects have already been created, so you could either: * Run through every object in the database one by one and update the dict as a one-off task (potentially taking a very long time as you force the computer to pull the entire database off disk) * Have written lookuplanguage as a class property, so re-initialising the class will update the definition without any extra overhead. -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question - defining immutable class data members
On Sun, 15 Mar 2009 23:26:04 -, Aaron Brady wrote: On Mar 15, 1:50 pm, "Rhodri James" wrote: On Sun, 15 Mar 2009 17:55:25 -, Aaron Brady wrote: > On Mar 15, 12:39 pm, John Posner wrote: >> (My apologies if the thread has already covered this.) I believe I >> understand the WHAT in this situation, but I don't understand the >> WHY [snip] > Yes. If you access an attribute, you want the search to go like this: > - check instance for attribute > - check class for attribute > - check base classes for attribute But do you, though? The only occasion I can think of that I'd want the search to go past the instance is this "auto-initialisation", and frankly I'd rather do that in an __init__ anyway. Perhaps static methods or class methods work that way, I don't know how the innards of the interpreter handle that. As Bruno stated, yes, for resolving 'self.method', and other descriptors. You acknowledge that 'foo.jam' would need to identify itself as coming from an instance, class, or base, since the only entries in 'foo's dictionary are those attributes which are particular to 'foo'. No, I don't acknowledge that. (Note that John's original question was *WHY*, and you effectively gave him a *HOW* answer by asserting that it's what he wants. I'm playing Devil's Advocate to an extent.) "self.method" is not the same object as "Class.method"; one's bound and the other isn't, for starters. It's therefore by no means obvious that method lookup isn't being done via the instance's dictionary. After all, some kind of binding has to be done at instance creation time. If you're telling me that it's time- efficient (or at least space-efficient and not horribly time- inefficient) to use the class dictionary and magically know to wrapper the call, then we've that makes things different and gives us a reason for wanting that search order. It's the same story with descriptors; in fact they mask rather more of the detail of what they're doing and look at first glance more tightly bound to the instance than the class. Further steps get you to the same "why" answer, but they are further steps. Class attributes are grouped together in the class dictionary, instance attributes are grouped together in the instance dictionary, and instances need to see both. True, but they don't need to see both with instance attribute syntax. That they can is what we're trying to justify here. If you have a counter-proposal, either for a wishlist for behavior, or a way of arranging its implementation, I for one would entertain it, even on the c-l-python newsgroup, and even though it wouldn't have much of a chance of making it in to Python. Nope, no proposal. Mildly considering one, but I thought I'd try understanding why what happens is considered a good thing before I let my hare-brainedness off the leash. As a side note, this argument of 'whose methods am I seeing?' has an inconvenient artifact: the behavior of 'foo.method'. 'foo.method' needs to refer to an instance method, due to not needing the 'self' attribute respecified; while 'foo.__class__.method' needs to refer to a plain function. Python's solution is a skeleton type, that just redirects 'foo.method( )' to an append of the arguments plus call. As I said, this inconvenient artefact is exactly why I didn't think assuming instance method lookup happened via the *class* dictionary was safe! Actually what I want is for the attribute to be stored where I told it, which could well be in the class. If the attribute is specified as "self.attribute", then yes, put it in the instance. The way C++ works is by allocating storage for the data and method pointers in a class. class X { int foo; char jam[ 12 ]; int foojam( int y, int z ) { ...; } }; X requires 20 bytes: 4 for 'foo', 12 for 'jam', and 4 for 'foojam'... under a 32-bit target. (The 4 for 'foojam' come from a virtual function table, for polymorphic objects er, technically.) I'm sorry, I'm utterly baffled. Why is this relevant to my bit of pedantry? You get what you want: attributes are stored where you tell them. But where are they read from? No, *why*. These questions aren't about what the search order is, they're about why there is a search order. -- Rhodri James *-* Wildebeeste Herder to the Masses -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question - defining immutable class data members
Earlier, I said: > I'll look into what the standard Python doc set says on this > matter. > RTFM, in section "Augmented assignment statements" of python301.chm: --- For targets which are attribute references, the initial value is retrieved with a getattr() and the result is assigned with a setattr(). Notice that the two methods do not necessarily refer to the same variable. When getattr() refers to a class variable, setattr() still writes to an instance variable. For example: class A: x = 3# class variable a = A() a.x += 1 # writes a.x as 4 leaving A.x as 3 --- So, this case is closed ... almost. I believe a similar explanation, with a similar example, should appear in the preceding/parent section, "Assignment statements". Here's my proposed example: class A: x = 3 # class variable a = A() a.x = a.x + 1 # a.x on RHS gets value of class variable (3) # a.x on LHS creates instance variable with value of RHS expression (4) Others' thoughts on this? -John -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question - defining immutable class data members
John Posner wrote: > Summary: I no longer suspect that "Python is broken". I *do* think that > there's a situation that is potentially quite confusing: > > * In the statement "self.x = self.x + 1", the two "self.x" names can > sometimes refer to different objects. But this is fundamental to Python. The name (or slot, in the case of say a slice assignment) on the left hand side is being given a new binding by the assignment statement. So whatever object the 'self.x' on the left hand side may have pointed to before the statement is executed is irrelevant (if we ignore '+=' and kin). That is the essence of assignment in Python. If you are surprised by this, then you should probably study up a bit on the way namespaces work in Python. What I think you meant is that even though both are represented by the same token sequence in the source ('self.x'), the two 'x's are actually located in two different namespaces. The one on the left hand side of the assignment is local to the instance, while the one on the right hand side can cascade upward to the class namespace and resolve to an object from there. > * Even worse, in the equivalent statement "self.x += 1", the single name > "self.x" can sometimes refer to two different objects! Now on this one I'll agree with you about the "worse" part. Consider: >>> class A(object): ... x = [1] ... def f(self): ... self.x = self.x + [2] ... print self.x ... >>> >>> m = A() >>> m.f() [1, 2] >>> A.x [1] >>> class B(object): ... x = [1] ... def g(self): ... self.x += [2] ... print self.x ... >>> n = B() >>> n.g() [1, 2] >>> B.x [1, 2] I'm inclined to call that a problem, myself, even though I understand why it happens (+= mutates the object pointed to by the class variable 'x', and _then_ the instance variable 'x' is created and pointed at the same object. Whereas in the '+' case, a new list is created and the new 'x' instance variable is pointed at that new list.) There is a somewhat analogous situation with variables in the local scope of a function and global variables in the module. For example, we might have: >>> x = 1 >>> def f(): ... print x ... >>> f() 1 So, when 'x' isn't found locally, the value gets picked up from the global namespace. The difference from the class/instance case is when we try to assign to it: >>> def g(): ... x = x + 1 ... >>> g() Traceback (most recent call last): File "", line 1, in File "", line 2, in g UnboundLocalError: local variable 'x' referenced before assignment >>> x = [] >>> def g(): ... x += [1] ... >>> g() Traceback (most recent call last): File "", line 1, in File "", line 2, in g UnboundLocalError: local variable 'x' referenced before assignment So in this case Python is warning us about the namespace difference. Why are the two cases handled differently? To tell you the truth, I'm not sure. I've been programming in Python for years and it just seems to make sense to me to do it that way. It does allow you to use class variables as default values for instance variables, as long as you are careful when using mutable objects. But you could argue that it should behave in a way analogous to local/global. It would be interesting to see that argument laid out in full, with all the consequences it would entail examined. > I think this situation should be handled in documentation. (I'm a tech writer > in my day job ... oh wait, I forgot ... I got laid off from my day job in > December.) I'll look into what the standard Python doc set says on this > matter. Doc patches are always welcome, and from what I hear easier to get accepted than code patches ;) -- R. David Murray http://www.bitdance.com -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question - defining immutable class data members
On Mar 15, 1:50 pm, "Rhodri James" wrote: > On Sun, 15 Mar 2009 17:55:25 -, Aaron Brady > wrote: > > > On Mar 15, 12:39 pm, John Posner wrote: > >> (My apologies if the thread has already covered this.) I believe I > >> understand the WHAT in this situation, but I don't understand the WHY > >> ... > > [snip] > > > > >> My question is ... WHY does the interpreter silently create the > >> instance attribute at this point, causing a "surprising decoupling" > >> from the class attribute? WHY doesn't the interpreter behave as it > >> would with a simple, non-instance variable: > > >> > python > >> Python 2.6.1 ... > >> Type "help", "copyright", "credits" or "license" for more information. > > >> >>> x += 1 > >> Traceback (most recent call last): > >> File "", line 1, in > >> NameError: name 'x' is not defined > > >> Is there a beneficial effect of silently creating the instance > >> attribute, which outweighs the detrimental effects: (1) inconsistency, > >> (2) the "surprising" decoupling? > > > Yes. If you access an attribute, you want the search to go like this: > > > - check instance for attribute > > - check class for attribute > > - check base classes for attribute > > But do you, though? The only occasion I can think of that I'd want > the search to go past the instance is this "auto-initialisation", > and frankly I'd rather do that in an __init__ anyway. Perhaps > static methods or class methods work that way, I don't know how > the innards of the interpreter handle that. As Bruno stated, yes, for resolving 'self.method', and other descriptors. You acknowledge that 'foo.jam' would need to identify itself as coming from an instance, class, or base, since the only entries in 'foo's dictionary are those attributes which are particular to 'foo'. Others, such as the entries in 'foo's class, are stored in a different dictionary. Changes to that class's dictionary are visible to all 'foo' instances (as desired), as well that as 'foo' isn't clogged by copies of entries for all of its class's functions. Class attributes are grouped together in the class dictionary, instance attributes are grouped together in the instance dictionary, and instances need to see both. If you have a counter-proposal, either for a wishlist for behavior, or a way of arranging its implementation, I for one would entertain it, even on the c-l-python newsgroup, and even though it wouldn't have much of a chance of making it in to Python. As a side note, this argument of 'whose methods am I seeing?' has an inconvenient artifact: the behavior of 'foo.method'. 'foo.method' needs to refer to an instance method, due to not needing the 'self' attribute respecified; while 'foo.__class__.method' needs to refer to a plain function. Python's solution is a skeleton type, that just redirects 'foo.method( )' to an append of the arguments plus call. > Is there any actual advantage to self.attribute picking up > Class.attribute instead of raising a NameError? > > > If you write an attribute, you want it stored in the attribute, not > > ^ > > > the class or base classes. > > I think you meant "instance" there :-) Syntax error line 4! Gasp! All hands to battle stations. > Actually what I want is for > the attribute to be stored where I told it, which could well be in > the class. If the attribute is specified as "self.attribute", then > yes, put it in the instance. The way C++ works is by allocating storage for the data and method pointers in a class. class X { int foo; char jam[ 12 ]; int foojam( int y, int z ) { ...; } }; X requires 20 bytes: 4 for 'foo', 12 for 'jam', and 4 for 'foojam'... under a 32-bit target. (The 4 for 'foojam' come from a virtual function table, for polymorphic objects er, technically.) Python can't and won't do that, because you want attributes to be able to join instances over time. You get what you want: attributes are stored where you tell them. But where are they read from? > > -- > Rhodri James *-* Wildebeeste Herder to the Masses -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question - defining immutable class data members
Matthew Woodcraft said: > I doubt it's because anyone particularly wanted this > behaviour; it just > falls out of the way '+=' is defined. > > At the point where 'inst.x += 1' is compiled, > Python doesn't know > whether 'inst.x' is going to turn out to be a class > attribute or an > instance attribute or a property. So really the only thing > it can do is > generate code to read inst.x in the usual way and then > assign to inst.x > in the usual way (where 'the usual way' for CPython > is LOAD_ATTR and > STORE_ATTR). That sounds reasonable to me. Matthew Woodcraft also said: >> Is there any actual advantage to self.attribute picking up >> Class.attribute instead of raising a NameError? > You use that any time you call an ordinary method using syntax like > 'self.foo()'. Yes, but that's performing a read (and call) operation on an attribute. My question concerned itself with potential confusion when you perform a write operation on an attribute. Bruno Desthuilliers said: >> My question is ... WHY does the interpreter silently create the >> instance attribute at this point, > Becaause that's how you create instance attributes in Python. Why do you > think 'self' - that is, a reference to some object - is mandatory in > "methods" (really, functions) arguments list ? > Or do you mean that the existence of a synonym class attribute should be > checked on each instance variable assignement ? This would probably be a > big performance hit, ... Yes, Bruno, I'm persuaded by this argument. Ideally, I'd like the interpreter to prevent the programmer from shooting him/herself in the foot, but it's not worth the performance hit. > and it would make per-instance method overloading > impossible (remember that OOP is about objects, not classes). Yes again. While I was writing the above comment ("write operation on an attribute"), it *did* cross my mind that you might want to write self.attribute, even if it names a method, not a data-item. Summary: I no longer suspect that "Python is broken". I *do* think that there's a situation that is potentially quite confusing: * In the statement "self.x = self.x + 1", the two "self.x" names can sometimes refer to different objects. * Even worse, in the equivalent statement "self.x += 1", the single name "self.x" can sometimes refer to two different objects! I think this situation should be handled in documentation. (I'm a tech writer in my day job ... oh wait, I forgot ... I got laid off from my day job in December.) I'll look into what the standard Python doc set says on this matter. -John -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question - defining immutable class data members
M R A Barnett wrote: > Aaron Brady wrote: > [snip] > > However, in my (opined) interpretation, 'list.append(...) is an in- > > place operation' is a factual error. In-place operations -also- > > rebind their 'argument' (FLOBW for lack of better words). 'append' is > > a by-side-effect operation. However colloquially it's mostly > > accurate. > > > [snip] > All the augmented assignments rebind, even for objects which support > in-place operations. For example: > > my_list = [] > my_list += [0] > > rebinds, but the equivalent: > > my_list = [] > my_list.extend([0]) > > doesn't. Lest someone be mislead by this discussion, how about an example: >>> a = b = [] >>> a.extend([1]) >>> a [1] >>> b [1] >>> a += [3] >>> a [1, 3] >>> b [1, 3] >>> a = a + [5] >>> a [1, 3, 5] >>> b [1, 3] It is technically correct that '+=' bebinds 'a', but what it rebinds it to is the same object that was just mutated. Unlike the '+' case where 'a' is bound to a newly created list object. Personally I think += and kin were a bad idea and should have been removed in Python 3.0 :) Even though I occasionally use them. (Maybe I'll stop.) > Augmented assignments which don't support in-place operations behave > like normal assignments (binding). For example: > > my_int = 0 > my_int += 1 > > behaves like: > > my_int = 0 > my_int = my_int + 1 -- R. David Murray http://www.bitdance.com -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question - defining immutable class data members
John Posner a écrit : (My apologies if the thread has already covered this.) I believe I understand the WHAT in this situation, but I don't understand the WHY ... Given this class definition: class Cls(object): x = 345 ... I observe the following, using IDLE 2.6.1: inst = Cls() Cls.x is inst.x True Cls.x += 1 Cls.x is inst.x True inst.x += 1 Cls.x is inst.x False My question is ... WHY does the interpreter silently create the instance attribute at this point, Becaause that's how you create instance attributes in Python. Why do you think 'self' - that is, a reference to some object - is mandatory in "methods" (really, functions) arguments list ? Or do you mean that the existence of a synonym class attribute should be checked on each instance variable assignement ? This would probably be a big performance hit, and it would make per-instance method overloading impossible (remember that OOP is about objects, not classes). -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question - defining immutable class data members
"Rhodri James" writes: > But do you, though? The only occasion I can think of that I'd want > the search to go past the instance is this "auto-initialisation", > and frankly I'd rather do that in an __init__ anyway. Perhaps > static methods or class methods work that way, I don't know how > the innards of the interpreter handle that. > > Is there any actual advantage to self.attribute picking up > Class.attribute instead of raising a NameError? You use that any time you call an ordinary method using syntax like 'self.foo()'. -M- -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question - defining immutable class data members
Rhodri James a écrit : On Sun, 15 Mar 2009 17:55:25 -, Aaron Brady wrote: On Mar 15, 12:39 pm, John Posner wrote: (snip) Is there a beneficial effect of silently creating the instance attribute, which outweighs the detrimental effects: (1) inconsistency, (2) the "surprising" decoupling? Yes. If you access an attribute, you want the search to go like this: - check instance for attribute - check class for attribute - check base classes for attribute But do you, though? The only occasion I can think of that I'd want the search to go past the instance is this "auto-initialisation", How would you resolve inst.method, then ? and frankly I'd rather do that in an __init__ anyway. Perhaps static methods or class methods work that way, I don't know how the innards of the interpreter handle that. Is there any actual advantage to self.attribute picking up Class.attribute instead of raising a NameError? Yes: resolving methods and other descriptors. -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question - defining immutable class data members
John Posner writes: > My question is ... WHY does the interpreter silently create the > instance attribute at this point, causing a "surprising decoupling" > from the class attribute? WHY doesn't the interpreter behave as it > would with a simple, non-instance variable: > > python > Python 2.6.1 ... > Type "help", "copyright", "credits" or "license" for more information. > > >>> x += 1 > Traceback (most recent call last): > File "", line 1, in > NameError: name 'x' is not defined > Is there a beneficial effect of silently creating the instance > attribute, which outweighs the detrimental effects: (1) inconsistency, > (2) the "surprising" decoupling? I doubt it's because anyone particularly wanted this behaviour; it just falls out of the way '+=' is defined. At the point where 'inst.x += 1' is compiled, Python doesn't know whether 'inst.x' is going to turn out to be a class attribute or an instance attribute or a property. So really the only thing it can do is generate code to read inst.x in the usual way and then assign to inst.x in the usual way (where 'the usual way' for CPython is LOAD_ATTR and STORE_ATTR). -M- -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question - defining immutable class data members
On Sun, 15 Mar 2009 17:55:25 -, Aaron Brady wrote: On Mar 15, 12:39 pm, John Posner wrote: (My apologies if the thread has already covered this.) I believe I understand the WHAT in this situation, but I don't understand the WHY ... [snip] My question is ... WHY does the interpreter silently create the instance attribute at this point, causing a "surprising decoupling" from the class attribute? WHY doesn't the interpreter behave as it would with a simple, non-instance variable: > python Python 2.6.1 ... Type "help", "copyright", "credits" or "license" for more information. >>> x += 1 Traceback (most recent call last): File "", line 1, in NameError: name 'x' is not defined Is there a beneficial effect of silently creating the instance attribute, which outweighs the detrimental effects: (1) inconsistency, (2) the "surprising" decoupling? Yes. If you access an attribute, you want the search to go like this: - check instance for attribute - check class for attribute - check base classes for attribute But do you, though? The only occasion I can think of that I'd want the search to go past the instance is this "auto-initialisation", and frankly I'd rather do that in an __init__ anyway. Perhaps static methods or class methods work that way, I don't know how the innards of the interpreter handle that. Is there any actual advantage to self.attribute picking up Class.attribute instead of raising a NameError? If you write an attribute, you want it stored in the attribute, not ^ the class or base classes. I think you meant "instance" there :-) Actually what I want is for the attribute to be stored where I told it, which could well be in the class. If the attribute is specified as "self.attribute", then yes, put it in the instance. -- Rhodri James *-* Wildebeeste Herder to the Masses -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question - defining immutable class data members
On Mar 15, 12:39 pm, John Posner wrote: > (My apologies if the thread has already covered this.) I believe I understand > the WHAT in this situation, but I don't understand the WHY ... > > Given this class definition: > > class Cls(object): > x = 345 > > ... I observe the following, using IDLE 2.6.1: > > >>> inst = Cls() > >>> Cls.x is inst.x > > True > > >>> Cls.x += 1 > >>> Cls.x is inst.x > > True > > >>> inst.x += 1 > >>> Cls.x is inst.x > > False > > My question is ... WHY does the interpreter silently create the instance > attribute at this point, causing a "surprising decoupling" from the class > attribute? WHY doesn't the interpreter behave as it would with a simple, > non-instance variable: > > > python > Python 2.6.1 ... > Type "help", "copyright", "credits" or "license" for more information. > > >>> x += 1 > Traceback (most recent call last): > File "", line 1, in > NameError: name 'x' is not defined > > Is there a beneficial effect of silently creating the instance attribute, > which outweighs the detrimental effects: (1) inconsistency, (2) the > "surprising" decoupling? > > Tx, > John Yes. If you access an attribute, you want the search to go like this: - check instance for attribute - check class for attribute - check base classes for attribute If you write an attribute, you want it stored in the attribute, not the class or base classes. ...unless you're just picking on the augmented ops, in which case the tradeoff is more subtle than stated. -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question - defining immutable class data members
(My apologies if the thread has already covered this.) I believe I understand the WHAT in this situation, but I don't understand the WHY ... Given this class definition: class Cls(object): x = 345 ... I observe the following, using IDLE 2.6.1: >>> inst = Cls() >>> Cls.x is inst.x True >>> Cls.x += 1 >>> Cls.x is inst.x True >>> inst.x += 1 >>> Cls.x is inst.x False My question is ... WHY does the interpreter silently create the instance attribute at this point, causing a "surprising decoupling" from the class attribute? WHY doesn't the interpreter behave as it would with a simple, non-instance variable: > python Python 2.6.1 ... Type "help", "copyright", "credits" or "license" for more information. >>> x += 1 Traceback (most recent call last): File "", line 1, in NameError: name 'x' is not defined Is there a beneficial effect of silently creating the instance attribute, which outweighs the detrimental effects: (1) inconsistency, (2) the "surprising" decoupling? Tx, John -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question - defining immutable class data members
Aaron Brady wrote: [snip] However, in my (opined) interpretation, 'list.append(...) is an in- place operation' is a factual error. In-place operations -also- rebind their 'argument' (FLOBW for lack of better words). 'append' is a by-side-effect operation. However colloquially it's mostly accurate. [snip] All the augmented assignments rebind, even for objects which support in-place operations. For example: my_list = [] my_list += [0] rebinds, but the equivalent: my_list = [] my_list.extend([0]) doesn't. Augmented assignments which don't support in-place operations behave like normal assignments (binding). For example: my_int = 0 my_int += 1 behaves like: my_int = 0 my_int = my_int + 1 -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question - defining immutable class data members
On Mar 15, 8:56 am, "Rhodri James" wrote: > On Sun, 15 Mar 2009 13:26:17 -, Matthew Woodcraft > > wrote: > > [snip Gary Herron's explanation of instance attribute lookup > falling back to class attribute lookup] > > > It seems clear to me that Maxim understood all this when he asked his > > original question (you need to understand this subtlety to know why > > the trick he was asking about only works for immutable values). > > It seems equally clear to me that Maxim didn't understand any of this > when he asked his original question, since he appeared to view class > attributes purely as initialisers. > > Given that either of us could be right, Gary's assumption of less > understanding rather than more is clearly the safer one to take. > > -- > Rhodri James *-* Wildebeeste Herder to the Masses It's interesting Rhodri chose the safety dimension as the deciding factor: Gary's assumption might have other faults, but it's safer, and (by Grice's maxim of quantity,) therefore better. In it's form: M: Safer is better. m: Gary's assumption is safer. C: Gary's assumption is better. There are two empirical claims, specifically the major and minor premises. It's not clear that either is true, but I think it's a mistake to make a blanket judgment of net safety between competing goods. Long story short, it's safe for our pride, by cutting down outsiders, but it's not safe for our publicity. As for the discussion, Gary said it: 'self.list = self.list + [i]' is a private write, but has other dangers such as running time and stored references. However, in my (opined) interpretation, 'list.append(...) is an in- place operation' is a factual error. In-place operations -also- rebind their 'argument' (FLOBW for lack of better words). 'append' is a by-side-effect operation. However colloquially it's mostly accurate. And to the OP, your method works for immutable class members, and even certain uses of mutable ones. -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question - defining immutable class data members
Maxim Khitrov a écrit : On Sat, Mar 14, 2009 at 2:07 PM, Gary Herron wrote: Maxim Khitrov wrote: Very simple question on the preferred coding style. I frequently write classes that have some data members initialized to immutable values. For example: class Test(object): def __init__(self): self.some_value = 0 self.another_value = None Similar effect can be achieved by defining some_value and another_value for the entire class, like so: class Test(object): some_value = 0 another_value = None The advantage of doing this is that the assignments are evaluated once and thus the creation of that class is a bit faster. Access is still performed through self.some_value and self.another_value. Is there a reason to prefer the first style over the second? - Max -- http://mail.python.org/mailman/listinfo/python-list Such things are often called class attributes, and the are fine. If you look through Python's standard library, you will find many examples of class attributes. However, you appear to have either a misuse or misconception of the word "immutable' here. Whether the value you assign to a class attribute is mutable or immutable is irrelevant. Also whether you plan on leaving the value constant or not is also not relevant. What does matter is this: If every instance wants access to a single value (immutable or not), use a class attribute, otherwise use an instance attribute. Gary Herron Perhaps a different example would help explain what I'm trying to do: class Case1(object): def __init__(self): self.count = 0 self.list = [] def inc(self): self.count += 1 self.list.append(self.count) def val(self): return (self.count, self.list) class Case2(object): count = 0 list = [] def inc(self): self.count += 1 This above statement does 3 things: 1/ read "self.count", which, *the first time this method is called*, resolves to self.__class__.count since by that time, there's no instance attribute named 'count' 2/ add one to the int object returned by looking up 'self.count' 3/ store the result as instance attribute named 'count'. IOW, the first calls to the method reads the class 'count' attribute and creates the instance 'count' attribute. Subsequent calls will resolve 'self.count' as the instance attribute since it now exists. self.list.append(self.count) And this statement: 1/ read 'self.list', which resolves to self.__class__.list (the class attribute) since there's no instance attribute named 'list' 2/ mutate the class attribute The only difference between Case1 and Case2 classes is where the count and list attributes are defined. You will notice that for an immutable type (count), this doesn't matter. cf above. On the last line, v1 == v2 is always True. When the type is mutable (list), you must define it in __init__. Try rebinding self.list instead of mutating it, and you'll find out that it's not related to immutable/mutable types, but to how Python's object model works wrt/ attribute lookup and attribute binding. An simple example being worth a thousand words: class Case3(object): count = 0 list = [] def inc(self): print self.__dict__ self.count += 1 self.list = self.list + [self.count] print self.__dict__ def val(self): return (self.count, self.list) >>> c = Case3() >>> print c.__dict__ {} >>> print c.__class__.__dict__ {'count': 0, '__module__': '__main__', 'val': 0xb7c7bd4c>, 'list': [], '__dict__': objects>, '__weakref__': , '__doc__': None, 'inc': } >>> c.inc() {} {'count': 1, 'list': [1]} >>> print c.__dict__ {'count': 1, 'list': [1]} >>> print c.__class__.__dict__ {'count': 0, '__module__': '__main__', 'val': 0xb7c7bd4c>, 'list': [], '__dict__': objects>, '__weakref__': , '__doc__': None, 'inc': } >>> This isn't about class attributes or shared instance attributes/constants. Yes, it is. This is about a small optimization in defining per-instance variables. This optimization only applies to immutable types. Wrong conclusions, sorry. HTH -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question - defining immutable class data members
On Sun, 15 Mar 2009 15:05:04 -, Matthew Woodcraft wrote: "Rhodri James" writes: On Sun, 15 Mar 2009 13:26:17 -, Matthew Woodcraft It seems clear to me that Maxim understood all this when he asked his original question (you need to understand this subtlety to know why the trick he was asking about only works for immutable values). It seems equally clear to me that Maxim didn't understand any of this when he asked his original question, since he appeared to view class attributes purely as initialisers. Not at all. He said: << Look, here's a tricky way to use a class attribute as an initialiser. Is this good style? >>. What was there in his post that makes you think he viewed class attributes purely as initialisers? My lack of sleep :-( -- Rhodri James *-* Wildebeeste Herder to the Masses -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question - defining immutable class data members
"Rhodri James" writes: > On Sun, 15 Mar 2009 13:26:17 -, Matthew Woodcraft >> It seems clear to me that Maxim understood all this when he asked his >> original question (you need to understand this subtlety to know why >> the trick he was asking about only works for immutable values). > > It seems equally clear to me that Maxim didn't understand any of this > when he asked his original question, since he appeared to view class > attributes purely as initialisers. Not at all. He said: << Look, here's a tricky way to use a class attribute as an initialiser. Is this good style? >>. What was there in his post that makes you think he viewed class attributes purely as initialisers? > Given that either of us could be right, Gary's assumption of less > understanding rather than more is clearly the safer one to take. As a general rule, making that assumption runs the risk of being rude or patronising, so the respondent should be very careful how to phrase the response. c.l.py is friendlier than many newsgroups, but it could still do much better. But in this particular case, statements like > However, you appear to have either a misuse or misconception of the > word "immutable' here. Whether the value you assign to a class > attribute is mutable or immutable is irrelevant. are wrong as well as unhelpfully phrased. -M- -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question - defining immutable class data members
On Sun, 15 Mar 2009 13:26:17 -, Matthew Woodcraft wrote: [snip Gary Herron's explanation of instance attribute lookup falling back to class attribute lookup] It seems clear to me that Maxim understood all this when he asked his original question (you need to understand this subtlety to know why the trick he was asking about only works for immutable values). It seems equally clear to me that Maxim didn't understand any of this when he asked his original question, since he appeared to view class attributes purely as initialisers. Given that either of us could be right, Gary's assumption of less understanding rather than more is clearly the safer one to take. -- Rhodri James *-* Wildebeeste Herder to the Masses -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question - defining immutable class data members
Gary Herron writes: > Gary Herron wrote: > No, you are still misinterpreting your results. But you can be forgiven > because this is quite a subtle point about Python's attribute access. > > Here's how it works: > > On access, self.count (or self.anything) attempts to find "count" in > the instance variable "self". If that fails, it attempts to lookup > "count" in the class. If that fails it attempts to lookup "count" in a > global context, ...). However, on assignment self.count=... *must* > necessarily mean the local instance variable -- no defaulting to a > class variable on assignment. > > So ... > > With your class C2, the line > self.count +=1 > which really translates into > self.count = self.count + 1 > has two different actions depending on the pass through the inner loop. > The first time through (when no instance variable "count" exists), that line > means > = + 1 > and succeeding passes through (now that self.count is defined) become > = +1 > which is now the same as your class C1 > > To complete the subtlety, if you were to do > self.list = self.list + [i] > you would see list behaving just as count. However since, >list.append(...) > is an in-place operation, and not an assignment, the creation of an instance > variable > is not provoked, and so all instances continue using the single class > variable. It seems clear to me that Maxim understood all this when he asked his original question (you need to understand this subtlety to know why the trick he was asking about only works for immutable values). I wish people on this mailing list|newsgroup would be a little more ready to assume that people really are asking the question they wrote, and not the FAQ that sounds most like it. -M- -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question - defining immutable class data members
Maxim Khitrov wrote: On Sat, Mar 14, 2009 at 5:38 PM, Matthew Woodcraft wrote: Gary Herron writes: I think this code is in poor taste: it's clear that it will confuse people (which is what Maxim was asking about in the first place). Careful now -- I didn't write that. (Although I agree that it is confusing.) Gary Herron Yes, I see that now, thanks :) - Max -- http://mail.python.org/mailman/listinfo/python-list -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question - defining immutable class data members
Maxim Khitrov wrote: On Sat, Mar 14, 2009 at 4:31 PM, Gary Herron wrote: Perhaps a different example would help explain what I'm trying to do: class Case1(object): def __init__(self): self.count = 0 self.list = [] def inc(self): self.count += 1 self.list.append(self.count) def val(self): return (self.count, self.list) class Case2(object): count = 0 list = [] def inc(self): self.count += 1 self.list.append(self.count) def val(self): return (self.count, self.list) for i in xrange(10): c1 = Case1() c2 = Case2() for j in xrange(i): c1.inc() c2.inc() v1, l1 = c1.val() v2, l2 = c2.val() print v1 == v2, l1 == l2 The only difference between Case1 and Case2 classes is where the count and list attributes are defined. You will notice that for an immutable type (count), this doesn't matter. On the last line, v1 == v2 is always True. When the type is mutable (list), you must define it in __init__. This isn't about class attributes or shared instance attributes/constants. This is about a small optimization in defining per-instance variables. This optimization only applies to immutable types. - Max -- http://mail.python.org/mailman/listinfo/python-list But now you are not listening to what people are telling you. It has *nothing* to do with the mutability/immutability of the integer and the list your two classes create. The difference is this: For C1: You create 10 instances of C1. Each one creates its own count, and a list variables, and manipulates them calls to inc and val. Then each on is discarded as you go through the next pass on the outer loop. Correct, though the discarded part makes no difference. For C2; You create 10 instances of C2, but these 10 instances each manipulate values created once in the class itself. The values manipulated by one instance of C2 in one pass through the loop are not affected when, on the next pass through the loop, that instance is destroyed and another instance is created. So... Incorrect. Only the count is unaffected, which was the whole point of my question. No, you are still misinterpreting your results. But you can be forgiven because this is quite a subtle point about Python's attribute access. Here's how it works: On access, self.count (or self.anything) attempts to find "count" in the instance variable "self". If that fails, it attempts to lookup "count" in the class. If that fails it attempts to lookup "count" in a global context, ...).However, on assignment self.count=... *must* necessarily mean the local instance variable -- no defaulting to a class variable on assignment. So ... With your class C2, the line self.count +=1 which really translates into self.count = self.count + 1 has two different actions depending on the pass through the inner loop. The first time through (when no instance variable "count" exists), that line means = count> + 1 and succeeding passes through (now that self.count is defined) become = +1 which is now the same as your class C1 To complete the subtlety, if you were to do self.list = self.list + [i] you would see list behaving just as count. However since, list.append(...) is an in-place operation, and not an assignment, the creation of an instance variable is not provoked, and so all instances continue using the single class variable. There is a lesson to be learned here. Class variables can't be the target of an assignment through self, because that creates an instance variable. You can, however, assign to a class variable through the class: C2.count = ... If you want a variable that records/supplies some value across *all* instances of a class, use a class variable. (Or use a global variable -- it would have the same effect.) If you want a variable whose value is unique to each instance of a class, then make it an instance variable. Gary Herron I never thought that such simple question would turn into this. David Stanek gave me the answer I was looking for (thank you). You, on the other hand, are still going after the wrong issue. Once again, here's the same example using Terry's suggestions. No class instances are being destroyed until the very end. class Case1(object): def __init__(self): self.count = 0 self.list = [] def inc(self): self.count += 1 self.list.append(self.count) def val(self): return (self.count, self.list) class Case2(object): count = 0 list = [] def inc(self): self.count += 1 self.list.append(self.count) def val(self): return (self.count, self.list) c1a, c1b = Case1(), Cas
Re: Style question - defining immutable class data members
Hallöchen! Maxim Khitrov writes: > [...] > > The advantage of doing this is that the assignments are evaluated > once and thus the creation of that class is a bit faster. Access > is still performed through self.some_value and > self.another_value. Is there a reason to prefer the first style > over the second? I think that tools like epydoc can generate more accurate API documentation if you write them as instance attributes. Tschö, Torsten. -- Torsten Bronger, aquisgrana, europa vetus Jabber ID: torsten.bron...@jabber.rwth-aachen.de -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question - defining immutable class data members
On Sat, Mar 14, 2009 at 5:38 PM, Matthew Woodcraft wrote: > Gary Herron writes: > I think this code is in poor taste: it's clear that it will confuse > people (which is what Maxim was asking about in the first place). Yes, I see that now, thanks :) - Max -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question - defining immutable class data members
On Sat, Mar 14, 2009 at 4:31 PM, Gary Herron wrote: >> Perhaps a different example would help explain what I'm trying to do: >> >> class Case1(object): >> def __init__(self): >> self.count = 0 >> self.list = [] >> >> def inc(self): >> self.count += 1 >> self.list.append(self.count) >> >> def val(self): >> return (self.count, self.list) >> >> class Case2(object): >> count = 0 >> list = [] >> >> def inc(self): >> self.count += 1 >> self.list.append(self.count) >> >> def val(self): >> return (self.count, self.list) >> >> for i in xrange(10): >> c1 = Case1() >> c2 = Case2() >> >> for j in xrange(i): >> c1.inc() >> c2.inc() >> >> v1, l1 = c1.val() >> v2, l2 = c2.val() >> >> print v1 == v2, l1 == l2 >> >> The only difference between Case1 and Case2 classes is where the count >> and list attributes are defined. You will notice that for an immutable >> type (count), this doesn't matter. On the last line, v1 == v2 is >> always True. When the type is mutable (list), you must define it in >> __init__. This isn't about class attributes or shared instance >> attributes/constants. This is about a small optimization in defining >> per-instance variables. This optimization only applies to immutable >> types. >> >> - Max >> -- >> http://mail.python.org/mailman/listinfo/python-list >> > > But now you are not listening to what people are telling you. It has > *nothing* to do with the mutability/immutability of the integer and the list > your two classes create. > > The difference is this: > > For C1: You create 10 instances of C1. Each one creates its own count, > and a list variables, and manipulates them calls to inc and val. Then each > on is discarded as you go through the next pass on the outer loop. Correct, though the discarded part makes no difference. > For C2; You create 10 instances of C2, but these 10 instances each > manipulate values created once in the class itself. The values manipulated > by one instance of C2 in one pass through the loop are not affected when, on > the next pass through the loop, that instance is destroyed and another > instance is created. > So... Incorrect. Only the count is unaffected, which was the whole point of my question. > If you want a variable that records/supplies some value across *all* > instances of a class, use a class variable. (Or use a global variable -- it > would have the same effect.) > > If you want a variable whose value is unique to each instance of a class, > then make it an instance variable. > > Gary Herron I never thought that such simple question would turn into this. David Stanek gave me the answer I was looking for (thank you). You, on the other hand, are still going after the wrong issue. Once again, here's the same example using Terry's suggestions. No class instances are being destroyed until the very end. class Case1(object): def __init__(self): self.count = 0 self.list = [] def inc(self): self.count += 1 self.list.append(self.count) def val(self): return (self.count, self.list) class Case2(object): count = 0 list = [] def inc(self): self.count += 1 self.list.append(self.count) def val(self): return (self.count, self.list) c1a, c1b = Case1(), Case1() c2a, c2b = Case2(), Case2() c1a.inc(), c1b.inc() c2a.inc(), c2b.inc() print c1a.val(), c1b.val(), c2a.val(), c2b.val() And the output: (1, [1]), (1, [1]), (1, [1, 1]), (1, [1, 1]) The first element of every tuple is the same. This is the count, which is immutable. The second element is not the same for c2[a,b]. This is the list, which is mutable. My question was about immutable values, and for those the who cases are identical. In the second case, c2a and c2b begin with count referring to the same '0' object. This is where the time and space savings are made. But because that object is immutable, when += 1 operation is performed, a copy is made for each instance. At that point, I am not sharing any values between class instances. The whole point is that this is a quick(er) way of providing initial values for class instance variables when those values are immutable. When/if that initial value is changed, a copy is made. In Case1, that copy is made from the very begging in __init__. Please try to understand what the question is about before responding to it. - Max -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question - defining immutable class data members
Gary Herron writes: > But now you are not listening to what people are telling you. It has > *nothing* to do with the mutability/immutability of the integer and the list > your two classes create. No! Did you run the code he posted? The immutability makes all the difference. > The difference is this: >For C1: You create 10 instances of C1. Each one creates its own > count, and a list variables, and manipulates them calls to inc and > val. Then each on is discarded as you go through the next pass on the > outer loop. >For C2; You create 10 instances of C2, but these 10 instances each > manipulate values created once in the class itself. The values > manipulated by one instance of C2 in one pass through the loop are not > affected when, on the next pass through the loop, that instance is > destroyed and another instance is created. If you try it, you will see that this isn't true for C2, in the case of the immutable object. That's because given this code: class Foo(object): x = 0 def inc(self): self.x += 1 when inc is called, it creates an 'x' attribute on the instance, even though one didn't exist before, and it doesn't change the value of the class attribute. If 'x' were a list, the new instance attribute would refer to the same object as the class attribute, so it wouldn't make much difference. But when the original class attribute was an immutable object, they become 'decoupled'. I think this code is in poor taste: it's clear that it will confuse people (which is what Maxim was asking about in the first place). -M- -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question - defining immutable class data members
Maxim Khitrov wrote: Perhaps a different example would help explain what I'm trying to do: class Case1(object): def __init__(self): self.count = 0 self.list = [] def inc(self): self.count += 1 self.list.append(self.count) def val(self): return (self.count, self.list) OK, so .count and .list (BAD IDEA TO USE BUILT-IN NAME) are not constants, as you previously implied. class Case2(object): count = 0 list = [] def inc(self): self.count += 1 self.list.append(self.count) def val(self): return (self.count, self.list) for i in xrange(10): You really only need one value of i for a test. But you need multiple instances of each class c1 = Case1() c2 = Case2() c1a, c1b = Case1(), Case1() c2a, c2b = Case2(), Case2() for j in xrange(i): c1.inc() c2.inc() c1a.inc(), c1b.inc() c2a.inc(), c2b,inc() v1, l1 = c1.val() v2, l2 = c2.val() print(c1a.val(), c1b.val(), c2a.val(), c2b.val()) print v1 == v2, l1 == l2 # just look as all four tuples The only difference between Case1 and Case2 classes is where the count and list attributes are defined. and that 'only difference makes a major difference. Make two instances of each class and you will see how. Terry Jan Reedy -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question - defining immutable class data members
Maxim Khitrov wrote: On Sat, Mar 14, 2009 at 2:07 PM, Gary Herron wrote: Maxim Khitrov wrote: Very simple question on the preferred coding style. I frequently write classes that have some data members initialized to immutable values. For example: class Test(object): def __init__(self): self.some_value = 0 self.another_value = None Similar effect can be achieved by defining some_value and another_value for the entire class, like so: class Test(object): some_value = 0 another_value = None The advantage of doing this is that the assignments are evaluated once and thus the creation of that class is a bit faster. Access is still performed through self.some_value and self.another_value. Is there a reason to prefer the first style over the second? - Max -- http://mail.python.org/mailman/listinfo/python-list Such things are often called class attributes, and the are fine. If you look through Python's standard library, you will find many examples of class attributes. However, you appear to have either a misuse or misconception of the word "immutable' here. Whether the value you assign to a class attribute is mutable or immutable is irrelevant. Also whether you plan on leaving the value constant or not is also not relevant. What does matter is this: If every instance wants access to a single value (immutable or not), use a class attribute, otherwise use an instance attribute. Gary Herron Perhaps a different example would help explain what I'm trying to do: class Case1(object): def __init__(self): self.count = 0 self.list = [] def inc(self): self.count += 1 self.list.append(self.count) def val(self): return (self.count, self.list) class Case2(object): count = 0 list = [] def inc(self): self.count += 1 self.list.append(self.count) def val(self): return (self.count, self.list) for i in xrange(10): c1 = Case1() c2 = Case2() for j in xrange(i): c1.inc() c2.inc() v1, l1 = c1.val() v2, l2 = c2.val() print v1 == v2, l1 == l2 The only difference between Case1 and Case2 classes is where the count and list attributes are defined. You will notice that for an immutable type (count), this doesn't matter. On the last line, v1 == v2 is always True. When the type is mutable (list), you must define it in __init__. This isn't about class attributes or shared instance attributes/constants. This is about a small optimization in defining per-instance variables. This optimization only applies to immutable types. - Max -- http://mail.python.org/mailman/listinfo/python-list But now you are not listening to what people are telling you. It has *nothing* to do with the mutability/immutability of the integer and the list your two classes create. The difference is this: For C1: You create 10 instances of C1. Each one creates its own count, and a list variables, and manipulates them calls to inc and val. Then each on is discarded as you go through the next pass on the outer loop. For C2; You create 10 instances of C2, but these 10 instances each manipulate values created once in the class itself. The values manipulated by one instance of C2 in one pass through the loop are not affected when, on the next pass through the loop, that instance is destroyed and another instance is created. So... If you want a variable that records/supplies some value across *all* instances of a class, use a class variable. (Or use a global variable -- it would have the same effect.) If you want a variable whose value is unique to each instance of a class, then make it an instance variable. Gary Herron -- http://mail.python.org/mailman/listinfo/python-list
Re: Style question - defining immutable class data members
On Sat, Mar 14, 2009 at 12:32 PM, Maxim Khitrov wrote: > Very simple question on the preferred coding style. I frequently write > classes that have some data members initialized to immutable values. > For example: > > class Test(object): > def __init__(self): > self.some_value = 0 > self.another_value = None > > Similar effect can be achieved by defining some_value and > another_value for the entire class, like so: > > class Test(object): > some_value = 0 > another_value = None > > The advantage of doing this is that the assignments are evaluated once > and thus the creation of that class is a bit faster. Access is still > performed through self.some_value and self.another_value. Is there a > reason to prefer the first style over the second? > In general I think it can be fine as long as you do use immutable values. I use this pattern when I create data transfer objects[0]. Normally these objects don't have any methods. So you want to be careful that you are doing it for the right reason. When I create objects that are not DTOs I don't do this. [0] http://martinfowler.com/eaaCatalog/dataTransferObject.html -- David blog: http://www.traceback.org twitter: http://twitter.com/dstanek -- http://mail.python.org/mailman/listinfo/python-list