Leonardo Giordani
April 08, 2015
580

# Object-Oriented Python From scratch

April 08, 2015

## Transcript

2. ### I'm a software engineer, interested in operating systems, versioning, Python

and software architecture. Coder since around 1988, Linux user since 1998, Python lover since 1999. Currently working with Python and C in the field of satellite remote sensing. about me The Digital Cat lgiordani.com https://twitter.com/ tw_lgiordani https://github.com/ lgiordani https://plus.google.com/u/ LeonardoGiordani

4. ### ABOUT THIS TUTORIAL This tutorial covers Python 3. Almost all

concepts are valid for Python 2. Relevant differences will be highlighted. Objects and types Classes and members Delegation Polymorphism Metaclasses 3

7. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

I-2 27 data = (13, 63, 5, 378, 58, 40) def avg(d): return sum(d)/len(d) avg(data) 92.83333333333333 Plain old procedures part1/01.py
8. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

I-3 27 data = (13, 63, 5, 378, 58, 40) def avg(d): return sum(d)/len(d) avg(data) 92.83333333333333 Very simple data: Very simple data: a sequence of numbers a sequence of numbers This returns new data This returns new data part1/01.py Source data enters here Source data enters here Plain old procedures
9. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

I-4 27 door1 = [1, 'closed'] door2 = [2, 'closed'] def open_door(door): door[1] = 'open' open_door(door1) door1 [1, 'open'] part1/02.py Procedures can modify data
10. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

I-5 27 door1 = [1, 'closed'] door2 = [2, 'closed'] ldoor1 = [1, 'closed', 'unlocked'] def open_door(door): door[1] = 'open' def open_ldoor(door): if door[2] == 'unlocked': door[1] = 'open' part1/03.py Things can get complicated
11. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

I-6 27 Same “action” Same “action” You must use You must use the right function the right function door1 = [1, 'closed'] door2 = [2, 'closed'] ldoor1 = [1, 'closed', 'unlocked'] def open_door(door): door[1] = 'open' def open_ldoor(door): if door[2] == 'unlocked': door[1] = 'open' open_door(door1) door1 [1, 'open'] open_ldoor(ldoor1) ldoor1 [1, 'open', 'unlocked'] part1/03.py Things can get complicated
12. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

I-7 27 Behaves Behaves like a duck like a duck Behavioural meaning The meaning of the word 'type'
13. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

I-8 27 Dissection Dissection reveals reveals the the truth truth Structural meaning The meaning of the word 'type'
14. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

I-9 27 The behavioural meaning is important
15. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

I-10 27 Duck typing: make it behave like a duck
16. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

I-11 27 Duck typing joke #1
17. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

I-12 27 Duck typing joke #2
18. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

I-13 27 The meaning of the word 'class'
19. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

I-14 27 The meaning of the word 'instance'
20. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

I-15 27 a = 6 a 6 type(a) <class 'int'> You already used classes
21. ### Python 2.x Object-oriented Python from scratch – lgiordani.com - CC

BY-SA 4.0 I-16 27 You already used classes a = 6 a 6 type(a) <type 'int'>
22. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

I-17 27 The first class part1/04.py class Door: def __init__(self, number, status): self.number = number self.status = status def open(self): self.status = 'open' def close(self): self.status = 'closed'
23. ### Python 2.x Object-oriented Python from scratch – lgiordani.com - CC

BY-SA 4.0 I-18 27 The first class class Door(object): def __init__(self, number, status): self.number = number self.status = status def open(self): self.status = 'open' def close(self): self.status = 'closed'
24. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

I-19 27 The first class part1/04.py class Door: def __init__(self, number, status): self.number = number self.status = status def open(self): self.status = 'open' def close(self): self.status = 'closed' The 'class' keyword defines the class The 'class' keyword defines the class
25. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

I-20 27 The first class part1/04.py class Door: def __init__(self, number, status): self.number = number self.status = status def open(self): self.status = 'open' def close(self): self.status = 'closed' Everything under the 'class' Everything under the 'class' keyword is part of the class keyword is part of the class
26. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

I-21 27 The first class part1/04.py class Door: def __init__(self, number, status): self.number = number self.status = status def open(self): self.status = 'open' def close(self): self.status = 'closed' Method Method
27. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

I-22 27 The first class part1/04.py class Door: def __init__(self, number, status): self.number = number self.status = status def open(self): self.status = 'open' def close(self): self.status = 'closed' Attributes Attributes Constructor (part of) Constructor (part of)
28. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

I-23 27 door1 = Door(1, 'closed') The first class class Door: def __init__(self, number, status): self.number = number self.status = status def open(self): self.status = 'open' def close(self): self.status = 'closed'
29. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

I-24 27 door1 = Door(1, 'closed') type(door1) <class '__main__.Door'> The first class class Door: def __init__(self, number, status): self.number = number self.status = status def open(self): self.status = 'open' def close(self): self.status = 'closed'
30. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

I-25 27 door1 = Door(1, 'closed') type(door1) <class '__main__.Door'> door1.number 1 door1.status 'closed' The first class class Door: def __init__(self, number, status): self.number = number self.status = status def open(self): self.status = 'open' def close(self): self.status = 'closed'
31. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

I-26 27 door1 = Door(1, 'closed') type(door1) <class '__main__.Door'> door1.number 1 door1.status 'closed' door1.open() The first class class Door: def __init__(self, number, status): self.number = number self.status = status def open(self): self.status = 'open' def close(self): self.status = 'closed'
32. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

I-27 27 door1 = Door(1, 'closed') type(door1) <class '__main__.Door'> door1.number 1 door1.status 'closed' door1.open() door1.number 1 door1.status 'open' The first class class Door: def __init__(self, number, status): self.number = number self.status = status def open(self): self.status = 'open' def close(self): self.status = 'closed'

34. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

II-2 42 Everything is an object a = 1 type(a) <class 'int'>
35. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

II-3 42 Everything is an object a = 1 type(a) <class 'int'> type(int) <class 'type'> The type of an object is The type of an object is an object itself an object itself
36. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

II-4 42 Where is the class of an object? door1 = Door(1, 'closed') door2 = Door(1, 'closed')
37. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

II-5 42 Where is the class of an object? door1 = Door(1, 'closed') door2 = Door(1, 'closed') hex(id(door1)) '0xb67e148c' hex(id(door2)) '0xb67e144c'
38. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

II-6 42 Where is the class of an object? door1 = Door(1, 'closed') door2 = Door(1, 'closed') hex(id(door1)) '0xb67e148c' hex(id(door2)) '0xb67e144c' hex(id(door1.__class__)) '0xb685f56c' hex(id(door2.__class__)) '0xb685f56c' The class is not a mere concept! The class is not a mere concept! It is an object in the system. It is an object in the system.
39. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

II-7 42 Class attributes part2/01.py class Door: colour = 'brown' def __init__(self, number, status): self.number = number self.status = status def open(self): self.status = 'open' def close(self): self.status = 'closed'
40. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

II-8 42 part2/01.py class Door: colour = 'brown' def __init__(self, number, status): self.number = number self.status = status def open(self): self.status = 'open' def close(self): self.status = 'closed' No 'self' here No 'self' here Class attributes
41. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

II-9 42 door1 = Door(1, 'closed') door2 = Door(2, 'closed') Class attributes
42. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

II-10 42 door1 = Door(1, 'closed') door2 = Door(2, 'closed') Door.colour 'brown' door1.colour 'brown' door2.colour 'brown' Class attributes
43. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

II-11 42 Door.colour = 'white' Class attributes
44. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

II-12 42 Door.colour = 'white' Door.colour 'white' door1.colour 'white' door2.colour 'white' Class attributes
45. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

II-13 42 Door.colour = 'white' Door.colour 'white' door1.colour 'white' door2.colour 'white' hex(id(Door.colour)) '0xb67e1500' hex(id(door1.colour)) '0xb67e1500' hex(id(door2.colour)) '0xb67e1500' Class attributes
46. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

II-14 42 Door.__dict__ mappingproxy({'open': <function Door.open at 0xb68604ac>, 'colour': 'white', '__dict__': <attribute '__dict__' of 'Door' objects>, '__weakref__': <attribute '__weakref__' of 'Door' objects>, '__init__': <function Door.__init__ at 0xb7062854>, '__module__': '__main__', '__doc__': None, 'close': <function Door.close at 0xb686041c>}) Class attributes
47. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

II-15 42 Door.__dict__ mappingproxy({'open': <function Door.open at 0xb68604ac>, 'colour': 'white', '__dict__': <attribute '__dict__' of 'Door' objects>, '__weakref__': <attribute '__weakref__' of 'Door' objects>, '__init__': <function Door.__init__ at 0xb7062854>, '__module__': '__main__', '__doc__': None, 'close': <function Door.close at 0xb686041c>}) door1.__dict__ {'number': 1, 'status': 'closed'} Class attributes
48. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

II-16 42 Door.__dict__ mappingproxy({'open': <function Door.open at 0xb68604ac>, 'colour': 'white', '__dict__': <attribute '__dict__' of 'Door' objects>, '__weakref__': <attribute '__weakref__' of 'Door' objects>, '__init__': <function Door.__init__ at 0xb7062854>, '__module__': '__main__', '__doc__': None, 'close': <function Door.close at 0xb686041c>}) door1.__dict__ {'number': 1, 'status': 'closed'} door1.__dict__['colour'] Traceback (most recent call last): File "<stdin>", line 1, in <module> KeyError: 'colour' Class attributes
49. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

II-17 42 Door.__dict__ mappingproxy({'open': <function Door.open at 0xb68604ac>, 'colour': 'white', '__dict__': <attribute '__dict__' of 'Door' objects>, '__weakref__': <attribute '__weakref__' of 'Door' objects>, '__init__': <function Door.__init__ at 0xb7062854>, '__module__': '__main__', '__doc__': None, 'close': <function Door.close at 0xb686041c>}) door1.__dict__ {'number': 1, 'status': 'closed'} door1.__dict__['colour'] Traceback (most recent call last): File "<stdin>", line 1, in <module> KeyError: 'colour' door1.__class__.__dict__['colour'] 'white' door1.colour is Door.colour True Class attributes
50. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

II-18 42 Door door1 door2 __getattribute__() __getattribute__() Let's dive into attribute resolution door1.colour Door.colour
51. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

II-19 42 Let's dive into attribute resolution door1 = Door(1, 'closed') door1.colour = 'white' door1.__dict__['colour'] 'white' door1.__class__.__dict__['colour'] 'brown'
52. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

II-20 42 Let's dive into attribute resolution door1 = Door(1, 'closed') door1.colour = 'white' door1.__dict__['colour'] 'white' door1.__class__.__dict__['colour'] 'brown' door1.colour 'white' Door.colour 'brown'
53. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

II-21 42 Let's dive into attribute resolution door1 = Door(1, 'closed') door1.colour = 'white' door1.__dict__['colour'] 'white' door1.__class__.__dict__['colour'] 'brown' door1.colour 'white' Door.colour 'brown' Door.colour = 'red'
54. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

II-22 42 Let's dive into attribute resolution door1 = Door(1, 'closed') door1.colour = 'white' door1.__dict__['colour'] 'white' door1.__class__.__dict__['colour'] 'brown' door1.colour 'white' Door.colour 'brown' Door.colour = 'red' door1.__dict__['colour'] 'white' door1.__class__.__dict__['colour'] 'red'
55. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

II-23 42 Door.__dict__ mappingproxy({'open': <function Door.open at 0xb68604ac>, 'colour': 'white', '__dict__': <attribute '__dict__' of 'Door' objects>, '__weakref__': <attribute '__weakref__' of 'Door' objects>, '__init__': <function Door.__init__ at 0xb7062854>, '__module__': '__main__', '__doc__': None, 'close': <function Door.close at 0xb686041c>}) door1.__dict__ {'number': 1, 'status': 'closed'} door1.colour is Door.colour True What about methods?
56. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

II-24 42 Door.__dict__ mappingproxy({'open': <function Door.open at 0xb68604ac>, 'colour': 'white', '__dict__': <attribute '__dict__' of 'Door' objects>, '__weakref__': <attribute '__weakref__' of 'Door' objects>, '__init__': <function Door.__init__ at 0xb7062854>, '__module__': '__main__', '__doc__': None, 'close': <function Door.close at 0xb686041c>}) door1.__dict__ {'number': 1, 'status': 'closed'} door1.colour is Door.colour True door1.open is Door.open False What about methods?
57. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

II-25 42 Door.__dict__ mappingproxy({'open': <function Door.open at 0xb68604ac>, 'colour': 'white', '__dict__': <attribute '__dict__' of 'Door' objects>, '__weakref__': <attribute '__weakref__' of 'Door' objects>, '__init__': <function Door.__init__ at 0xb7062854>, '__module__': '__main__', '__doc__': None, 'close': <function Door.close at 0xb686041c>}) door1.__dict__ {'number': 1, 'status': 'closed'} door1.colour is Door.colour True door1.open is Door.open False Door.__dict__['open'] <function Door.open at 0xb68604ac> Door.open <function Door.open at 0xb68604ac> What about methods?
58. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

II-26 42 Door.__dict__ mappingproxy({'open': <function Door.open at 0xb68604ac>, 'colour': 'white', '__dict__': <attribute '__dict__' of 'Door' objects>, '__weakref__': <attribute '__weakref__' of 'Door' objects>, '__init__': <function Door.__init__ at 0xb7062854>, '__module__': '__main__', '__doc__': None, 'close': <function Door.close at 0xb686041c>}) door1.__dict__ {'number': 1, 'status': 'closed'} door1.colour is Door.colour True door1.open is Door.open False Door.__dict__['open'] <function Door.open at 0xb68604ac> Door.open <function Door.open at 0xb68604ac> door1.open <bound method Door.open of <__main__.Door object at 0xb67e162c>> What about methods?
59. ### Python 2.x Object-oriented Python from scratch – lgiordani.com - CC

BY-SA 4.0 II-27 42 Door.__dict__ mappingproxy({'open': <function Door.open at 0xb68604ac>, 'colour': 'white', '__dict__': <attribute '__dict__' of 'Door' objects>, '__weakref__': <attribute '__weakref__' of 'Door' objects>, '__init__': <function Door.__init__ at 0xb7062854>, '__module__': '__main__', '__doc__': None, 'close': <function Door.close at 0xb686041c>}) door1.__dict__ {'number': 1, 'status': 'closed'} door1.colour is Door.colour True door1.open is Door.open False Door.__dict__['open'] <function Door.open at 0xb68604ac> Door.open <unbound method Door.open> door1.open <bound method Door.open of <__main__.Door object at 0xb67e162c>> What about methods?
60. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

II-28 42 Door.open() Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: open() missing 1 required positional argument: 'self' From functions to bound methods
61. ### Python 2.x Object-oriented Python from scratch – lgiordani.com - CC

BY-SA 4.0 II-29 42 Door.open() Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unbound method open() must be called with Door instance as first argument (got nothing instead) From functions to bound methods
62. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

II-30 42 Door.open() Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: open() missing 1 required positional argument: 'self' Door.open(door1) door1.status 'open' From functions to bound methods
63. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

II-31 42 Door.open() Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: open() missing 1 required positional argument: 'self' Door.open(door1) door1.status 'open' door1.__class__.__dict__['open'] <function Door.open at 0xb68604ac> From functions to bound methods
64. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

II-32 42 Door.open() Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: open() missing 1 required positional argument: 'self' Door.open(door1) door1.status 'open' door1.__class__.__dict__['open'] <function Door.open at 0xb68604ac> dir(door1.__class__.__dict__['open']) ['__annotations__', '__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__get__', '__getattribute__', '__globals__', '__gt__', '__hash__', '__init__', '__kwdefaults__', '__le__', '__lt__', '__module__', '__name__', '__ne__', '__new__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__'] From functions to bound methods
65. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

II-33 42 Door.open() Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: open() missing 1 required positional argument: 'self' Door.open(door1) door1.status 'open' door1.__class__.__dict__['open'] <function Door.open at 0xb68604ac> dir(door1.__class__.__dict__['open']) ['__annotations__', '__call__', '__class__', '__closure__', ...,'__get__',...] door1.__class__.__dict__['open'].__get__ <method-wrapper '__get__' of function object at 0xb68604ac> From functions to bound methods
66. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

II-34 42 Door.open() Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: open() missing 1 required positional argument: 'self' Door.open(door1) door1.status 'open' door1.__class__.__dict__['open'] <function Door.open at 0xb68604ac> dir(door1.__class__.__dict__['open']) ['__annotations__', '__call__', '__class__', '__closure__', ...,'__get__',...] door1.__class__.__dict__['open'].__get__ <method-wrapper '__get__' of function object at 0xb68604ac> door1.__class__.__dict__['open'].__get__(door1) <bound method Door.open of <__main__.Door object at 0xb67e162c>> From functions to bound methods
67. ### Python 2.x Object-oriented Python from scratch – lgiordani.com - CC

BY-SA 4.0 II-35 42 Door.open() Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: open() missing 1 required positional argument: 'self' Door.open(door1) door1.status 'open' door1.__class__.__dict__['open'] <function Door.open at 0xb68604ac> dir(door1.__class__.__dict__['open']) ['__annotations__', '__call__', '__class__', '__closure__', ...,'__get__',...] door1.__class__.__dict__['open'].__get__ <method-wrapper '__get__' of function object at 0xb68604ac> door1.__class__.__dict__['open'].__get__(door1) <bound method ?.open of <__main__.Door instance at 0xb6977aac>> door1.__class__.__dict__['open'].__get__(door1, Door) <bound method Door.open of <__main__.Door object at 0xb73f956c>> From functions to bound methods
68. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

II-36 42 part2/02.py class Door: colour = 'brown' def __init__(self, number, status): self.number = number self.status = status @classmethod def knock(cls): print("Knock!") def open(self): self.status = 'open' def close(self): self.status = 'closed' Class methods
69. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

II-37 42 door1 = Door(1, 'closed') door1.knock() Knock! Door.knock() Knock! From functions to bound methods
70. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

II-38 42 part2/03.py class Door: colour = 'brown' def __init__(self, number, status): self.number = number self.status = status @classmethod def knock(cls): print("Knock!") @classmethod def paint(cls, colour): cls.colour = colour def open(self): self.status = 'open' def close(self): self.status = 'closed' Class methods
71. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

II-39 42 door1 = Door(1, 'closed') door2 = Door(2, 'closed') Class methods
72. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

II-40 42 door1 = Door(1, 'closed') door2 = Door(2, 'closed') Door.colour 'brown' door1.colour 'brown' door2.colour 'brown' Class methods
73. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

II-41 42 Door.paint('white') Door.colour 'white' door1.colour 'white' door2.colour 'white' Class methods
74. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

II-42 42 Door.paint('white') Door.colour 'white' door1.colour 'white' door2.colour 'white' door1.paint('yellow') Door.colour 'yellow' door1.colour 'yellow' door2.colour 'yellow' Class methods

76. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

III-2 36 Specialization Cat Animal
77. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

III-3 36 Cat has all the features of Cat has all the features of Animal, i.e. 'moves' Animal, i.e. 'moves' Specialization Cat Animal
78. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

III-4 36 Cat can provide new features, i.e. Cat can provide new features, i.e. 'has whiskers' 'has whiskers' Specialization Cat Animal
79. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

III-5 36 Cat performs some or all the tasks performed Cat performs some or all the tasks performed by Animal in a different way, i.e. 'moves silently' by Animal in a different way, i.e. 'moves silently' Specialization Cat Animal
80. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

III-6 36 Cat implements only 'new' or Cat implements only 'new' or 'changed' features 'changed' features Cat delegates the remaining Cat delegates the remaining features to Animal features to Animal Delegation Cat Animal
81. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

III-7 36 Composition: 'has' Car Engine turn_on() Wheels steer() get_color()
82. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

III-8 36 Inheritance: 'is' look() look() Cat Animal look() mew()

III-9 36
84. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

III-10 36 Inheritance part3/01.py class SecurityDoor(Door): pass
85. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

III-11 36 Inheritance class SecurityDoor(Door): pass sdoor = SecurityDoor(1, 'closed')
86. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

III-12 36 Inheritance class SecurityDoor(Door): pass sdoor = SecurityDoor(1, 'closed') SecurityDoor.colour is Door.colour True sdoor.colour is Door.colour True
87. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

III-13 36 Inheritance class SecurityDoor(Door): pass sdoor = SecurityDoor(1, 'closed') SecurityDoor.colour is Door.colour True sdoor.colour is Door.colour True sdoor.colour sdoor.colour SecurityDoor.colour SecurityDoor.colour Door.colour Door.colour
88. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

III-14 36 Inheritance sdoor.__dict__ {'number': 1, 'status': 'closed'}
89. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

III-15 36 Inheritance sdoor.__dict__ {'number': 1, 'status': 'closed'} sdoor.__class__.__dict__ mappingproxy({'__doc__': None, '__module__': '__main__'}) Door.__dict__ mappingproxy({'__dict__': <attribute '__dict__' of 'Door' objects>, 'colour': 'yellow', 'open': <function Door.open at 0xb687e224>, '__init__': <function Door.__init__ at 0xb687e14c>, '__doc__': None, 'close': <function Door.close at 0xb687e1dc>, 'knock': <classmethod object at 0xb67ff6ac>, '__weakref__': <attribute '__weakref__' of 'Door' objects>, '__module__': '__main__', 'paint': <classmethod object at 0xb67ff6ec>})
90. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

III-16 36 Inheritance sdoor.__dict__ {'number': 1, 'status': 'closed'} sdoor.__class__.__dict__ mappingproxy({'__doc__': None, '__module__': '__main__'}) Door.__dict__ mappingproxy({'__dict__': <attribute '__dict__' of 'Door' objects>, 'colour': 'yellow', 'open': <function Door.open at 0xb687e224>, '__init__': <function Door.__init__ at 0xb687e14c>, '__doc__': None, 'close': <function Door.close at 0xb687e1dc>, 'knock': <classmethod object at 0xb67ff6ac>, '__weakref__': <attribute '__weakref__' of 'Door' objects>, '__module__': '__main__', 'paint': <classmethod object at 0xb67ff6ec>}) SecurityDoor.__bases__ (<class '__main__.Door'>,)
91. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

III-17 36 Inheritance sdoor.__dict__ {'number': 1, 'status': 'closed'} sdoor.__class__.__dict__ mappingproxy({'__doc__': None, '__module__': '__main__'}) Door.__dict__ mappingproxy({'__dict__': <attribute '__dict__' of 'Door' objects>, 'colour': 'yellow', 'open': <function Door.open at 0xb687e224>, '__init__': <function Door.__init__ at 0xb687e14c>, '__doc__': None, 'close': <function Door.close at 0xb687e1dc>, 'knock': <classmethod object at 0xb67ff6ac>, '__weakref__': <attribute '__weakref__' of 'Door' objects>, '__module__': '__main__', 'paint': <classmethod object at 0xb67ff6ec>}) SecurityDoor.__bases__ (<class '__main__.Door'>,) sdoor.knock <bound method type.knock of <class '__main__.SecurityDoor'>> sdoor.__class__.__bases__[0].__dict__['knock'].__get__(sdoor) <bound method type.knock of <class '__main__.SecurityDoor'>>
92. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

III-18 36 Overriding part3/02.py class SecurityDoor(Door): colour = 'grey' locked = True def open(self): if not self.locked: self.status = 'open'
93. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

III-19 36 Overriding part3/02.py Overriding blocks implicit Overriding blocks implicit delegation delegation class SecurityDoor(Door): colour = 'grey' locked = True def open(self): if not self.locked: self.status = 'open' SecurityDoor.__dict__ mappingproxy({'__doc__': None, '__module__': '__main__', 'open': <function SecurityDoor.open at 0xb6fcf89c>, 'colour': 'grey', 'locked': True})
94. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

III-20 36 Overriding part3/03.py class SecurityDoor(Door): colour = 'grey' locked = True def open(self): if self.locked: return Door.open(self)
95. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

III-21 36 Overriding part3/03.py class SecurityDoor(Door): colour = 'grey' locked = True def open(self): if self.locked: return Door.open(self) sdoor = SecurityDoor(1, 'closed') sdoor.status 'closed'
96. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

III-22 36 Overriding part3/03.py class SecurityDoor(Door): colour = 'grey' locked = True def open(self): if self.locked: return Door.open(self) sdoor = SecurityDoor(1, 'closed') sdoor.status 'closed' sdoor.open() sdoor.status 'closed'
97. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

III-23 36 Overriding part3/03.py class SecurityDoor(Door): colour = 'grey' locked = True def open(self): if self.locked: return Door.open(self) sdoor = SecurityDoor(1, 'closed') sdoor.status 'closed' sdoor.open() sdoor.status 'closed' sdoor.locked = False sdoor.open() sdoor.status 'open'
98. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

III-24 36 Avoid strong coupling part3/04.py class SecurityDoor(Door): colour = 'grey' locked = True def open(self): if self.locked: return super().open()
99. ### Python 2.x Object-oriented Python from scratch – lgiordani.com - CC

BY-SA 4.0 III-25 36 class SecurityDoor(Door): colour = 'grey' locked = True def open(self): if self.locked: return super(SecurityDoor, self).open(self) Avoid strong coupling
100. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

III-26 36 class SecurityDoor: colour = 'grey' locked = True def __init__(self, number, status): self.door = Door(number, status) def open(self): if self.locked: return self.door.open() def close(self): self.door.close() Composition part3/05.py
101. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

III-27 36 class SecurityDoor: colour = 'grey' locked = True def __init__(self, number, status): self.door = Door(number, status) def open(self): if self.locked: return self.door.open() def close(self): Self.door.close() sdoor = SecurityDoor(1, 'closed') sdoor.status Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'SecurityDorr' object has no attribute 'status' Composition part3/05.py
102. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

III-28 36 class SecurityDoor: colour = 'grey' locked = True def __init__(self, number, status): self.door = Door(number, status) def open(self): if self.locked: return self.door.open() def close(self): self.door.close() def get_status(self): return self.door.status status = property(get_status) sdoor = SecurityDoor(1, 'closed') sdoor.status 'closed' Composition
103. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

III-29 36 Python magic to the rescue class SecurityDoor: colour = 'grey' locked = True def __init__(self, number, status): self.door = Door(number, status) def open(self): if self.locked: return self.door.open() def close(self): self.door.close() def __getattr__(self, attr): return getattr(self.door, attr) sdoor = SecurityDoor(1, 'closed') sdoor.status 'closed' part3/06.py
104. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

III-30 36 Python magic to the rescue class SecurityDoor: colour = 'grey' locked = True def __init__(self, number, status): self.door = Door(number, status) def open(self): if self.locked: return self.door.open() #def close(self): # self.door.close() def __getattr__(self, attr): return getattr(self.door, attr) part3/07.py
105. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

III-31 36 class ComposedDoor: def __init__(self, number, status): self.door = Door(number, status) def __getattr__(self, attr): return getattr(self.door, attr) Composed inheritance? part3/08.py
106. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

III-32 36 getattr() l = [1,2,3] dir(l) ['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
107. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

III-33 36 getattr() l = [1,2,3] dir(l) ['__add__', '__class__', '__contains__', '__delattr__', ..., 'append', 'clear', 'copy', ...] l.append <built-in method append of list object at 0xb70a2c2c>
108. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

III-34 36 getattr() l = [1,2,3] dir(l) ['__add__', '__class__', '__contains__', '__delattr__', ..., 'append', 'clear', 'copy', ...] l.append <built-in method append of list object at 0xb70a2c2c> a = l.append a <built-in method append of list object at 0xb70a2c2c>
109. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

III-35 36 getattr() l = [1,2,3] dir(l) ['__add__', '__class__', '__contains__', '__delattr__', ..., 'append', 'clear', 'copy', ...] l.append <built-in method append of list object at 0xb70a2c2c> a = l.append a <built-in method append of list object at 0xb70a2c2c> b = getattr(l, 'append') b <built-in method append of list object at 0xb70a2c2c>
110. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

III-36 36 getattr() l = [1,2,3] dir(l) ['__add__', '__class__', '__contains__', '__delattr__', ..., 'append', 'clear', 'copy', ...] l.append <built-in method append of list object at 0xb70a2c2c> a = l.append a <built-in method append of list object at 0xb70a2c2c> b = getattr(l, 'append') b <built-in method append of list object at 0xb70a2c2c> a == b True a is b False

112. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

IV-2 34 References a = 5 a 5
113. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

IV-3 34 References a = 5 a 5 type(a) <class 'int'> hex(id(a)) '0x83fe540'
114. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

IV-4 34 References a = 5 a 5 type(a) <class 'int'> hex(id(a)) '0x83fe540' a = 'five' a 'five'
115. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

IV-5 34 References a = 5 a 5 type(a) <class 'int'> hex(id(a)) '0x83fe540' a = 'five' a 'five' type(a) <class 'str'> hex(id(a)) '0xb70d6560'
116. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

IV-6 34 References a = 5 a 5 type(a) <class 'int'> hex(id(a)) '0x83fe540' a = 'five' a 'five' type(a) <class 'str'> hex(id(a)) '0xb70d6560' Strong Strong type system: every type system: every variable has a type variable has a type
117. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

IV-7 34 References a = 5 a 5 type(a) <class 'int'> hex(id(a)) '0x83fe540' a = 'five' a 'five' type(a) <class 'str'> hex(id(a)) '0xb70d6560' Dynamic Dynamic type system: the type type system: the type changes with the content changes with the content
118. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

IV-8 34 Every variable is a reference def echo(a): return a part4/01.py
119. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

IV-9 34 Every variable is a reference def echo(a): return a echo(5) 5 echo('five') 'five' part4/01.py
120. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

IV-10 34 5 + 6 11 What is polymorphism?
121. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

IV-11 34 5 + 6 11 5.5 + 6.6 12.1 What is polymorphism?
122. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

IV-12 34 5 + 6 11 5.5 + 6.6 12.1 "just a" + " string" 'just a string' What is polymorphism?
123. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

IV-13 34 5 + 6 11 5.5 + 6.6 12.1 "just a" + " string" 'just a string' [1,2,3] + [4,5,6] [1, 2, 3, 4, 5, 6] (1,2,3) + (4,5,6) (1, 2, 3, 4, 5, 6) What is polymorphism?
124. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

IV-14 34 5 + 6 11 5.5 + 6.6 12.1 "just a" + " string" 'just a string' [1,2,3] + [4,5,6] [1, 2, 3, 4, 5, 6] (1,2,3) + (4,5,6) (1, 2, 3, 4, 5, 6) {'a':4, 'b':5} + {'c':7} Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unsupported operand type(s) for +: 'dict' and 'dict' What is polymorphism?
125. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

IV-15 34 s = "Just a sentence" len(s) 15 l = [1, 2, 3] len(l) 3 d = {'a': 1, 'b': 2} len(d) 2 What is polymorphism?
126. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

IV-16 34 s = "Just a sentence" len(s) 15 l = [1, 2, 3] len(l) 3 d = {'a': 1, 'b': 2} len(d) 2 i = 5 len(i) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: object of type 'int' has no len() What is polymorphism?
127. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

IV-17 34 s.__len__() 15 l.__len__() 3 d.__len__() 2 What is polymorphism?
128. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

IV-18 34 s.__len__() 15 l.__len__() 3 d.__len__() 2 i.__len__() Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'int' object has no attribute '__len__' What is polymorphism?
129. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

IV-19 34 [1,2,3].__add__([4,5,6]) [1, 2, 3, 4, 5, 6] Polymorphism is based on delegation
130. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

IV-20 34 [1,2,3].__add__([4,5,6]) [1, 2, 3, 4, 5, 6] dir([1,2,3]) ['__add__', '__class__', '__contains__', ...] Polymorphism is based on delegation
131. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

IV-21 34 [1,2,3].__add__([4,5,6]) [1, 2, 3, 4, 5, 6] dir([1,2,3]) ['__add__', '__class__', '__contains__', ...] 1 in [1,2,3] True [1,2,3].__contains__(1) True Polymorphism is based on delegation
132. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

IV-22 34 [1,2,3].__add__([4,5,6]) [1, 2, 3, 4, 5, 6] dir([1,2,3]) ['__add__', '__class__', '__contains__', ...] 1 in [1,2,3] True [1,2,3].__contains__(1) True 6 in [1,2,3] False [1,2,3].__contains__(6) False Polymorphism is based on delegation
133. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

IV-23 34 def sum(a, b): return a + b Polymorphism is based on delegation part4/02.py
134. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

IV-24 34 def sum(a, b): return a + b sum(5,6) 11 sum("Being ", "polymorphic") 'Being polymorphic' sum([1,2,3], [4,5,6]) [1, 2, 3, 4, 5, 6] Polymorphism is based on delegation part4/02.py
135. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

IV-25 34 def sum(a, b): return a + b sum(5,6) 11 sum("Being ", "polymorphic") 'Being polymorphic' sum([1,2,3], [4,5,6]) [1, 2, 3, 4, 5, 6] sum([1,2,3], 8) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 2, in sum TypeError: can only concatenate list (not "int") to list Polymorphism is based on delegation part4/02.py
136. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

IV-26 34 class Room: def __init__(self, door): self.door = door def open(self): self.door.open() def close(self): self.door.close() def is_open(self): return self.door.is_open() Polymorphism in action part4/03.py
137. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

IV-27 34 class Door: def __init__(self): self.status = "closed" def open(self): self.status = "open" def close(self): self.status = "closed" def is_open(self): return self.status == "open" Polymorphism in action part4/03.py
138. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

IV-28 34 class BooleanDoor: def __init__(self): self.status = True def open(self): self.status = True def close(self): self.status = False def is_open(self): return self.status Polymorphism in action part4/03.py
139. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

IV-29 34 door = Door() bool_door = BooleanDoor() Polymorphism in action
140. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

IV-30 34 door = Door() bool_door = BooleanDoor() room = Room(door) bool_room = Room(bool_door) Polymorphism in action
141. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

IV-31 34 door = Door() bool_door = BooleanDoor() room = Room(door) bool_room = Room(bool_door) room.open() room.is_open() True room.close() room.is_open() False Polymorphism in action
142. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

IV-32 34 door = Door() bool_door = BooleanDoor() room = Room(door) bool_room = Room(bool_door) room.open() room.is_open() True room.close() room.is_open() False bool_room.open() bool_room.is_open() True bool_room.close() bool_room.is_open() False Polymorphism in action
143. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

IV-33 34 “Ask for permission” style if hasattr(someobj, 'open'): [...] else: [...] It It has has the attribute the attribute
144. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

IV-34 34 “Ask for permission” style try: someobj.open() [...] except AttributeError: [...] It It behaves behaves like it has like it has the attribute the attribute

146. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

V-2 20 Everything is an object (again) a = 5 type(a) <class 'int'> a.__class__ <class 'int'> a.__class__.__bases__ (<class 'object'>,) object.__bases__ ()
147. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

V-3 20 Everything is an object (again) a = 5 type(a) <class 'int'> a.__class__ <class 'int'> a.__class__.__bases__ (<class 'object'>,) object.__bases__ () 'int' 'int' inherits from inherits from (its base is) 'object' (its base is) 'object' 'a' 'a' is an is an instance of instance of (its type is) 'int' (its type is) 'int' object int a
148. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

V-4 20 Everything is an object (again) a = 5 type(a) <class 'int'> a.__class__ <class 'int'> a.__class__.__bases__ (<class 'object'>,) object.__bases__ () Inheritance Inheritance: 'int' finds : 'int' finds here attributes and here attributes and methods methods Instance Instance: 'a' : 'a' description as a description as a class is here class is here object int a
149. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

V-5 20 Everything is an object (again) type(a) <class 'int'> type(int) <class 'type'> object int a
150. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

V-6 20 Everything is an object (again) type(a) <class 'int'> type(int) <class 'type'> type(float) <class 'type'> type(dict) <class 'type'> object int a
151. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

V-7 20 Everything is an object (again) type(a) <class 'int'> type(int) <class 'type'> type(float) <class 'type'> type(dict) <class 'type'> object a type int int
152. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

V-8 20 Everything is an object (again) type(a) <class 'int'> type(int) <class 'type'> type(float) <class 'type'> type(dict) <class 'type'> object a type int int 'int' 'int' inherits inherits from from (its base is) (its base is) 'object' 'object' 'int' 'int' is an instance of is an instance of (its type is) 'type' (its type is) 'type'
153. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

V-9 20 Everything is an object (again) type(a) <class 'int'> type(int) <class 'type'> type(float) <class 'type'> type(dict) <class 'type'> object a type int int 'int' finds here 'int' finds here attributes and attributes and methods methods 'int' description as a 'int' description as a class is here class is here
154. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

V-10 20 Food for thought type(object) <class 'type'> type.__bases__ (<class 'object'>,)
155. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

V-11 20 Food for thought type(object) <class 'type'> type.__bases__ (<class 'object'>,) object type
156. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

V-12 20 type(object) <class 'type'> type.__bases__ (<class 'object'>,) type(type) <class 'type'> object type Fatality
157. ### Python 2.x Object-oriented Python from scratch – lgiordani.com - CC

BY-SA 4.0 V-13 20 type(object) <class 'type'> type.__bases__ (<class 'object'>,) type(type) <type 'type'> object type Fatality
158. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

V-14 20 Metaclasses class MyType(type): pass class MySpecialClass(metaclass=MyType): pass part5/01.py
159. ### Python 2.x Object-oriented Python from scratch – lgiordani.com - CC

BY-SA 4.0 V-15 20 Metaclasses class MyType(type): pass class MySpecialClass(object): __metaclass__ = MyType
160. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

V-16 20 Metaclasses class MyType(type): pass class MySpecialClass(metaclass=MyType): pass msp = MySpecialClass() type(msp) <class '__main__.MySpecialClass'>
161. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

V-17 20 Metaclasses class MyType(type): pass class MySpecialClass(metaclass=MyType): pass msp = MySpecialClass() type(msp) <class '__main__.MySpecialClass'> type(MySpecialClass) <class '__main__.MyType'> MySpecialClass.__bases__ (<class 'object'>,)
162. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

V-18 20 Metaclasses in action: singleton part5/02.py class Singleton(type): instance = None def __call__(cls, *args, **kw): if not cls.instance: cls.instance = super(Singleton, cls). __call__(*args, **kw) return cls.instance class ASingleton(metaclass=Singleton): pass
163. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

V-19 20 Metaclasses in action: singleton part5/02.py class Singleton(type): instance = None def __call__(cls, *args, **kw): if not cls.instance: cls.instance = super(Singleton, cls). __call__(*args, **kw) return cls.instance class ASingleton(metaclass=Singleton): pass a = ASingleton() b = ASingleton()
164. ### Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0

V-20 20 Metaclasses in action: singleton part5/02.py class Singleton(type): instance = None def __call__(cls, *args, **kw): if not cls.instance: cls.instance = super(Singleton, cls). __call__(*args, **kw) return cls.instance class ASingleton(metaclass=Singleton): pass a = ASingleton() b = ASingleton() a is b True hex(id(a)) '0xb68030ec' hex(id(b)) '0xb68030ec'
165. ### A lot of people provided free information and code Font

aswesome icons by Freepik Python 3 OOP series http://lgiordani.com/blog/categories/python3/ Some links about Python OOP http://goo.gl/UBdJDT CAST