Slide 1

Slide 1 text

OBJECT-ORIENTED PYTHON From scratch Leonardo Giordani lgiordani.com OOP

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

import users import talk assert all([a >= users.beginner for a in talk.attendees]) about_you.py

Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

https://github.com/lgiordani/oopy Code available as IPython Notebooks

Slide 6

Slide 6 text

PART 1 Objects and types

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

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'

Slide 13

Slide 13 text

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'

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0 I-15 27 a = 6 a 6 type(a) You already used classes

Slide 21

Slide 21 text

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)

Slide 22

Slide 22 text

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'

Slide 23

Slide 23 text

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'

Slide 24

Slide 24 text

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

Slide 25

Slide 25 text

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

Slide 26

Slide 26 text

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

Slide 27

Slide 27 text

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)

Slide 28

Slide 28 text

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'

Slide 29

Slide 29 text

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0 I-24 27 door1 = Door(1, 'closed') type(door1) 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'

Slide 30

Slide 30 text

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0 I-25 27 door1 = Door(1, 'closed') type(door1) 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'

Slide 31

Slide 31 text

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0 I-26 27 door1 = Door(1, 'closed') type(door1) 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'

Slide 32

Slide 32 text

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0 I-27 27 door1 = Door(1, 'closed') type(door1) 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'

Slide 33

Slide 33 text

PART 2 Classes and members

Slide 34

Slide 34 text

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0 II-2 42 Everything is an object a = 1 type(a)

Slide 35

Slide 35 text

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

Slide 36

Slide 36 text

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')

Slide 37

Slide 37 text

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'

Slide 38

Slide 38 text

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.

Slide 39

Slide 39 text

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'

Slide 40

Slide 40 text

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

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

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

Slide 43

Slide 43 text

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

Slide 44

Slide 44 text

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

Slide 45

Slide 45 text

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

Slide 46

Slide 46 text

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0 II-14 42 Door.__dict__ mappingproxy({'open': , 'colour': 'white', '__dict__': , '__weakref__': , '__init__': , '__module__': '__main__', '__doc__': None, 'close': }) Class attributes

Slide 47

Slide 47 text

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0 II-15 42 Door.__dict__ mappingproxy({'open': , 'colour': 'white', '__dict__': , '__weakref__': , '__init__': , '__module__': '__main__', '__doc__': None, 'close': }) door1.__dict__ {'number': 1, 'status': 'closed'} Class attributes

Slide 48

Slide 48 text

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0 II-16 42 Door.__dict__ mappingproxy({'open': , 'colour': 'white', '__dict__': , '__weakref__': , '__init__': , '__module__': '__main__', '__doc__': None, 'close': }) door1.__dict__ {'number': 1, 'status': 'closed'} door1.__dict__['colour'] Traceback (most recent call last): File "", line 1, in KeyError: 'colour' Class attributes

Slide 49

Slide 49 text

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0 II-17 42 Door.__dict__ mappingproxy({'open': , 'colour': 'white', '__dict__': , '__weakref__': , '__init__': , '__module__': '__main__', '__doc__': None, 'close': }) door1.__dict__ {'number': 1, 'status': 'closed'} door1.__dict__['colour'] Traceback (most recent call last): File "", line 1, in KeyError: 'colour' door1.__class__.__dict__['colour'] 'white' door1.colour is Door.colour True Class attributes

Slide 50

Slide 50 text

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

Slide 51

Slide 51 text

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'

Slide 52

Slide 52 text

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'

Slide 53

Slide 53 text

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'

Slide 54

Slide 54 text

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'

Slide 55

Slide 55 text

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0 II-23 42 Door.__dict__ mappingproxy({'open': , 'colour': 'white', '__dict__': , '__weakref__': , '__init__': , '__module__': '__main__', '__doc__': None, 'close': }) door1.__dict__ {'number': 1, 'status': 'closed'} door1.colour is Door.colour True What about methods?

Slide 56

Slide 56 text

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0 II-24 42 Door.__dict__ mappingproxy({'open': , 'colour': 'white', '__dict__': , '__weakref__': , '__init__': , '__module__': '__main__', '__doc__': None, 'close': }) door1.__dict__ {'number': 1, 'status': 'closed'} door1.colour is Door.colour True door1.open is Door.open False What about methods?

Slide 57

Slide 57 text

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0 II-25 42 Door.__dict__ mappingproxy({'open': , 'colour': 'white', '__dict__': , '__weakref__': , '__init__': , '__module__': '__main__', '__doc__': None, 'close': }) door1.__dict__ {'number': 1, 'status': 'closed'} door1.colour is Door.colour True door1.open is Door.open False Door.__dict__['open'] Door.open What about methods?

Slide 58

Slide 58 text

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0 II-26 42 Door.__dict__ mappingproxy({'open': , 'colour': 'white', '__dict__': , '__weakref__': , '__init__': , '__module__': '__main__', '__doc__': None, 'close': }) door1.__dict__ {'number': 1, 'status': 'closed'} door1.colour is Door.colour True door1.open is Door.open False Door.__dict__['open'] Door.open door1.open > What about methods?

Slide 59

Slide 59 text

Python 2.x Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0 II-27 42 Door.__dict__ mappingproxy({'open': , 'colour': 'white', '__dict__': , '__weakref__': , '__init__': , '__module__': '__main__', '__doc__': None, 'close': }) door1.__dict__ {'number': 1, 'status': 'closed'} door1.colour is Door.colour True door1.open is Door.open False Door.__dict__['open'] Door.open door1.open > What about methods?

Slide 60

Slide 60 text

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

Slide 61

Slide 61 text

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 "", line 1, in TypeError: unbound method open() must be called with Door instance as first argument (got nothing instead) From functions to bound methods

Slide 62

Slide 62 text

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

Slide 63

Slide 63 text

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

Slide 64

Slide 64 text

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0 II-32 42 Door.open() Traceback (most recent call last): File "", line 1, in TypeError: open() missing 1 required positional argument: 'self' Door.open(door1) door1.status 'open' door1.__class__.__dict__['open'] 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

Slide 65

Slide 65 text

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

Slide 66

Slide 66 text

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0 II-34 42 Door.open() Traceback (most recent call last): File "", line 1, in TypeError: open() missing 1 required positional argument: 'self' Door.open(door1) door1.status 'open' door1.__class__.__dict__['open'] dir(door1.__class__.__dict__['open']) ['__annotations__', '__call__', '__class__', '__closure__', ...,'__get__',...] door1.__class__.__dict__['open'].__get__ door1.__class__.__dict__['open'].__get__(door1) > From functions to bound methods

Slide 67

Slide 67 text

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 "", line 1, in TypeError: open() missing 1 required positional argument: 'self' Door.open(door1) door1.status 'open' door1.__class__.__dict__['open'] dir(door1.__class__.__dict__['open']) ['__annotations__', '__call__', '__class__', '__closure__', ...,'__get__',...] door1.__class__.__dict__['open'].__get__ door1.__class__.__dict__['open'].__get__(door1) > door1.__class__.__dict__['open'].__get__(door1, Door) > From functions to bound methods

Slide 68

Slide 68 text

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

Slide 69

Slide 69 text

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

Slide 70

Slide 70 text

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

Slide 71

Slide 71 text

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

Slide 72

Slide 72 text

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

Slide 73

Slide 73 text

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

Slide 74

Slide 74 text

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

Slide 75

Slide 75 text

PART 3 Delegation

Slide 76

Slide 76 text

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

Slide 77

Slide 77 text

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

Slide 78

Slide 78 text

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

Slide 79

Slide 79 text

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

Slide 80

Slide 80 text

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

Slide 81

Slide 81 text

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()

Slide 82

Slide 82 text

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0 III-8 36 Inheritance: 'is' look() look() Cat Animal look() mew()

Slide 83

Slide 83 text

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

Slide 84

Slide 84 text

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

Slide 85

Slide 85 text

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

Slide 86

Slide 86 text

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

Slide 87

Slide 87 text

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

Slide 88

Slide 88 text

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

Slide 89

Slide 89 text

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__': , 'colour': 'yellow', 'open': , '__init__': , '__doc__': None, 'close': , 'knock': , '__weakref__': , '__module__': '__main__', 'paint': })

Slide 90

Slide 90 text

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__': , 'colour': 'yellow', 'open': , '__init__': , '__doc__': None, 'close': , 'knock': , '__weakref__': , '__module__': '__main__', 'paint': }) SecurityDoor.__bases__ (,)

Slide 91

Slide 91 text

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__': , 'colour': 'yellow', 'open': , '__init__': , '__doc__': None, 'close': , 'knock': , '__weakref__': , '__module__': '__main__', 'paint': }) SecurityDoor.__bases__ (,) sdoor.knock > sdoor.__class__.__bases__[0].__dict__['knock'].__get__(sdoor) >

Slide 92

Slide 92 text

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'

Slide 93

Slide 93 text

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': , 'colour': 'grey', 'locked': True})

Slide 94

Slide 94 text

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)

Slide 95

Slide 95 text

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'

Slide 96

Slide 96 text

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'

Slide 97

Slide 97 text

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'

Slide 98

Slide 98 text

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()

Slide 99

Slide 99 text

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

Slide 100

Slide 100 text

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

Slide 101

Slide 101 text

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 "", line 1, in AttributeError: 'SecurityDorr' object has no attribute 'status' Composition part3/05.py

Slide 102

Slide 102 text

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

Slide 103

Slide 103 text

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

Slide 104

Slide 104 text

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

Slide 105

Slide 105 text

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

Slide 106

Slide 106 text

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']

Slide 107

Slide 107 text

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

Slide 108

Slide 108 text

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 a = l.append a

Slide 109

Slide 109 text

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 a = l.append a b = getattr(l, 'append') b

Slide 110

Slide 110 text

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 a = l.append a b = getattr(l, 'append') b a == b True a is b False

Slide 111

Slide 111 text

PART 4 Polymorphism

Slide 112

Slide 112 text

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

Slide 113

Slide 113 text

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

Slide 114

Slide 114 text

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

Slide 115

Slide 115 text

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

Slide 116

Slide 116 text

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

Slide 117

Slide 117 text

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

Slide 118

Slide 118 text

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

Slide 119

Slide 119 text

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

Slide 120

Slide 120 text

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

Slide 121

Slide 121 text

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?

Slide 122

Slide 122 text

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?

Slide 123

Slide 123 text

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?

Slide 124

Slide 124 text

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 "", line 1, in TypeError: unsupported operand type(s) for +: 'dict' and 'dict' What is polymorphism?

Slide 125

Slide 125 text

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?

Slide 126

Slide 126 text

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 "", line 1, in TypeError: object of type 'int' has no len() What is polymorphism?

Slide 127

Slide 127 text

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?

Slide 128

Slide 128 text

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 "", line 1, in AttributeError: 'int' object has no attribute '__len__' What is polymorphism?

Slide 129

Slide 129 text

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

Slide 130

Slide 130 text

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

Slide 131

Slide 131 text

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

Slide 132

Slide 132 text

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

Slide 133

Slide 133 text

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

Slide 134

Slide 134 text

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

Slide 135

Slide 135 text

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 "", line 1, in File "", line 2, in sum TypeError: can only concatenate list (not "int") to list Polymorphism is based on delegation part4/02.py

Slide 136

Slide 136 text

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

Slide 137

Slide 137 text

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

Slide 138

Slide 138 text

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

Slide 139

Slide 139 text

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

Slide 140

Slide 140 text

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

Slide 141

Slide 141 text

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

Slide 142

Slide 142 text

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

Slide 143

Slide 143 text

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

Slide 144

Slide 144 text

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

Slide 145

Slide 145 text

PART 5 Metaclasses

Slide 146

Slide 146 text

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

Slide 147

Slide 147 text

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0 V-3 20 Everything is an object (again) a = 5 type(a) a.__class__ a.__class__.__bases__ (,) 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

Slide 148

Slide 148 text

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0 V-4 20 Everything is an object (again) a = 5 type(a) a.__class__ a.__class__.__bases__ (,) 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

Slide 149

Slide 149 text

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

Slide 150

Slide 150 text

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

Slide 151

Slide 151 text

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

Slide 152

Slide 152 text

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

Slide 153

Slide 153 text

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0 V-9 20 Everything is an object (again) type(a) type(int) type(float) type(dict) 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

Slide 154

Slide 154 text

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

Slide 155

Slide 155 text

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

Slide 156

Slide 156 text

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0 V-12 20 type(object) type.__bases__ (,) type(type) object type Fatality

Slide 157

Slide 157 text

Python 2.x Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0 V-13 20 type(object) type.__bases__ (,) type(type) object type Fatality

Slide 158

Slide 158 text

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

Slide 159

Slide 159 text

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

Slide 160

Slide 160 text

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)

Slide 161

Slide 161 text

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) type(MySpecialClass) MySpecialClass.__bases__ (,)

Slide 162

Slide 162 text

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

Slide 163

Slide 163 text

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()

Slide 164

Slide 164 text

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'

Slide 165

Slide 165 text

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

Slide 166

Slide 166 text

OBJECT-ORIENTED PYTHON From scratch Leonardo Giordani lgiordani.com OOP