
I expected to find the answer to this question in FAQ, but because there is no FAQ I ask it anyway. How about adding a new standard dict-like container type that allows access using . (dot) to its members instead of ['index']? Why? It is convenient to write options.help instead of options['halp'] etc. Example:
I know that it is easy to implement, but wouldn't it be nice to make it available by default? A side benefit of having this in stdlib is that newbies will be aware of the behaviour of derived classes without having to understand the mechanics of magic methods.

On Thu, 26 Jan 2012 19:25:40 +0200 anatoly techtonik <techtonik@gmail.com> wrote:
I expected to find the answer to this question in FAQ, but because there is no FAQ I ask it anyway.
Better to have searched the python-ideas mail list archive.
Because it doesn't work in general. There are strings that can be used as an index, but not as an attribute. There are existing attributes that you have to avoid, etc. The only way this really works in practice is if you start with a fixed set of names you want to access, in which case collections.namedtuple will probably do the job. <mike

On 1/26/2012 12:38 PM, Mike Meyer wrote:
On Thu, 26 Jan 2012 19:25:40 +0200 anatoly techtonik<techtonik@gmail.com> wrote:
How about adding a new standard dict-like container type that allows access using . (dot) to its members instead of ['index']?
We already have them: any subclass of *object*.
class Option: pass
Or did you mean 'instead of' to mean 'in addition to'? That is actually possible too.
An advantage of collections.namedtuple is that all the pre-existing attributes start with '_' so as to avoid name clashes. Another is that name subscripts do *not* work, so there is no ambiguity there either. -- Terry Jan Reedy

On Thu, Jan 26, 2012 at 9:25 AM, anatoly techtonik <techtonik@gmail.com> wrote:
That is pretty much JavaScript's 'object', and I hate this ambiguity. If your keys are always constants, define a proper options class so you can say options.help instead of options['help']. You can also write a generic subclass of dict that works this way, if you really think you like it so much. But please keep it out of the stdlib. It leads to confused users, not happy users. An example of the problems that arise: If d['a'] == d.a, then how come d['clear'] != d.clear ? -- --Guido van Rossum (python.org/~guido)

On Thu, Jan 26, 2012 at 8:47 PM, Guido van Rossum <guido@python.org> wrote:
In which case d['clear'] != d.clear can be true? I've found a MIT licensed library that implements just that: http://pypi.python.org/pypi/bunch/ Q. Why it is better than subclass of object? A. Because it is implicit. -- anatoly t.

In web2py we have a class called Storage. (web.py has a similar class too). works exactly like this except that if you do mydict.someprop and someprop does not exist returns None (which plays the role of JS undefined) instead of raining an exception. Users like this a lot because they can do: a = mydict.somevalue or 'somedefault' which new users find more readable than a = mydict.get('somevalue','somedefault') mydict.__getattr__ is the single most called method in web2py and it does affect performance. It it were supported natively by the language we would benefit from it. Massimo On Jan 26, 2012, at 11:47 AM, Guido van Rossum wrote:

I do not think the issue is whether the people who use that semantic understand it or not. I can assure you they do and they know when it is appropriate to use it or not. The issue is whether there is any value is making it faster by including it in python or not. Because of the increasing popularity of JS I think new users are starting to expect something like it out of the box. Anyway, Guido's object about the "clear" method (and other methods) is the most serious problem. One way around could be preventing keys which conflicts with the method names. Massimo On Jan 30, 2012, at 10:01 AM, Masklinn wrote:

On Jan 30, 2012 4:23 PM, "Massimo Di Pierro" <massimo.dipierro@gmail.com> wrote:
I do not think the issue is whether the people who use that semantic
understand it or not. I can assure you they do and they know when it is appropriate to use it or not. The issue is whether there is any value is making it faster by including it in python or not. Because of the increasing popularity of JS I think new users are starting to expect something like it out of the box. But this design decision in JavaScript is at the heart of many problems (e.g. simply looping over keys is a pain). That it is widely used doesn't make it desirable. My experience with JavaScript is that we should keep this 'feature' out of Python. If people want it they can implement it very easily but encouraging them would be wrong. -- Arnaud

I actually implemented this while ago in a dictionary I created. And a few weeks ago I went through all my code and removed it because it just wasn't worth the problems it gave. It's really just sugar for something that's pretty neat already. On Jan 30, 2012 7:28 PM, "Eric Snow" <ericsnowcurrently@gmail.com> wrote:

Trying to make sure I understand where we disagree and perhaps explain my problem better. For me this has very little to do with dictionaries. STEP 1) Today we can do this: class Dummy(object): pass d = Dummy() d.something = 5 print d.something Is anybody calling this un-pythonic? STEP 2) We can now overload the [] to make the dynamic attributes accessible in an alternative syntax: class Dummy(object): def __getitem__(self,key): return getattr(self,key) def __setitem__(self,key,value): return setattr(self,key,value) d = Dummy() d.something = 5 d['something'] = 5 print d.something print d['something'] STEP 3) Is anybody calling this un-pythonic? We can add redefine __getattr__ so that it never raises an exception: STEP 4) class Dummy(object): def __getitem__(self,key): return getattr(self,key) def __setitem__(self,key,value): return setattr(self,key,value) def __getattr__(self,key): return object.__getattr__(self,key) if hasattr(self,key) else Dummy() Is this un-pythonic? I do not think so but I do have a problem with it: class Dummy(object): def __getitem__(self,key): return getattr(self,key) def __setitem__(self,key,value): return setattr(self,key,value) def __getattr__(self,key): print 'wtf' return object.__getattr__(self,key) if hasattr(self,key) else None >>> d=Dummy() >>> print d.somethingelse wtf ... 334 wtf times with python2.7, 999 times with python2.5... wtf None whatever this does internally, it makes some programs slower then I would like them to be. Why is it calling itself 334 times? STEP 5) We can add methods to make this object behave like a dictionary by redefining d.keys() in terms of d.__dict__.keys() etc. STEP 6) we can re-factor it a bit so that actually class Dummy is derived from dict. Is this the part that people do not like? I would be happy if Python provided an efficient way to do something like STEP 4 without the problem I mentioned. Perhaps there is one and I ignore it. I do not necessarily require STEP5 and STEP6. Use case: settings = Dummy() settings.parameter1 = 'a' settings.parameter2 = 'b' etc. if not settings.parameter1: do something ... Massimo On Jan 30, 2012, at 11:28 AM, Eric Snow wrote:

On Mon, Jan 30, 2012 at 10:49 AM, Massimo Di Pierro < massimo.dipierro@gmail.com> wrote:
getattr calls hasattr, which calls getattr again. You are hitting the recursion limit before failing the test, due to hasattr failing with a recursion error, thus returning false. You could refactor this to use exceptions, such as: def __getattr__(self, key): try: return object.__getattr__(self, key) except Exception: return None
The general discontent with the idea is step 4. Doing so leads to abnormalities, such as d['clear'] != d.clear. The only ways to resolve such abnormalities are to make using any keys/attributes which conflict illegal, or to use different access methods for the two forms.

On Mon, 30 Jan 2012 12:49:54 -0600 Massimo Di Pierro <massimo.dipierro@gmail.com> wrote:
Depends what you're doing with it, but having a custom class which serves as nothing but a plain container is quite contrived in my opinion.
Yes. You don't need both kinds of accesses. Regards Antoine.

Antoine Pitrou wrote:
Sure you do -- as soon as 'something' can be passed in via a variable: def some_func(name): print(d.name) # uh, no print(d[name]) # okay, this works And when you are working with known objects (not passed in names): def some_other_func(): flam(d.something) sniggle(d.somethingelse) Okay, *need* might be too strong, as you could get by with [] access -- but . access is so much nicer when possible (saves three characters, which can make a difference for those of us with wimpy wrists!). ~Ethan~

On 2012-01-30, at 20:23 , Ethan Furman wrote:
Sure you do -- as soon as 'something' can be passed in via a variable: That's what getattr is for, isn't it?
The issue I have is that, to me, string keys say "arbitrary" and attributes say "enumerated set". Using one for the other? Wreaks that information. I like that Python (and most languages) makes the distinction, and I don't think Javascript and Lua should be emulated on this point.

Massimo Di Pierro writes:
On Jan 30, 2012, at 1:39 PM, Masklinn wrote:
The issue I have is that, to me, string keys say "arbitrary" and attributes say "enumerated set".
I do not understand the distinciton. In fact getattr(x,...) functionally just delegates to getitem(x.__dict__, ...). I do not see why this delegation should not be achieved using the same operator __getitem__.
That's because you're looking at it through the lens of the implementation. But you're suggesting changing the language. The argument for that cannot depend on the implementation.

Am 30.01.2012 20:23, schrieb Ethan Furman:
If anything, the d.[name] (short for getattr(d, name)) proposal should be reconsidered. But IIRC it was concluded when discussed last time that the syntax is too hard to quickly distinguish from item access, and a better one couldn't be found. Georg

On Tue, Jan 31, 2012 at 12:10 AM, Georg Brandl <g.brandl@gmx.net> wrote:
The last discussion I recall for that syntax was less than a year ago[1] and got lost amid other proposals. The idea did come up (and floundered) in 2007, though. It would be worth having another look. As Raymond put it[2]: IIRC, the idea for a __getattr__ syntax was favorably received at first, but it then drowned in a sea of syntax bikeshedding which precluded any serious discussion of use cases and benefits. Also remember that not all dead proposals have to stay dead. When generator expressions were first proposed, the PEP was rejected. The same was true for generator exceptions and for pushing data into running generators, yey these were ultimately accepted in the form of throw() and send(). +1 for reconsidering the d.[name] / d.(name) / d!name syntax. -eric [1] blow-by-blow compilation from March 2011: * Raymond brought it up -- http://mail.python.org/pipermail/python-ideas/2011-March/009265.html * ...and remained relatively neutral -- http://mail.python.org/pipermail/python-ideas/2011-March/009269.html * Greg Ewing approved -- http://mail.python.org/pipermail/python-ideas/2011-March/009271.html * Guido was thinking about it -- http://mail.python.org/pipermail/python-ideas/2011-March/009290.html * Larry Hastings on the 2007 thread -- http://mail.python.org/pipermail/python-ideas/2011-March/009284.html * Raymond in response -- http://mail.python.org/pipermail/python-ideas/2011-March/009286.html [2] http://mail.python.org/pipermail/python-ideas/2011-March/009286.html

On 1/31/2012 1:06 PM, Eric Snow wrote:
+1 for reconsidering the d.[name] / d.(name) / d!name syntax.
d.[name] is too much like d[name] The . that modifies the meaning of 'name' is too far away. d.(name) is like d.name except to me the () means to use the value of name rather than 'name' itself. This is just what you are trying to say. I believe () is used elsewhere with that meaning. I could live with this. d!name has the advantage? of no brackets, but just looks crazy since ! meant 'not' in Python. -- Terry Jan Reedy

Le 01/02/2012 02:06, MRAB a écrit :
I'm not a fan of any of the .[], .(), .{} patterns, nor of .! .
.() looks the most sensible to me.
If .[] looks like indexing, .() looks like calling. (I’m not for or against either of these, just pointing out that they have the same problem.) Regards, -- Simon Sapin

On Wed, Feb 1, 2012 at 6:06 AM, Simon Sapin <simon.sapin@kozea.fr> wrote:
Still, there should be something with a closing token. Try to imagine three of these in a chain, if the syntax is a colon: name1:name2:name3:name4 -> which could mean either of: name1:(name2:(name3:name4)), (name1:name2):(name3.name4) and so on - (not to mention other expressions involving names, though these would be less ambiguous due to to operator precedence. js -><-

On 1 February 2012 11:33, Joao S. O. Bueno <jsbueno@python.org.br> wrote:
No more so than a.b.c.d.e I would expect a:b to behave exactly the same as a.b, Except that it uses getitem rather than getattr under the hood (was that the proposal? I'm completely confused by now as to what this new syntax is intended to achieve...) But I don't like the idea in any case, so I remain -1 on the whole proposal. Paul.

Using x:[....] wouldn't it create ambiguities when parsing (lambda x:[....])? How about x. as a shortcut for x.__dict__ so we can do x.key -> x.__dict__['key'] x.[key] -> x.__dict__[key] x..keys() -> x.__dict__.keys() x..values() -> x.__dict__.values() for attribute in x.: print 'x.'+attribute and leave open the possibility of 3 dots for for ranges 1...5 -> range(1,5) 1,2...10 -> range(1,10,2-1) On Feb 1, 2012, at 7:05 AM, Paul Moore wrote:

Am 01.02.2012 14:32, schrieb Massimo Di Pierro:
Actually no, because 1. is a float literal. So 1...keys() would already be valid, and you have to use four dots for ranges. I would suggest five to be on the safe side (plus it has as many dots as there are letters in "range", therefore easy to remember). SCNR, Georg

I think .() is the nicest of the suggestions thus far. I don't mind the <- and -> syntax so much either, I could live with obj<-foo. Nathan

Let me add that one can do this: class Dummy(object): def __getitem__(self,key): return getattr(self,key) def __setitem__(self,key,value): return setattr(self,key,value) def __getattr__(self,key): return self.__dict__.get(key,None) d=Dummy() d.something = 5 print d.something print d.somethingelse which is more or less efficient and accomplished 4. Not as fast as a dict anyway. On Jan 30, 2012, at 12:49 PM, Massimo Di Pierro wrote:

On Mon, Jan 30, 2012 at 12:49:54PM -0600, Massimo Di Pierro wrote:
I do. The object has two different interfaces for the same values and that's IMO unpythonic. The Zen says "There should be one-- and preferably only one --obvious way to do it." Oleg. -- Oleg Broytman http://phdru.name/ phd@phdru.name Programmers don't die, they just GOSUB without RETURN.

Arnaud Delobelle wrote:
Fair point. I guess I'll be happy that Python will let me do it the way that works better for me. :) I think the thing to keep in mind is that this Bunch type object is not general purpose, like a dict is: it is specialized -- only string keys, only keys that don't conflict with methods (or no methods, depending on the needs), etc., etc. My custom object that works this way has attributes/methods divided by size: 10 or less and it's an attribute; more and it's a method. Works well for me. (10 because that's the maximum size for a field name in a dbf table (version 5 and below, anyway).) ~Ethan~

On Mon, Jan 30, 2012 at 11:25:12AM -0800, Ethan Furman wrote:
Sure, for attributes. But a dict contents ain't attributes, it's (key => value) mapping. So for a dict, getitem interface give access to dict's content, while getattr interface give access to dict's services - all those .keys(), .items(), .values(), .clear(), .update() et al. Oleg. -- Oleg Broytman http://phdru.name/ phd@phdru.name Programmers don't die, they just GOSUB without RETURN.

On Tue, Jan 31, 2012 at 4:49 AM, Massimo Di Pierro <massimo.dipierro@gmail.com> wrote:
Trying to make sure I understand where we disagree and perhaps explain my problem better. For me this has very little to do with dictionaries.
One general challenge with "arbitrary keys as attributes" data stores in Python is that they can get into messy namespace conflicts, because you want to allow arbitrary keys, but you also want access to ordinary methods. collections.namedtuple gets around this by leaving the attribute namespace largely free for end users and prefixing method names and class information with underscores. Ultimately, what ends up happening as far as the standard library goes is that "explicit is better than implicit" wins. If you don't know what keys you're going to get, then the appropriate data structure is a dict, not an object. If you *do* know which keys you're going to get, then the appropriate data structure is a predefined class (perhaps generated programmatically once the full set of permitted attributes is determined - e.g. when creating an appropriate namedtuple definition from a set of column headers). *Outside* the standard library, it's "practicality beats purity" that wins. People *like* being able to type ".attr" instead of "['attr']" when a field name happens to be a legal identifier. The core problem is that it's so easy to write a "good enough" version of such a class for yourself that nobody has ever bothered to standardise on a particular way of handling this that is suitable for stdlib inclusion (particularly when there are so many people that object to the idea *in principle*, regardless of the details of how it is implemented) Cheers, Nick.
P.S. Tip for fast autovivification in Python: from collections import defaultdict def autodict(): return defaultdict(autodict) >>> store['a']['b']['c'] defaultdict(<function autodict at 0x7f5adfe349b0>, {}) If you want this behaviour in instances of a particular class, set the instance __dict__ attributes to one of those in __new__ instead of overriding __getattr__. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia

Nick Coghlan wrote:
Yes, but people like all sorts of things that aren't good for them, and while Python can and does allow people to shoot themselves in the foot, I don't think we should be providing a standard foot-shooting class :) As I see it, x.name is best used for attributes of the object, which typically means that (1) in some sense, they are inherently part of the object; (2) they come from a relatively small enumerated set of names which is usually fixed; and (3) you are very unlikely to be added or deleting them from an object (usually a static set rather than dynamic). x['name'] is for the opposite cases: (1) the key/value pairs are not inherently part of the object, but in some sense are possessions of the object; (2) they come from a potentially arbitrarily large set of names which could grow indefinitely large; and (3) are usually dynamic rather than static. In my experience, there are very few use-cases which fall between those two extremes and don't see the need for a standard Javascript-like dotted-access dict. But I think the first place to put one would be a recipe on (say) ActiveState's cookbook, and see what sort of feedback and use it gets. -- Steven

On Tue, Jan 31, 2012 at 10:28 AM, Steven D'Aprano <steve@pearwood.info> wrote:
You don't have to persuade *me* of that. I spent a bunch of time years ago working with Steven Bethard on the "namespaces" proto-PEP and package, and the idea is logically incoherent enough that it's simply hard to cover all the use case variants in a single class. You either end up with a baroque monstrosity that handles everything, or you have people still rolling their own because the "official" one doesn't behave exactly the way they want. About the only variant of the idea that I *could* get behind these days is a collections.record class factory that was basically a variant of collections.namedtuple that produced mutable objects instead of tuples. Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia

There are many of these. My own http://pypi.python.org/pypi/recordtype is one such. It's primary use cases are: - mutability - default values Eric.

On 1/30/2012 1:49 PM, Massimo Di Pierro wrote:
I already suggested that that is the way to make a pure *name* to data mapping object. If you want a default data object, add your corrected method: def __getattr__(self,key): return self.__dict__.get(key,None) To make Dummy instances key iterable like dicts, add def __iter__(self): return iter(self.__dict__) If you prefer to iterate by name-object pairs: def __iter__(self): return iter(self.__dict__.items()) One could define a few other special methods, like __eq__, to tie into other syntax.
Is anybody calling this un-pythonic?
Guido already did, insofar as he defines 'pythonic'. Anyway, skip that word. This is where many of us 'disagree'. This design redefines Dummy as a *string* to data mapping object. You add a second access method that makes the first access method only partial. To me, it is a conceptually crazy object. And it gets worse when you try to make it a dict, with some names now reserved for methods. Dicts, lists, and tuples have a clean separation between contents, accessed by subscript, and methods to work on contents, accessed as attributes. Many of us consider that a virtue and a feature. -- Terry Jan Reedy

On 30Jan2012 10:28, Eric Snow <ericsnowcurrently@gmail.com> wrote: | On Mon, Jan 30, 2012 at 10:14 AM, Arnaud Delobelle <arnodel@gmail.com> wrote: | > On Jan 30, 2012 4:23 PM, "Massimo Di Pierro" <massimo.dipierro@gmail.com> | > wrote: | >> I do not think the issue is whether the people who use that semantic | >> understand it or not. I can assure you they do and they know when it is | >> appropriate to use it or not. The issue is whether there is any value is | >> making it faster by including it in python or not. Because of the increasing | >> popularity of JS I think new users are starting to expect something like it | >> out of the box. | > | > But this design decision in JavaScript is at the heart of many problems | > (e.g. simply looping over keys is a pain). That it is widely used doesn't | > make it desirable. My experience with JavaScript is that we should keep this | > 'feature' out of Python. If people want it they can implement it very easily | > but encouraging them would be wrong. | | +1 +1 Like a few others, I have implemented this kind of class. The only one of mine that survives only supports .UPPERCASE attribute->key access and is quite special purpose. I'm very much against including such a facility in the language directly. -- Cameron Simpson <cs@zip.com.au> DoD#743 http://www.cskk.ezoshosting.com/cs/ Excuse me, do you know what time it is? -About Noon. I'd prefer something more exact . . . -About Noon, Stupid.

On Thu, 26 Jan 2012 19:25:40 +0200 anatoly techtonik <techtonik@gmail.com> wrote:
I expected to find the answer to this question in FAQ, but because there is no FAQ I ask it anyway.
Better to have searched the python-ideas mail list archive.
Because it doesn't work in general. There are strings that can be used as an index, but not as an attribute. There are existing attributes that you have to avoid, etc. The only way this really works in practice is if you start with a fixed set of names you want to access, in which case collections.namedtuple will probably do the job. <mike

On 1/26/2012 12:38 PM, Mike Meyer wrote:
On Thu, 26 Jan 2012 19:25:40 +0200 anatoly techtonik<techtonik@gmail.com> wrote:
How about adding a new standard dict-like container type that allows access using . (dot) to its members instead of ['index']?
We already have them: any subclass of *object*.
class Option: pass
Or did you mean 'instead of' to mean 'in addition to'? That is actually possible too.
An advantage of collections.namedtuple is that all the pre-existing attributes start with '_' so as to avoid name clashes. Another is that name subscripts do *not* work, so there is no ambiguity there either. -- Terry Jan Reedy

On Thu, Jan 26, 2012 at 9:25 AM, anatoly techtonik <techtonik@gmail.com> wrote:
That is pretty much JavaScript's 'object', and I hate this ambiguity. If your keys are always constants, define a proper options class so you can say options.help instead of options['help']. You can also write a generic subclass of dict that works this way, if you really think you like it so much. But please keep it out of the stdlib. It leads to confused users, not happy users. An example of the problems that arise: If d['a'] == d.a, then how come d['clear'] != d.clear ? -- --Guido van Rossum (python.org/~guido)

On Thu, Jan 26, 2012 at 8:47 PM, Guido van Rossum <guido@python.org> wrote:
In which case d['clear'] != d.clear can be true? I've found a MIT licensed library that implements just that: http://pypi.python.org/pypi/bunch/ Q. Why it is better than subclass of object? A. Because it is implicit. -- anatoly t.

In web2py we have a class called Storage. (web.py has a similar class too). works exactly like this except that if you do mydict.someprop and someprop does not exist returns None (which plays the role of JS undefined) instead of raining an exception. Users like this a lot because they can do: a = mydict.somevalue or 'somedefault' which new users find more readable than a = mydict.get('somevalue','somedefault') mydict.__getattr__ is the single most called method in web2py and it does affect performance. It it were supported natively by the language we would benefit from it. Massimo On Jan 26, 2012, at 11:47 AM, Guido van Rossum wrote:

I do not think the issue is whether the people who use that semantic understand it or not. I can assure you they do and they know when it is appropriate to use it or not. The issue is whether there is any value is making it faster by including it in python or not. Because of the increasing popularity of JS I think new users are starting to expect something like it out of the box. Anyway, Guido's object about the "clear" method (and other methods) is the most serious problem. One way around could be preventing keys which conflicts with the method names. Massimo On Jan 30, 2012, at 10:01 AM, Masklinn wrote:

On Jan 30, 2012 4:23 PM, "Massimo Di Pierro" <massimo.dipierro@gmail.com> wrote:
I do not think the issue is whether the people who use that semantic
understand it or not. I can assure you they do and they know when it is appropriate to use it or not. The issue is whether there is any value is making it faster by including it in python or not. Because of the increasing popularity of JS I think new users are starting to expect something like it out of the box. But this design decision in JavaScript is at the heart of many problems (e.g. simply looping over keys is a pain). That it is widely used doesn't make it desirable. My experience with JavaScript is that we should keep this 'feature' out of Python. If people want it they can implement it very easily but encouraging them would be wrong. -- Arnaud

I actually implemented this while ago in a dictionary I created. And a few weeks ago I went through all my code and removed it because it just wasn't worth the problems it gave. It's really just sugar for something that's pretty neat already. On Jan 30, 2012 7:28 PM, "Eric Snow" <ericsnowcurrently@gmail.com> wrote:

Trying to make sure I understand where we disagree and perhaps explain my problem better. For me this has very little to do with dictionaries. STEP 1) Today we can do this: class Dummy(object): pass d = Dummy() d.something = 5 print d.something Is anybody calling this un-pythonic? STEP 2) We can now overload the [] to make the dynamic attributes accessible in an alternative syntax: class Dummy(object): def __getitem__(self,key): return getattr(self,key) def __setitem__(self,key,value): return setattr(self,key,value) d = Dummy() d.something = 5 d['something'] = 5 print d.something print d['something'] STEP 3) Is anybody calling this un-pythonic? We can add redefine __getattr__ so that it never raises an exception: STEP 4) class Dummy(object): def __getitem__(self,key): return getattr(self,key) def __setitem__(self,key,value): return setattr(self,key,value) def __getattr__(self,key): return object.__getattr__(self,key) if hasattr(self,key) else Dummy() Is this un-pythonic? I do not think so but I do have a problem with it: class Dummy(object): def __getitem__(self,key): return getattr(self,key) def __setitem__(self,key,value): return setattr(self,key,value) def __getattr__(self,key): print 'wtf' return object.__getattr__(self,key) if hasattr(self,key) else None >>> d=Dummy() >>> print d.somethingelse wtf ... 334 wtf times with python2.7, 999 times with python2.5... wtf None whatever this does internally, it makes some programs slower then I would like them to be. Why is it calling itself 334 times? STEP 5) We can add methods to make this object behave like a dictionary by redefining d.keys() in terms of d.__dict__.keys() etc. STEP 6) we can re-factor it a bit so that actually class Dummy is derived from dict. Is this the part that people do not like? I would be happy if Python provided an efficient way to do something like STEP 4 without the problem I mentioned. Perhaps there is one and I ignore it. I do not necessarily require STEP5 and STEP6. Use case: settings = Dummy() settings.parameter1 = 'a' settings.parameter2 = 'b' etc. if not settings.parameter1: do something ... Massimo On Jan 30, 2012, at 11:28 AM, Eric Snow wrote:

On Mon, Jan 30, 2012 at 10:49 AM, Massimo Di Pierro < massimo.dipierro@gmail.com> wrote:
getattr calls hasattr, which calls getattr again. You are hitting the recursion limit before failing the test, due to hasattr failing with a recursion error, thus returning false. You could refactor this to use exceptions, such as: def __getattr__(self, key): try: return object.__getattr__(self, key) except Exception: return None
The general discontent with the idea is step 4. Doing so leads to abnormalities, such as d['clear'] != d.clear. The only ways to resolve such abnormalities are to make using any keys/attributes which conflict illegal, or to use different access methods for the two forms.

On Mon, 30 Jan 2012 12:49:54 -0600 Massimo Di Pierro <massimo.dipierro@gmail.com> wrote:
Depends what you're doing with it, but having a custom class which serves as nothing but a plain container is quite contrived in my opinion.
Yes. You don't need both kinds of accesses. Regards Antoine.

Antoine Pitrou wrote:
Sure you do -- as soon as 'something' can be passed in via a variable: def some_func(name): print(d.name) # uh, no print(d[name]) # okay, this works And when you are working with known objects (not passed in names): def some_other_func(): flam(d.something) sniggle(d.somethingelse) Okay, *need* might be too strong, as you could get by with [] access -- but . access is so much nicer when possible (saves three characters, which can make a difference for those of us with wimpy wrists!). ~Ethan~

On 2012-01-30, at 20:23 , Ethan Furman wrote:
Sure you do -- as soon as 'something' can be passed in via a variable: That's what getattr is for, isn't it?
The issue I have is that, to me, string keys say "arbitrary" and attributes say "enumerated set". Using one for the other? Wreaks that information. I like that Python (and most languages) makes the distinction, and I don't think Javascript and Lua should be emulated on this point.

Massimo Di Pierro writes:
On Jan 30, 2012, at 1:39 PM, Masklinn wrote:
The issue I have is that, to me, string keys say "arbitrary" and attributes say "enumerated set".
I do not understand the distinciton. In fact getattr(x,...) functionally just delegates to getitem(x.__dict__, ...). I do not see why this delegation should not be achieved using the same operator __getitem__.
That's because you're looking at it through the lens of the implementation. But you're suggesting changing the language. The argument for that cannot depend on the implementation.

Am 30.01.2012 20:23, schrieb Ethan Furman:
If anything, the d.[name] (short for getattr(d, name)) proposal should be reconsidered. But IIRC it was concluded when discussed last time that the syntax is too hard to quickly distinguish from item access, and a better one couldn't be found. Georg

On Tue, Jan 31, 2012 at 12:10 AM, Georg Brandl <g.brandl@gmx.net> wrote:
The last discussion I recall for that syntax was less than a year ago[1] and got lost amid other proposals. The idea did come up (and floundered) in 2007, though. It would be worth having another look. As Raymond put it[2]: IIRC, the idea for a __getattr__ syntax was favorably received at first, but it then drowned in a sea of syntax bikeshedding which precluded any serious discussion of use cases and benefits. Also remember that not all dead proposals have to stay dead. When generator expressions were first proposed, the PEP was rejected. The same was true for generator exceptions and for pushing data into running generators, yey these were ultimately accepted in the form of throw() and send(). +1 for reconsidering the d.[name] / d.(name) / d!name syntax. -eric [1] blow-by-blow compilation from March 2011: * Raymond brought it up -- http://mail.python.org/pipermail/python-ideas/2011-March/009265.html * ...and remained relatively neutral -- http://mail.python.org/pipermail/python-ideas/2011-March/009269.html * Greg Ewing approved -- http://mail.python.org/pipermail/python-ideas/2011-March/009271.html * Guido was thinking about it -- http://mail.python.org/pipermail/python-ideas/2011-March/009290.html * Larry Hastings on the 2007 thread -- http://mail.python.org/pipermail/python-ideas/2011-March/009284.html * Raymond in response -- http://mail.python.org/pipermail/python-ideas/2011-March/009286.html [2] http://mail.python.org/pipermail/python-ideas/2011-March/009286.html

On 1/31/2012 1:06 PM, Eric Snow wrote:
+1 for reconsidering the d.[name] / d.(name) / d!name syntax.
d.[name] is too much like d[name] The . that modifies the meaning of 'name' is too far away. d.(name) is like d.name except to me the () means to use the value of name rather than 'name' itself. This is just what you are trying to say. I believe () is used elsewhere with that meaning. I could live with this. d!name has the advantage? of no brackets, but just looks crazy since ! meant 'not' in Python. -- Terry Jan Reedy

Le 01/02/2012 02:06, MRAB a écrit :
I'm not a fan of any of the .[], .(), .{} patterns, nor of .! .
.() looks the most sensible to me.
If .[] looks like indexing, .() looks like calling. (I’m not for or against either of these, just pointing out that they have the same problem.) Regards, -- Simon Sapin

On Wed, Feb 1, 2012 at 6:06 AM, Simon Sapin <simon.sapin@kozea.fr> wrote:
Still, there should be something with a closing token. Try to imagine three of these in a chain, if the syntax is a colon: name1:name2:name3:name4 -> which could mean either of: name1:(name2:(name3:name4)), (name1:name2):(name3.name4) and so on - (not to mention other expressions involving names, though these would be less ambiguous due to to operator precedence. js -><-

On 1 February 2012 11:33, Joao S. O. Bueno <jsbueno@python.org.br> wrote:
No more so than a.b.c.d.e I would expect a:b to behave exactly the same as a.b, Except that it uses getitem rather than getattr under the hood (was that the proposal? I'm completely confused by now as to what this new syntax is intended to achieve...) But I don't like the idea in any case, so I remain -1 on the whole proposal. Paul.

Using x:[....] wouldn't it create ambiguities when parsing (lambda x:[....])? How about x. as a shortcut for x.__dict__ so we can do x.key -> x.__dict__['key'] x.[key] -> x.__dict__[key] x..keys() -> x.__dict__.keys() x..values() -> x.__dict__.values() for attribute in x.: print 'x.'+attribute and leave open the possibility of 3 dots for for ranges 1...5 -> range(1,5) 1,2...10 -> range(1,10,2-1) On Feb 1, 2012, at 7:05 AM, Paul Moore wrote:

Am 01.02.2012 14:32, schrieb Massimo Di Pierro:
Actually no, because 1. is a float literal. So 1...keys() would already be valid, and you have to use four dots for ranges. I would suggest five to be on the safe side (plus it has as many dots as there are letters in "range", therefore easy to remember). SCNR, Georg

I think .() is the nicest of the suggestions thus far. I don't mind the <- and -> syntax so much either, I could live with obj<-foo. Nathan

Let me add that one can do this: class Dummy(object): def __getitem__(self,key): return getattr(self,key) def __setitem__(self,key,value): return setattr(self,key,value) def __getattr__(self,key): return self.__dict__.get(key,None) d=Dummy() d.something = 5 print d.something print d.somethingelse which is more or less efficient and accomplished 4. Not as fast as a dict anyway. On Jan 30, 2012, at 12:49 PM, Massimo Di Pierro wrote:

On Mon, Jan 30, 2012 at 12:49:54PM -0600, Massimo Di Pierro wrote:
I do. The object has two different interfaces for the same values and that's IMO unpythonic. The Zen says "There should be one-- and preferably only one --obvious way to do it." Oleg. -- Oleg Broytman http://phdru.name/ phd@phdru.name Programmers don't die, they just GOSUB without RETURN.

Arnaud Delobelle wrote:
Fair point. I guess I'll be happy that Python will let me do it the way that works better for me. :) I think the thing to keep in mind is that this Bunch type object is not general purpose, like a dict is: it is specialized -- only string keys, only keys that don't conflict with methods (or no methods, depending on the needs), etc., etc. My custom object that works this way has attributes/methods divided by size: 10 or less and it's an attribute; more and it's a method. Works well for me. (10 because that's the maximum size for a field name in a dbf table (version 5 and below, anyway).) ~Ethan~

On Mon, Jan 30, 2012 at 11:25:12AM -0800, Ethan Furman wrote:
Sure, for attributes. But a dict contents ain't attributes, it's (key => value) mapping. So for a dict, getitem interface give access to dict's content, while getattr interface give access to dict's services - all those .keys(), .items(), .values(), .clear(), .update() et al. Oleg. -- Oleg Broytman http://phdru.name/ phd@phdru.name Programmers don't die, they just GOSUB without RETURN.

On Tue, Jan 31, 2012 at 4:49 AM, Massimo Di Pierro <massimo.dipierro@gmail.com> wrote:
Trying to make sure I understand where we disagree and perhaps explain my problem better. For me this has very little to do with dictionaries.
One general challenge with "arbitrary keys as attributes" data stores in Python is that they can get into messy namespace conflicts, because you want to allow arbitrary keys, but you also want access to ordinary methods. collections.namedtuple gets around this by leaving the attribute namespace largely free for end users and prefixing method names and class information with underscores. Ultimately, what ends up happening as far as the standard library goes is that "explicit is better than implicit" wins. If you don't know what keys you're going to get, then the appropriate data structure is a dict, not an object. If you *do* know which keys you're going to get, then the appropriate data structure is a predefined class (perhaps generated programmatically once the full set of permitted attributes is determined - e.g. when creating an appropriate namedtuple definition from a set of column headers). *Outside* the standard library, it's "practicality beats purity" that wins. People *like* being able to type ".attr" instead of "['attr']" when a field name happens to be a legal identifier. The core problem is that it's so easy to write a "good enough" version of such a class for yourself that nobody has ever bothered to standardise on a particular way of handling this that is suitable for stdlib inclusion (particularly when there are so many people that object to the idea *in principle*, regardless of the details of how it is implemented) Cheers, Nick.
P.S. Tip for fast autovivification in Python: from collections import defaultdict def autodict(): return defaultdict(autodict) >>> store['a']['b']['c'] defaultdict(<function autodict at 0x7f5adfe349b0>, {}) If you want this behaviour in instances of a particular class, set the instance __dict__ attributes to one of those in __new__ instead of overriding __getattr__. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia

Nick Coghlan wrote:
Yes, but people like all sorts of things that aren't good for them, and while Python can and does allow people to shoot themselves in the foot, I don't think we should be providing a standard foot-shooting class :) As I see it, x.name is best used for attributes of the object, which typically means that (1) in some sense, they are inherently part of the object; (2) they come from a relatively small enumerated set of names which is usually fixed; and (3) you are very unlikely to be added or deleting them from an object (usually a static set rather than dynamic). x['name'] is for the opposite cases: (1) the key/value pairs are not inherently part of the object, but in some sense are possessions of the object; (2) they come from a potentially arbitrarily large set of names which could grow indefinitely large; and (3) are usually dynamic rather than static. In my experience, there are very few use-cases which fall between those two extremes and don't see the need for a standard Javascript-like dotted-access dict. But I think the first place to put one would be a recipe on (say) ActiveState's cookbook, and see what sort of feedback and use it gets. -- Steven
participants (26)
-
Alexander Heger
-
anatoly techtonik
-
Antoine Pitrou
-
Arnaud Delobelle
-
Cameron Simpson
-
Chris Kaynor
-
David Townshend
-
Devin Jeanpierre
-
Eric Smith
-
Eric Snow
-
Ethan Furman
-
Georg Brandl
-
Guido van Rossum
-
Joao S. O. Bueno
-
Masklinn
-
Massimo Di Pierro
-
Mike Meyer
-
MRAB
-
Nathan Rice
-
Nick Coghlan
-
Oleg Broytman
-
Paul Moore
-
Simon Sapin
-
Stephen J. Turnbull
-
Steven D'Aprano
-
Terry Reedy