I would like to understand the difference between these two syntaxes:
Ex:.
obj = {
'atrib1': 1,
'atrib2': 2
}
#accessing atrib1
print(obj['atrib1'])
#why can't I access like this, and what is accessible in this way?
#print(obj.atrib1)
I would like to understand the difference between these two syntaxes:
Ex:.
obj = {
'atrib1': 1,
'atrib2': 2
}
#accessing atrib1
print(obj['atrib1'])
#why can't I access like this, and what is accessible in this way?
#print(obj.atrib1)
In languages like Lua and JavaScript, where what you can access via obj.attr
and obj["attr"]
is the same, you'll notice that the APIs for manipulating a dictionary are not actually part of the dictionary object. For example, if you want to get the keys of a dictionary as a list, in JavaScript, you call Objects.keys()
, passing the dictionary as a parameter. You don't call the_dictionary.keys()
.
The reason these are external functions rather than member functions is that the keys in the key/value dictionary could override member functions. If a dictionary just so happened to have a key named "keys", any member function named "keys" would be overridden. Therefore, functions which act on dictionaries cannot be members of the actual dictionary type.
In Python, they can be. The contents of a dictionary are accessed via []
, but the member functions, the operations which act upon those contents, are accessed via .name
notation. That's the distinction between attributes and "fields". And that means the operations on dictionaries are actually on the dictionary.
You can of course make them one and the same, but then you recreate the original problem. And since Python doesn't have that problem normally, it doesn't have non-member functions you can easily call to do that job. You can still do it via the class object, but it's clearly non-Pythonic.
In Python, objects have attributes, which may be accessed with the .name
syntax. But some object classes implement a __getitem__
method, which is accessed with the ['name']
syntax. Most notably, the dict
class:
In [102]: obj = {
...: 'atrib1': 1,
...: 'atrib2': 2
...: }
...:
In [103]: type(obj)
Out[103]: dict
obj['atrib1']
is translated by the interpreter into a method call:
In [104]: obj.__getitem__('atrib1')
Out[104]: 1
obj.atrib1
is translated into an __getattribute__
call:
In [105]: obj.__getattribute__('atrib1')
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-105-ec1bc68ae22d> in <module>
----> 1 obj.__getattribute__('atrib1')
AttributeError: 'dict' object has no attribute 'atrib1'
That class does have attributes like __getattribute__
and keys
, which are functions:
In [106]: obj.__getattribute__('__getitem__')
Out[106]: <function dict.__getitem__>
In [107]: obj.__getattribute__('keys')
Out[107]: <function dict.keys>
So the dict
object does have a lot of attributes, but the items access with keys aren't attributes.
Some classes also implement a __dict__
attribute, which stores user defined attributes. vars(obj)
returns that as dict. But for this dict
class:
In [108]: vars(obj)
...
TypeError: vars() argument must have __dict__ attribute
Here's a little class that has both:
In [111]: class mydict(dict):
...: pass
...:
In [112]: obj1 = mydict()
In [113]: obj1 = mydict(atrib1=1, atrib2=2)
In [114]: obj1
Out[114]: {'atrib1': 1, 'atrib2': 2}
In [115]: obj1.__dict__
Out[115]: {}
In [116]: obj1.foobar = 42
In [117]: vars(obj1)
Out[117]: {'foobar': 42}
In [118]: obj1.foobar
Out[118]: 42
In [119]: obj1['atrib1']
Out[119]: 1