Bug? Feature? setattr(foo, '3', 4) works!
Terry Reedy
tjreedy at udel.edu
Fri Dec 19 08:50:54 EST 2014
On 12/19/2014 6:40 AM, Cem Karan wrote:
> I'm bringing this discussion over from the python-ideas mailing list
> to see what people think. I accidentally discovered that the
> following works, at least in Python 3.4.2:
>
>>>> class foo(object):
> ... pass ...
>>>> setattr(foo, '3', 4) dir(foo)
> ['3', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__',
> '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__',
> '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__',
> '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__',
> '__sizeof__', '__str__', '__subclasshook__', '__weakref__']
>>>> getattr(foo, '3')
> 4
>>>> bar = foo() dir(bar)
> ['3', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__',
> '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__',
> '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__',
> '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__',
> '__sizeof__', '__str__', '__subclasshook__', '__weakref__']
>>>> getattr(bar, '3')
> 4
>>>> hasattr(foo, '3')
> True
>>>> hasattr(bar, '3')
> True
The fact that one has set and retrieve non-identifier attributes has
always been true and known and discussed before. Guido has declared
that it should continue to work rather than break code that uses this
fact (and their is apparently such). This follows under Python's
'consenting adults' policy.
The attribute 'name' is type-checked to be a string.
>>> class C: pass
>>> c = C()
>>> setattr(c, 3, '3')
Traceback (most recent call last):
File "<pyshell#3>", line 1, in <module>
setattr(c, 3, '3')
TypeError: attribute name must be string, not 'int'
>>> setattr(c, b'3', '3')
Traceback (most recent call last):
File "<pyshell#4>", line 1, in <module>
setattr(c, b'3', '3')
TypeError: attribute name must be string, not 'bytes'
If one accesses the dict directly, even the string limitation is
bypassed, but one suffers the consequences.
>>> c.__dict__[3] = 3
>>> dir(c)
Traceback (most recent call last):
File "<pyshell#9>", line 1, in <module>
dir(c)
TypeError: unorderable types: int() < str()
> Thoughts?
Don't pursue this. Leave good enough alone.
--
Terry Jan Reedy
More information about the Python-list
mailing list