Why should you know “In python, Everything is an Object”?
I generally prefer to a read book rather than video tutorials. In my beginning days of journey to python I encountered the phrase — “In python everything is an object” in many of the text books. It is similar to the way I code and think about python.
Before diving into this post, let us know about object in python.
Everything in Python is an object, and almost everything has attributes and methods. All functions have a built-in attribute __doc__
, which returns the doc string defined in the function's source code. The sys module is an object which has (among other things) an attribute called path. And so forth.
There is many definition of “object” in different programming languages. Some languages Gurus’ say that all object must have attributes and/or methods. And rest of them says objects are subclassable (means that you can inherit from them).
However, in python the definition is not so strict. Some objects in python neither have objects nor methods. Another notable difference in python with other language is that all objects in python is not subclassable.
To sum up, everything in python or anything you created in python can be assigned to a variable and can passed it as an arguments to any callables (say functions/classes). Because of this property, Python is also called first-class object.
Illustrations:
# create a list
alist = [3, 5, 7, 8]# lets create another list using same list
blist = alist# Now print both valuesprint("Before perfoming any operations:")
print("alist: ", alist)
print("blist: ", blist)# Its time to do some operation on these list. lets append new object in list
alist.append(23)# again print both valuesprint("After append operation")
print("alist: ", alist)
print("blist: ", blist)
Outputs
Before performing any operations:
alist: [3, 5, 7, 8]
blist: [3, 5, 7, 8]After append operation:
alist: [3, 5, 7, 8, 33]
blist: [3, 5, 7, 8, 33]
Note the operation we did on “alist” list and result on both (alist, blist) list. Though we did operation on “alist” object we found it appended value 23 (which itself called int object in python) on “blist” also.
This result motivated me to think on how actually python works. After a small research I came to know that it is happening because “In python everything is an object”. Let me clarify this by adding couple line of code in previous example:
print("ID of alist: ", id(alist))
print("ID of blist: ", id(blist))Outputs:
ID of alist: 4844897928
ID of blist: 4844897928
Did you notice that both list have same id? Yes, this is first step to know how “Everything in python is an object.”
Let me introduce these things in real example which we implement repeatedly.
Example:
fruits = ["Avocardo", "Kiwis"]
prices = [300, 400]fruits_detail = {}fruits_detail_list = []for fruit, price in zip(fruits, prices):
fruits_detail["Name"] = fruit
fruits_detail["Price"] = price
fruits_detail_list.append(fruits_detail)print("List of fruits details: ")
print(fruits_detail_list)
Question: What is your expected output?
Possibly expected answer:
List of fruits details:
[{“Name”: “Avocardo”, “Price”: 300}, {“Name”: “Kiwis”, “Price”: 400}]
Question: What is your real output?
Answer:
List of fruits details:
[{“Name”: “Kiwis”, “Price”: 400}, {“Name”: “Kiwis”, “Price”: 400}]
In my programming career when I faced this issue, I spent more that 5 hours to fixed it. At some instance I even changed my mind to skip it and try other stuffs to achieve the goal. But thanks to my decision that I made at that time; I decided to find out what’s wrong in this above code. And yes finally I came to know that it was my silly mistake and big fault.
Then I realized that why should I know “In python, Everything is an Object”?
Yes, the main mantras/solution to this problem is the same phrase that I stated in title of this post i.e Why should you know “In python, Everything is an Object”?
Lets have a deep look on above problem.
fruits = ["Avocardo", "Kiwis"]
prices = [300, 400]
fruits_detail = {}fruits_detail_list = []print("Information of fruits_detail inside for loop")for fruit, price in zip(fruits, prices):
fruits_detail["Name"] = fruit
fruits_detail["Price"] = price
print("fruits_detail in each loop: ", fruits_detail)
print("fruits_detail id: ", id(fruits_detail))
fruits_detail_list.append(fruits_detail)
print("--------------------------------")print("List of fruits details: ")
print("fruits_detail_list": fruits_detail_list)
print("fruits_detail id: ", id(fruits_detail))
Output:
Information of fruits_detail inside for loop
fruits_detail in each loop: {‘Name’: ‘Avocardo’, ‘Price’: 300}
fruits_detail id: 4845794720
fruits_detail in each loop: {‘Name’: ‘Kiwis’, ‘Price’: 400}
fruits_detail id: 4845794720
— — — — — — — — — — — — — — — —
List of fruits details:
fruits_detail_list: [{‘Name’: ‘Kiwis’, ‘Price’: 400}, {‘Name’: ‘Kiwis’, ‘Price’: 400}]
fruits_detail id: 4845794720
Key points from above output:
- In each loop we get unique value for fruits_detail object i.e
{‘Name’: ‘Avocardo’, ‘Price’: 300} and {‘Name’: ‘Kiwis’, ‘Price’: 400}
2. Also in all loop, the id of fruits_detail object is same i.e. 4845794720
3. But when we print the result of fruits_detail_list, the fruits_detail object with unique value (from point 1) which is appended in fruits_detail_list is not printing the unique value inside it.
fruits_detail_list: [{‘Name’: ‘Kiwis’, ‘Price’: 400}, {‘Name’: ‘Kiwis’, ‘Price’: 400}]
Also we can see the id of fruits_detail after the for loop which is same as in for loop.
Issue in above example:
The appended objects i.e, fruits_detail is not actually unique at all. It is just updating the same object and fruits_detail_list is simply pointing to updated fruits_detail in its result.
How to solve this problem?
From the above discussion we came to know that appending the same object will results unexpected output (lastly updated output has been saw in output). See above image for reference.
To fix this we can create new object inside a loop and just do shallow copy of that object (fruits_detail). And than append new object in fruits_detail_list gives me the unique value in fruits_detail_list. It is because, in each loop new object will be created which means that newly created object inside will have new object_id.
Final code:
fruits_detail = {}fruits_detail_list = []print("Information of fruits_detail inside for loop")for fruit, price in zip(fruits, prices):
temp_fruits_detail = fruits_detail.copy() #shallow copy
temp_fruits_detail["Name"] = fruit
temp_fruits_detail["Price"] = price
print("fruits_detail in each loop: ", temp_fruits_detail)
print("fruits_detail id: ", id(temp_fruits_detail))
fruits_detail_list.append(temp_fruits_detail)
print("--------------------------------")print("List of fruits details: ")
print("fruits_detail_list: ", fruits_detail_list)
Output:
Information of fruits_detail inside for loop
fruits_detail in each loop: {‘Name’: ‘Avocardo’, ‘Price’: 300}
fruits_detail id: 4845867944
fruits_detail in each loop: {‘Name’: ‘Kiwis’, ‘Price’: 400}
fruits_detail id: 4844859752
— — — — — — — — — — — — — — — —
List of fruits details:
fruits_detail_list: [{‘Name’: ‘Avocardo’, ‘Price’: 300}, {‘Name’: ‘Kiwis’, ‘Price’: 400}]
Yeah, we get the desired output here.
Conclusion
The zen of this post is to know what is an object in python and how it behaves in the python interpreter. You should always keep it in mind that whenever you create new containers using any object, make it sure that the original object (which you are using to create new container) did not get updated through out your code. If there is the situation to update your object, I recommend you to create any temporary object which will be the copy of original object (you can you either shallpw or deep copy as well)so that the change in original object will not affect newly created container object.