Share
Embed
Execution model and other must-know's
Session in Python Bcn Meetup, Beginners session
>> Contents:
- Python execution model
- Everything is an object
- Everything is a pointer (or a reference)
- Mutable vs. immutable objects
- Common errors
>> Code examples:
https://github.com/pablito56/pybcn-beginners
Pablo E
March 20, 2014
Transcript
43 slides
-
{ Execution model and other must-‐‑know’s “event”:
“Python BCN Meetup – Beginners session” “author”: “Pablo Enfedaque” “twi5er”: “@pablitoev56” -
{ “event”: “Python BCN Meetup”, “author”: “Pablo Enfedaque”, “twi5er”: “@pablitoev56”}
> Today we are going to see: > Python execution model > Everything is an object > Everything is a pointer (or a reference) > Mutable vs. immutable objects Welcome to Python! -
{ “event”: “Python BCN Meetup”, “author”: “Pablo Enfedaque”, “twi5er”: “@pablitoev56”}
Let’s start with a simple module -
{ “event”: “Python BCN Meetup”, “author”: “Pablo Enfedaque”, “twi5er”: “@pablitoev56”}
a_simple_module.py #-*- coding: utf-8 -*- "pybcn basic module example" # Module docstring from random import randint # An import class MyClass(object): # A class declaration def __init__(self, attr1, attr2): self.attr1 = attr1 self.attr2 = attr2 def random_instance(): # A function declaration "Create an instance of MyClass with random values" attr1_val = randint(0, 10) attr2_val = randint(0, 10) return MyClass(attr1_val, attr2_val) # We execute some statements inst = random_instance() print "Instance:", inst, inst.attr1, inst.attr2 -
{ “event”: “Python BCN Meetup”, “author”: “Pablo Enfedaque”, “twi5er”: “@pablitoev56”}
> Modules can contain any kind and any number of valid Python statements > Classes declaration > Functions declaration > Logical control constructions (if, for, while...) > Function calls > Assignments and instantiations > Etc. Python modules -
{ “event”: “Python BCN Meetup”, “author”: “Pablo Enfedaque”, “twi5er”: “@pablitoev56”}
Let’s execute this module me@myhost:~/wspace/beginners$ python a_simple_module.py Instance: <__main__.MyClass object at 0x10210b390> 2 5 me@myhost:~/wspace/beginners$ python a_simple_module.py Instance: <__main__.MyClass object at 0x10104c390> 6 3 me@myhost:~/wspace/beginners$ python a_simple_module.py Instance: <__main__.MyClass object at 0x11004a390> 9 4 -
{ “event”: “Python BCN Meetup”, “author”: “Pablo Enfedaque”, “twi5er”: “@pablitoev56”}
Let’s import this module me@myhost:~/wspace/beginners$ python Python 2.7.5 (default, Aug 25 2013, 00:04:04) [GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.0.68)] on darwin Type "help", "copyright", "credits" or "license" for more ... >>> from a_simple_module import random_instance Instance: <a_simple_module.MyClass object at 0x10083b490> 0 4 >>> from a_simple_module import random_instance >>> another_inst = random_instance() >>> print another_inst, another_inst.attr1, another_inst.attr2 <a_simple_module.MyClass object at 0x10083b510> 5 8 -
{ “event”: “Python BCN Meetup”, “author”: “Pablo Enfedaque”, “twi5er”: “@pablitoev56”}
> Modules are the basic unit of code reusability > We can reuse the content of modules with import Python modules import module_name from package import module_name from package.module_name import name from module_name import name as another_name -
{ “event”: “Python BCN Meetup”, “author”: “Pablo Enfedaque”, “twi5er”: “@pablitoev56”}
Let’s import again the module me@myhost:~/wspace/beginners$ python Python 2.7.5 (default, Aug 25 2013, 00:04:04) [GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.0.68)] on darwin Type "help", "copyright", "credits" or "license" for more ... >>> from a_simple_module import random_instance Instance: <a_simple_module.MyClass object at 0x10083b490> 0 4 >>> from a_simple_module import random_instance >>> another_inst = random_instance() >>> print another_inst, another_inst.attr1, another_inst.attr2 <a_simple_module.MyClass object at 0x10083b510> 5 8 me@myhost:~/wspace/beginners$ python Python 2.7.5 (default, Aug 25 2013, 00:04:04) [GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.0.68)] on darwin Type "help", "copyright", "credits" or "license" for more ... >>> from a_simple_module import inst Instance: <a_simple_module.MyClass object at 0x10d305490> 6 3 -
{ “event”: “Python BCN Meetup”, “author”: “Pablo Enfedaque”, “twi5er”: “@pablitoev56”}
> When a module is imported for first time Python interprets (executes) all its content > Classes declaration > Functions declaration > Logical control constructions (if, for, while...) > Function calls > Assignments and instantiations > Etc. Python execution model -
{ “event”: “Python BCN Meetup”, “author”: “Pablo Enfedaque”, “twi5er”: “@pablitoev56”}
Let’s modify our simple module #-*- coding: utf-8 -*- "pybcn basic module example” from random import randint class MyClass(object): def __init__(self, attr1, attr2): self.attr1 = attr1 self.attr2 = attr2 def random_instance(): "Create an instance of MyClass with random values" attr1_val = randint(0, 10) attr2_val = randint(0, 10) return MyClass(attr1_val, attr2_val) # We execute some statements inst = random_instance() print "Instance:", inst, inst.attr1, inst.attr2 -
{ “event”: “Python BCN Meetup”, “author”: “Pablo Enfedaque”, “twi5er”: “@pablitoev56”}
a_main_module.py #-*- coding: utf-8 -*- "pybcn main module example” from random import randint class MyClass(object): def __init__(self, attr1, attr2): self.attr1 = attr1 self.attr2 = attr2 def random_instance(): "Create an instance of MyClass with random values" attr1_val = randint(0, 10) attr2_val = randint(0, 10) return MyClass(attr1_val, attr2_val) if __name__ == "__main__": # Only run when module is executed inst = random_instance() print "Instance:", inst, inst.attr1, inst.attr2 -
{ “event”: “Python BCN Meetup”, “author”: “Pablo Enfedaque”, “twi5er”: “@pablitoev56”}
Let’s import the new module me@myhost:~/wspace/beginners$ python Python 2.7.5 (default, Aug 25 2013, 00:04:04) [GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.0.68)] on darwin Type "help", "copyright", "credits" or "license" for more ... >>> from a_main_module import random_instance >>> another_inst = random_instance() >>> print another_inst, another_inst.attr1, another_inst.attr2 <a_main_module.MyClass object at 0x1082191d0> 4 4 me@myhost:~/wspace/beginners$ python Python 2.7.5 (default, Aug 25 2013, 00:04:04) [GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.0.68)] on darwin Type "help", "copyright", "credits" or "license" for more ... >>> from a_main_module import inst Traceback (most recent call last): File "<stdin>", line 1, in <module> ImportError: cannot import name inst -
{ “event”: “Python BCN Meetup”, “author”: “Pablo Enfedaque”, “twi5er”: “@pablitoev56”}
> When a module is imported for first time Python interprets (executes) all its content > Check the name of the module in __name__ > This global module a5ribute has value __main__ when a module is directly executed (instead of imported) Python execution model -
{ “event”: “Python BCN Meetup”, “author”: “Pablo Enfedaque”, “twi5er”: “@pablitoev56”}
All code is interpreted, also the if #-*- coding: utf-8 -*- "pybcn main module example” from random import randint class MyClass(object): def __init__(self, attr1, attr2): self.attr1 = attr1 self.attr2 = attr2 def random_instance(): "Create an instance of MyClass with random values" attr1_val = randint(0, 10) attr2_val = randint(0, 10) return MyClass(attr1_val, attr2_val) if __name__ == "__main__": # Only run when module is executed inst = random_instance() print "Instance:", inst, inst.attr1, inst.attr2 -
{ “event”: “Python BCN Meetup”, “author”: “Pablo Enfedaque”, “twi5er”: “@pablitoev56”}
another_module.py #-*- coding: utf-8 -*- "pybcn another main module example” from random import randint class MyClass(object): def __init__(self, attr1, attr2): self.attr1 = attr1 self.attr2 = attr2 def random_instance(): "Create an instance of MyClass with random values" attr1_val = randint(0, 10) attr2_val = randint(0, 10) return MyClass(attr1_val, attr2_val) if False: # Never interpreted!! inst = random_instance() print "Instance:", inst, inst.attr1, inst.attr2 -
{ “event”: “Python BCN Meetup”, “author”: “Pablo Enfedaque”, “twi5er”: “@pablitoev56”}
Let’s use this module me@myhost:~/wspace/beginners$ python another_module.py me@myhost:~/wspace/beginners$ python another_module.py me@myhost:~/wspace/beginners$ python Python 2.7.5 (default, Aug 25 2013, 00:04:04) [GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.0.68)] on darwin Type "help", "copyright", "credits" or "license" for more ... >>> from another_module import random_instance >>> another_inst = random_instance() >>> print another_inst, another_inst.attr1, another_inst.attr2 <another_module.MyClass object at 0x10d6e4510> 10 10 >>> from another_module import inst Traceback (most recent call last): File "<stdin>", line 1, in <module> ImportError: cannot import name inst -
{ “event”: “Python BCN Meetup”, “author”: “Pablo Enfedaque”, “twi5er”: “@pablitoev56”}
Ok, but… why everything is interpreted? -
{ “event”: “Python BCN Meetup”, “author”: “Pablo Enfedaque”, “twi5er”: “@pablitoev56”}
Let’s use the interpreter me@myhost:~/wspace/beginners$ python Python 2.7.5 (default, Aug 25 2013, 00:04:04) [GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.0.68)] on darwin Type "help", "copyright", "credits" or "license" for more ... >>> def a_func(arg): ... "This is a function" ... return arg + arg ... >>> a_func(2) 4 >>> print a_func.func_doc This is a function >>> print a_func.func_name a_func >>> print type(a_func), isinstance(a_func, object) <type 'function'> True -
{ “event”: “Python BCN Meetup”, “author”: “Pablo Enfedaque”, “twi5er”: “@pablitoev56”}
> In Python everything is an object > For Python there is no difference between… > An instantiation calls the class constructor and the result is a new instance (object) of that class > The def keyword and all its statements are interpreted and the result is a new function object > The class keyword and all its statements are interpreted and the result is a new class object Python execution model -
{ “event”: “Python BCN Meetup”, “author”: “Pablo Enfedaque”, “twi5er”: “@pablitoev56”}
Everything is an object #-*- coding: utf-8 -*- "pybcn main module example” from random import randint class MyClass(object): def __init__(self, attr1, attr2): self.attr1 = attr1 self.attr2 = attr2 def random_instance(): "Create an instance of MyClass with random values" attr1_val = randint(0, 10) attr2_val = randint(0, 10) return MyClass(attr1_val, attr2_val) if __name__ == "__main__": # Only run when module is executed inst = random_instance() print "Instance:", inst, inst.attr1, inst.attr2 -
{ “event”: “Python BCN Meetup”, “author”: “Pablo Enfedaque”, “twi5er”: “@pablitoev56”}
Everything is an object #-*- coding: utf-8 -*- "pybcn main module example” from random import randint class MyClass(object): def __init__(self, attr1, attr2): self.attr1 = attr1 self.attr2 = attr2 def random_instance(): "Create an instance of MyClass with random values" attr1_val = randint(0, 10) attr2_val = randint(0, 10) return MyClass(attr1_val, attr2_val) if __name__ == "__main__": # Only run when module is executed inst = random_instance() print "Instance:", inst, inst.attr1, inst.attr2 -
{ “event”: “Python BCN Meetup”, “author”: “Pablo Enfedaque”, “twi5er”: “@pablitoev56”}
id_function_is_example.py #-*- coding: utf-8 -*- "pybcn 'id' function and 'is' example" class MyClass(object): def __init__(self, attr1, attr2): self.attr1 = attr1 self.attr2 = attr2 inst1 = MyClass(1, 1) inst2 = MyClass(2, 2) inst3 = inst1 # Copy # 'id' function returns the unique identity of an object print "Instance 1:", id(inst1), inst1.attr1, inst1.attr2 print "Instance 2:", id(inst2), inst2.attr1, inst2.attr2 print "Instance 3:", id(inst3), inst3.attr1, inst3.attr2 print inst1 is inst3 # 'is' compares the identity -
{ “event”: “Python BCN Meetup”, “author”: “Pablo Enfedaque”, “twi5er”: “@pablitoev56”}
Did we copy the object? #-*- coding: utf-8 -*- "pybcn 'id' function and 'is' example" class MyClass(object): def __init__(self, attr1, attr2): self.attr1 = attr1 self.attr2 = attr2 inst1 = MyClass(1, 1) inst2 = MyClass(2, 2) inst3 = inst1 # Copy? # 'id' function returns the unique identity of an object print "Instance 1:", id(inst1), inst1.attr1, inst1.attr2 print "Instance 2:", id(inst2), inst2.attr1, inst2.attr2 print "Instance 3:", id(inst3), inst3.attr1, inst3.attr2 print inst1 is inst3 # 'is' compares the identity me@myhost:~/wspace/beginners$ python id_function_is_example.py Instance 1: 4424626832 1 1 Instance 2: 4424626896 2 2 Instance 3: 4424626832 1 1 True -
{ “event”: “Python BCN Meetup”, “author”: “Pablo Enfedaque”, “twi5er”: “@pablitoev56”}
No, we just copied the reference -
{ “event”: “Python BCN Meetup”, “author”: “Pablo Enfedaque”, “twi5er”: “@pablitoev56”}
> Every object has an unchangeable identity > In Python names are references bound to an object > Assignments only copy the reference to an object > Shallow copy is the default behaviour in Python > Otherwise, use copy.deepcopy method > Function calls only pass the reference to the arguments > You access the same object outside and inside a call > The same applies for return values Python execution model -
{ “event”: “Python BCN Meetup”, “author”: “Pablo Enfedaque”, “twi5er”: “@pablitoev56”}
everything_is_a_pointer.py #-*- coding: utf-8 -*- "pybcn 'everything is a pointer' example" class MyClass(object): def __init__(self, attr1, attr2): self.attr1 = attr1 self.attr2 = attr2 def print_id_and_return(attr): print "Attr id:", id(attr) return attr inst = MyClass(3, 4) print "Instance:", id(inst) ret_val = print_id_and_return(inst) print inst is ret_val me@myhost:~/wspace/beginners$ python everything_is_a_pointer.py Instance: 4306146128 Attr id: 4306146128 True -
{ “event”: “Python BCN Meetup”, “author”: “Pablo Enfedaque”, “twi5er”: “@pablitoev56”}
h5p://pythontutor.com/ visualize.html -
{ “event”: “Python BCN Meetup”, “author”: “Pablo Enfedaque”, “twi5er”: “@pablitoev56”}
Let’s modify some objects value -
{ “event”: “Python BCN Meetup”, “author”: “Pablo Enfedaque”, “twi5er”: “@pablitoev56”}
modify_objects_value.py #-*- coding: utf-8 -*- "pybcn modify objects value example” txt1 = "This is text" print id(txt1), txt1 txt2 = txt1 + " and more text" # Which object is txt2? print id(txt2), txt2 print "-" * 5 int1 = 7 print id(int1), int1 int1 += 11 # Which object is int1? print id(int1), int1 print "-" * 5 list1 = ["a", "b", "c"] print id(list1), list1 list1.extend([0, 1, 2]) # In place modification list1[0] = "XXX" print id(list1), list1 -
{ “event”: “Python BCN Meetup”, “author”: “Pablo Enfedaque”, “twi5er”: “@pablitoev56”}
Assignment copies the ref. to an object! #-*- coding: utf-8 -*- "pybcn modify objects value example” txt1 = "This is text" print id(txt1), txt1 txt2 = txt1 + " and more text" # Which object is txt2? print id(txt2), txt2 print "-" * 5 int1 = 7 print id(int1), int1 int1 += 11 # Which object is int1? print id(int1), int1 print "-" * 5 list1 = ["a", "b", "c"] print id(list1), list1 list1.extend([0, 1, 2]) # In place modification list1[0] = "XXX" print id(list1), list1 $ python modify_objects_value.py 4335119080 This is text 4335161776 This is text and more text ----- 140435402066344 7 140435402066080 18 ----- 4335009736 ['a', 'b', 'c'] 4335009736 ['XXX', 'b', 'c', 0, 1, 2] -
{ “event”: “Python BCN Meetup”, “author”: “Pablo Enfedaque”, “twi5er”: “@pablitoev56”}
> Objects whose value can change are mutable > dicts, lists, sets > They allow in-‐‑place modifications (append in a list, pop in a dictionary...) > They can not be hashed (used as dict keys) > Objects whose value is unchangeable once they are created are called immutable > numbers, strings, tuples, NoneType, boolean Mutables vs. immutables -
{ “event”: “Python BCN Meetup”, “author”: “Pablo Enfedaque”, “twi5er”: “@pablitoev56”}
Ignorance can lead to bugs... -
{ “event”: “Python BCN Meetup”, “author”: “Pablo Enfedaque”, “twi5er”: “@pablitoev56”}
mutables_vs_immutables_1.py #-*- coding: utf-8 -*- "pybcn mutables assignment bug example” list1 = ["a", "b", "c"] print "list1", list1, "@", id(list1) print "-" * 5 list3 = list2 = list1 list2.append("x") print "list1", list1, "@", id(list1) print "list2", list2, "@", id(list2) print "list3", list3, "@", id(list3) print "-" * 5 mtrx1 = [[1, 1, 1], [2, 2, 2]] print "mtrx1", mtrx1, "@", id(mtrx1) print "-" * 5 mtrx2 = list(mtrx1) mtrx2[0].append("a") print "mtrx1", mtrx1, "@", id(mtrx1) print "mtrx2", mtrx2, "@", id(mtrx2) print "-" * 5 print "mtrx1[0]", mtrx1[0], "@", id(mtrx1[0]) print "mtrx2[0]", mtrx2[0], "@", id(mtrx2[0]) -
{ “event”: “Python BCN Meetup”, “author”: “Pablo Enfedaque”, “twi5er”: “@pablitoev56”}
Shallow copy uses ref. to same object #-*- coding: utf-8 -*- "pybcn mutables assignment bug example” list1 = ["a", "b", "c"] print "list1", list1, "@", id(list1) print "-" * 5 list3 = list2 = list1 list2.append("x") print "list1", list1, "@", id(list1) print "list2", list2, "@", id(list2) print "list3", list3, "@", id(list3) print "-" * 5 mtrx1 = [[1, 1, 1], [2, 2, 2]] print "mtrx1", mtrx1, "@", id(mtrx1) print "-" * 5 mtrx2 = list(mtrx1) mtrx2[0].append("a") print "mtrx1", mtrx1, "@", id(mtrx1) print "mtrx2", mtrx2, "@", id(mtrx2) print "-" * 5 print "mtrx1[0]", mtrx1[0], "@", id(mtrx1[0]) print "mtrx2[0]", mtrx2[0], "@", id(mtrx2[0]) $ python mutables_vs_immutables_1.py list1 ['a', 'b', 'c'] @ 4536893384 ----- list1 ['a', 'b', 'c', 'x'] @ 4536893384 list2 ['a', 'b', 'c', 'x'] @ 4536893384 list3 ['a', 'b', 'c', 'x'] @ 4536893384 ----- mtrx1 [[1, 1, 1], [2, 2, 2]] @ 4537042920 ----- mtrx1 [[1, 1, 1, 'a'], [2, 2, 2]] @ 4537042920 mtrx2 [[1, 1, 1, 'a'], [2, 2, 2]] @ 4537043928 ----- mtrx1[0] [1, 1, 1, 'a'] @ 4536943320 mtrx2[0] [1, 1, 1, 'a'] @ 4536943320 -
{ “event”: “Python BCN Meetup”, “author”: “Pablo Enfedaque”, “twi5er”: “@pablitoev56”}
mutables_vs_immutables_2.py #-*- coding: utf-8 -*- "pybcn class attributes bug example" class ExampleClass(object): list_attr = [] int_attr = 0 instA = ExampleClass() instB = ExampleClass() instA.int_attr += 1 instA.list_attr.extend([5, 7, 9]) print "instA.int_attr:", instA.int_attr print "instA.list_attr:", instA.list_attr print "-" * 5 print "instB.int_attr:", instB.int_attr print "instB.list_attr:", instB.list_attr print "-" * 5 print instA.list_attr is instB.list_attr print ExampleClass.list_attr -
{ “event”: “Python BCN Meetup”, “author”: “Pablo Enfedaque”, “twi5er”: “@pablitoev56”}
Class a5ributes remain in the class #-*- coding: utf-8 -*- "pybcn class attributes bug example" class ExampleClass(object): list_attr = [] int_attr = 0 instA = ExampleClass() instB = ExampleClass() instA.int_attr += 1 instA.list_attr.extend([5, 7, 9]) print "instA.int_attr:", instA.int_attr print "instA.list_attr:", instA.list_attr print "-" * 5 print "instB.int_attr:", instB.int_attr print "instB.list_attr:", instB.list_attr print "-" * 5 print instA.list_attr is instB.list_attr print ExampleClass.list_attr $ python mutables_vs_immutables_2.py instA.int_attr: 1 instA.list_attr: [5, 7, 9] ----- instB.int_attr: 0 instB.list_attr: [5, 7, 9] ----- True [5, 7, 9] -
{ “event”: “Python BCN Meetup”, “author”: “Pablo Enfedaque”, “twi5er”: “@pablitoev56”}
mutables_vs_immutables_3.py #-*- coding: utf-8 -*- "pybcn function default attribute bug example" def add_power_to_list(item, powers_lst=[]): powers_lst.append(item ** 2) return powers_lst print "default:", add_power_to_list.func_defaults print "-" * 5 result1 = add_power_to_list(2) print "result1:", result1 print "-" * 5 result2 = add_power_to_list(3) print "result1:", result1, 'vs', "result2", result2 print result1 is result2 print "-" * 5 print "default:", add_power_to_list.func_defaults -
{ “event”: “Python BCN Meetup”, “author”: “Pablo Enfedaque”, “twi5er”: “@pablitoev56”}
Functions default values remain in the function #-*- coding: utf-8 -*- "pybcn function default attribute bug example" def add_power_to_list(item, powers_lst=[]): powers_lst.append(item ** 2) return powers_lst print "default:", add_power_to_list.func_defaults print "-" * 5 result1 = add_power_to_list(2) print "result1:", result1 print "-" * 5 result2 = add_power_to_list(3) print "result1:", result1, 'vs', "result2", result2 print result1 is result2 print "-" * 5 print "default:", add_power_to_list.func_defaults $ python mutables_vs_immutables_3.py default: ([],) ----- result1: [4] ----- result1: [4, 9] vs result2 [4, 9] True ----- default: ([4, 9],) -
{ “event”: “Python BCN Meetup”, “author”: “Pablo Enfedaque”, “twi5er”: “@pablitoev56”}
> Shallow copy uses the reference to the object > Assignment, constructor by copy, arguments in function calls > Be aware of it > Class a5ributes remain in the class > Create instance mutable aPributes in __init__ > Functions default values remain in the function > Create mutable default values inside the function Mutables vs. immutables bugs -
{ “event”: “Python BCN Meetup”, “author”: “Pablo Enfedaque”, “twi5er”: “@pablitoev56”}
> Modules can contain anything > All lines of code are interpreted > Check __name__ > Everything is an object > Names are pointers bound to objects > Mutable and immutable objects > Take care with common bugs Conclusions -
{ “event”: “Python BCN Meetup”, “author”: “Pablo Enfedaque”, “twi5er”: “@pablitoev56”}
Q&A Thanks for coming! Slides: h5ps://speakerdeck.com/pablito56/ execution-‐‑model-‐‑and-‐‑other-‐‑must-‐‑knows Code: h5ps://github.com/pablito56/pybcn-‐‑ beginners