I'm at my wits end. Can't find anything else that helps with this.
dta = {'type': "", 'content': ""}
print dta
>>>{'content': '', 'type': ''}
setattr(dta, 'type', "Steve")
>>>AttributeError: 'dict' object has no attribute 'type'
Python's dictionaries aren't JS objects. When you create a dict, you aren't creating a dynamic object whose properties you can change at runtime as in JS. Instead the dictionary knows how to store pairs of keys and values and does so by overriding the operator [] (def __getitem__(self, key)).
On a more implementation level - calling getattr / setattr is really a shorthand for data.__getattr__("foo") and since dict uses __getitem__ as opposed to __getattr__ the function call fails.
Thus, there's no way to set (or get for that matter) the dict's items using generic attribute functions.
However, you can create your custom dict class that does support that operation (although I wouldn't recommend it):
class AttrDict(dict):
def __init__(self):
dict.__init__(self)
# Override getattr and setattr so that they return the values of getitem / setitem
def __setattr__(self, name, value):
self[name] = value
def __getattr__(self, name):
return self[name]
data = AttrDict()
data["foo"] = "bar"
print(getattr(data, "foo"))
setattr is a built-in function specifically to change values of object attributes, not dictionary values.setattr does not work with a dictionary because it does not have an __dict__.
I can make a simple class and instance:
In [88]: class Obj(object):
...: pass
...:
In [89]: ob = Obj()
In [90]: ob.__dict__
Out[90]: {}
In [91]: setattr(ob,'test',34)
In [92]: ob.__dict__
Out[92]: {'test': 34}
In [95]: ob.test
Out[95]: 34
setattr sets an item in the __dict__ of obj, and the resulting attribute can be accessed with .test syntax.
But a dict object does not have a __dict__.
In [96]: dd={1:2, 3:4}
In [97]: dd.__dict__
AttributeError: 'dict' object has no attribute '__dict__'
In [98]: setattr(dd, 'test', 34)
AttributeError: 'dict' object has no attribute 'test'
I add items to the dict with the dictionary indexing notation:
In [99]: dd['test'] = 34
In [100]: dd
Out[100]: {1: 2, 3: 4, 'test': 34}
The dictionary class inherits from object, but in way that does not give each instance a __dict__. Thus setattr has nothing to act on.
If for some reason the []= syntax is awkward, you can use operator.setitem as a function:
In [108]: operator.setitem?
Docstring: setitem(a, b, c) -- Same as a[b] = c.
Type: builtin_function_or_method
In [109]: operator.setitem(dd, 'test', 23)
In [110]: dd
Out[110]: {1: 2, 3: 4, 'test': 23}
Or use the __setitem__ method
In [111]: dd.__setitem__('test', 1)
In [112]: dd
Out[112]: {1: 2, 3: 4, 'test': 1}
Actually, a dictionary does have attributes. For example its .get method can be fetched with getattr. setattr returns a different error in this example.
In [119]: getattr(dd,'get')
Out[119]: <function dict.get>
In [120]: setattr(dd,'get',dict.get)
...
AttributeError: 'dict' object attribute 'get' is read-only
Without the __dict__ we can't add an attribute to a dictionary. And many, if not all, of the existing attributes are read only. I don't know if a dictionary has an attributes that can be changed.
Actually a dictionary is an object:
In [121]: isinstance(dd,dict)
Out[121]: True
In [122]: isinstance(dd,object)
Out[122]: True
I just imported defaultdict. It too lacks a __dict__. But I was able to use setattr(ddd,'default_factory', int). I think that no attribute is the correct error message when the attribute does not already exist, and it cannot add new ones.
==============
I'd have to double check the documentation on this, but I think setattr(dd,...) delegates to dd.__setattr__(...).
In [168]: dd.__setattr__('test',1)
...
AttributeError: 'dict' object has no attribute 'test'
In [169]: dd.__setattr__('get',None)
...
AttributeError: 'dict' object attribute 'get' is read-only
So the error message is determined by the dict class, not setattr.
Even instances that have a __dict_- might raise errors if setattr is used wrong. For example a number is not a valid attribute name:
In [171]: setattr(ob, 123, 'a')
....
TypeError: attribute name must be string, not 'int'
But setattr can set attributes that can't be accessed with the . syntax:
In [172]: setattr(ob, 'a#re',1)
In [174]: ob.a#re
...
AttributeError: 'Obj' object has no attribute 'a'
In [175]: getattr(ob, 'a#re')
Out[175]: 1
vars() is another way of accessing the __dict__ of an instance:
In [179]: vars(dd)
...
TypeError: vars() argument must have __dict__ attribute
setattr(obj, attr, val) first did a test if (type obj == 'dict') throw error "'obj ' is not an object". How handy would that be?s = { "qwe": "asd" } and print type s you get > > > type dict so if you in inadvertently pass a dict (i.e. s) to setattr() but it requires an object then setattr() should test for this and throw an error that regards the absence of an object parameter value. Instead what it does do is throw an error that it can't find the attribute in the dict that you requested.__setattr__ method that generates your error.object().__dict__? Obj class doesn't add any methods, but it still is a user defined class with a __dict__.You can assign dict values directly, setattr() is not needed.
dta = {'type': "", 'content': ""}
dta["type"] = "Steve"
'setattr()' refers to something else. When you write setattr(dta, 'type', "Steve") you're trying to access the field dta.type, dict class has no attribute type, so it gives an error.
dict_object['key'] is a completely different thing, and it's how dict members should be accessed.
More about settatr() Here
Dictionaries are subscriptable, the key:value pairs are items instead of attributes.
Items are accessed using a subscript notation:
>>> d = {'a':1, 'b':2}
>>> d['a']
1
Attributes are accessed using dot notation
>>> d.a
Traceback (most recent call last):
File "<pyshell#3>", line 1, in <module>
d.a
AttributeError: 'dict' object has no attribute 'a'
operator.itemgetter is similar to getattr:
>>> import operator
>>> bee = operator.itemgetter('b')
>>> bee(d)
2
>>>
>>> hasattr(d, '__getitem__')
True
>>> hasattr(d, '__getattr__')
False
>>>
docs.python.org/2/library/functions.html#setattr
This is the counterpart of getattr(). The arguments are an object, a string and an arbitrary value. The string may name an existing attribute or a new attribute. The function assigns the value to the attribute, provided the object allows it
OBJECT is not a DICTIONARY. And I probably confusing my JS work (syntax) with the Python code I'm always writing at the same time
So the error message is confusing:
AttributeError: 'dict' object has no attribute 'type'
It should be more like:
'setattr() is for objects not dictionaries'
.
Thanks everyone.
dta.type, then you should not be able to set it withsetattr.