Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Impossible to set an attribute to a string?

Tags:

python

Usually, you can set an arbitrary attribute to a custom object, for instance

----------
>>> a=A()
>>> a.foo=42
>>> a.__dict__
{'foo': 42}
>>> 
----------

On the other hand, you can't do the same binding with a string object :

----------
>>> a=str("bar")
>>> a.foo=42
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'str' object has no attribute 'foo'
>>> a.__dict__
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'str' object has no attribute '__dict__'
>>>
----------

Why ?

like image 782
candide Avatar asked Oct 27 '11 01:10

candide


2 Answers

Because the str type is a type wich does not has an attribute dict. From the docs, "Classes" section:

A class has a namespace implemented by a dictionary object. Class attribute references are translated to lookups in this dictionary, e.g., C.x is translated to C.__dict__["x"]

You can also enforce something similar on custom objects:

>>> class X(object):
...     __slots__=('a', )
... 
>>> a = X()
>>> a.a = 2
>>> a.foo = 2
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'X' object has no attribute 'foo'

In general, you should not be setting nor modifying fields of objects that you are not supposed to. The documentation of the specific data type should reference you what fields are available for public modification.

For example, an ReadOnlyPoint object, where the x and y coordinates are set only on object construction:

>>> class ReadOnlyPoint(object):
...     __slots__ = ('_x', '_y')
...     def __init__(self, x, y):
...             self._x = x
...             self._y = y
...     def getx(self):
...             return self._x
...     def gety(self):
...             return self._y
...     x = property(getx)
...     y = property(gety)
... 
>>> p = ReadOnlyPoint(2, 3)
>>> print p.x, p.y
2 3
>>> p.x = 9
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: can't set attribute
>>> p._x = 9
>>> print p.x, p.y
9 3

While the x and y properties are read-only, accessing the object internals allows you to alter the object's state.

The inhability to add a new field to an str object is an implementation detail, specific to the Python version that you are using.

like image 55
vz0 Avatar answered Oct 24 '22 00:10

vz0


http://docs.python.org/reference/datamodel.html

If the class has a setattr() or delattr() method, this is called instead of updating the instance dictionary directly.

http://docs.python.org/reference/datamodel.html#object.setattr

like image 2
Falmarri Avatar answered Oct 24 '22 00:10

Falmarri