In [37]:
# How do the dot operator work in Python

from holding import Holding


h = Holding('AA', '201608-09', 100, 67.9)

In [38]:
h.name


Out[38]:
'AA'

In [39]:
h.shares


Out[39]:
100
Out[39]:
100

In [40]:
# What is happening under the hood when dot operator is used
"""
-- Every instance has a __dict__ attributes that keeps a record of the instance attributes.
"""
h.__dict__


Out[40]:
{'date': '201608-09', 'name': 'AA', 'price': 67.9, 'shares': 100}
Out[40]:
{'date': '201608-09', 'name': 'AA', 'price': 67.9, 'shares': 100}

In [41]:
# Any operation on the instance attribute uses the __dict__ attribute to access the attribute
h.__dict__['name']


Out[41]:
'AA'
Out[41]:
'AA'

In [42]:
h.__dict__['shares']

In [43]:
# Add a new attribute
h.__dict__['yow'] = 'dummy'

In [44]:
h.yow


Out[44]:
'dummy'

In [45]:
h.__dict__


Out[45]:
{'date': '201608-09',
 'name': 'AA',
 'price': 67.9,
 'shares': 100,
 'yow': 'dummy'}

In [46]:
del h.__dict__['yow']

In [46]:
h.__dict__


Out[46]:
{'date': '201608-09', 'name': 'AA', 'price': 67.9, 'shares': 100}

In [48]:
# The functions in the class are not part of the __dict__ of the instance
# It is part of the __dict__ attribute of the class
h.__class__.__dict__

In [49]:
Holding.__dict__

In [50]:
# Here also when the function is accessed, the __dict__ attribute is used under the hood.
h.cost()

In [51]:
# The above is equivalent to 
Holding.__dict__['cost'](h)


Out[51]:
6790.000000000001

In [52]:
# Python does not impose restriction on adding, setting attributes
# There is no notion of private, protected attributes
# So how to ensure this in Python. This is what we are going to learn next.

In [ ]: