Slide 1

Slide 1 text

Dive into Object-oriented Python Leonardo Giordani lgiordani.com DjangoCon Europe 2015 – Cardiff, Wales

Slide 2

Slide 2 text

https://github.com/lgiordani/oopy IPython Notebooks DjangoCon_Europe_2015/notebooks Python 3 code DjangoCon_Europe_2015/code/python3 Python 2 code DjangoCon_Europe_2015/notebooks

Slide 3

Slide 3 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 4

Slide 4 text

import levels from djce2015 import oop_workshop def can_understand(user): return user.level >= levels.BEGINNER for you in oop_workshop.attendees: assert can_understand(you) about_you.py

Slide 5

Slide 5 text

ABOUT THIS TUTORIAL 3 Objects and types Classes and members Delegation Polymorphism

Slide 6

Slide 6 text

PART 1 Objects and types

Slide 7

Slide 7 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 data = (13, 63, 5, 378, 58, 40) def avg(d): return sum(d)/len(d) >>> avg(data) 92.83333333333333 Plain old procedures

Slide 8

Slide 8 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 door1 = [1, 'closed'] door2 = [2, 'closed'] def open_door(door): door[1] = 'open' >>> open_door(door1) >>> door1 [1, 'open'] Procedures can modify data

Slide 9

Slide 9 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 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' Things can get complicated

Slide 10

Slide 10 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 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'] Things can get complicated

Slide 11

Slide 11 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 Behavioural meaning The meaning of the word 'type'

Slide 12

Slide 12 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 Structural meaning The meaning of the word 'type'

Slide 13

Slide 13 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 The behavioural meaning is important

Slide 14

Slide 14 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 The meaning of the word 'class'

Slide 15

Slide 15 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 The meaning of the word 'instance'

Slide 16

Slide 16 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 >>> a = 6 >>> a 6 >>> type(a) >>> a = int(6) >>> a 6 >>> a.__class__ You already used classes

Slide 17

Slide 17 text

Python 2.x Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 You already used classes >>> a = 6 >>> a 6 >>> type(a) >>> a = int(6) >>> a 6 >>> a.__class__

Slide 18

Slide 18 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 H om ew ork 1. Find some types that Python provides out of the box. 2. Can you create a float variable without using the '.' character? 3. What is the difference between {1,2,3} and {'a':1, 'b':2}?

Slide 19

Slide 19 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 H om ew ork 1. Find some types that Python provides out of the box. >>> type(4) >>> type(4.5) >>> type('some words') >>> type([1,2,3,4]) >>> type((1,2,3,4)) >>> type({1,2,3,4}) >>> type({'first name':'Ray', 'last name':'Stantz'}) >>> type(True)

Slide 20

Slide 20 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 H om ew ork 2. Can you create a float variable without using the '.' character? >>> a = float(4) >>> type(a)

Slide 21

Slide 21 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 H om ew ork 3. What is the difference between {1,2,3} and {'a':1, 'b':2}? >>> type({1,2,3}) >>> type({'a':1, 'b':2})

Slide 22

Slide 22 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 >>> door1 = Door(1, 'closed') >>> type(door1) Keep data and functions together

Slide 23

Slide 23 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 >>> door1 = Door(1, 'closed') >>> type(door1) >>> door1.number 1 >>> door1.status 'closed' Keep data and functions together

Slide 24

Slide 24 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 >>> door1 = Door(1, 'closed') >>> type(door1) >>> door1.number 1 >>> door1.status 'closed' >>> door1.open() Keep data and functions together

Slide 25

Slide 25 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 >>> door1 = Door(1, 'closed') >>> type(door1) >>> door1.number 1 >>> door1.status 'closed' >>> door1.open() >>> door1.number 1 >>> door1.status 'open' Keep data and functions together

Slide 26

Slide 26 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 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 27

Slide 27 text

Python 2.x Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 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 28

Slide 28 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 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

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 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

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 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

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 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

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 >>> 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 33

Slide 33 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 >>> 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 34

Slide 34 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 >>> 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 35

Slide 35 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 >>> 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 36

Slide 36 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 >>> 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 37

Slide 37 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 H om ew ork 1. Create a ColouredDoor class that has the 'colour' attribute. 2. Create a ClosedDoor class that has a default status of 'closed'. 3. Create a ToggleDoor class that has a method toggle() that toggles the status of the door.

Slide 38

Slide 38 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 H om ew ork 1. Create a ColouredDoor class that has the 'colour' attribute. class ColouredDoor: def __init__(self, number, status, colour): self.number = number self.status = status self.colour = colour def open(self): self.status = 'open' def close(self): self.status = 'closed'

Slide 39

Slide 39 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 H om ew ork 2. Create a ClosedDoor class that has a default status of 'closed'. class ClosedDoor: def __init__(self, number, status='closed'): self.number = number self.status = status def open(self): self.status = 'open' def close(self): self.status = 'closed'

Slide 40

Slide 40 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 H om ew ork 3. Create a ToggleDoor class that has a method toggle() that toggles the status of the door. class ToggleDoor: def __init__(self, number, status): self.number = number self.status = status def open(self): self.status = 'open' def close(self): self.status = 'closed' def toggle(self): d = {'open': 'closed', 'closed': 'open'} self.status = d[self.status]

Slide 41

Slide 41 text

PART 2 Classes and members

Slide 42

Slide 42 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 Where is the class of an object? >>> door1 = Door(1, 'closed') >>> door2 = Door(1, 'closed')

Slide 43

Slide 43 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 Where is the class of an object? >>> door1 = Door(1, 'closed') >>> door2 = Door(1, 'closed') >>> hex(id(door1)) '0xb67e148c' >>> hex(id(door2)) '0xb67e144c'

Slide 44

Slide 44 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 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'

Slide 45

Slide 45 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 Class attributes 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 46

Slide 46 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 >>> door1 = Door(1, 'closed') >>> door2 = Door(2, 'closed') Class attributes

Slide 47

Slide 47 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 >>> door1 = Door(1, 'closed') >>> door2 = Door(2, 'closed') >>> Door.colour 'brown' >>> door1.colour 'brown' >>> door2.colour 'brown' Class attributes

Slide 48

Slide 48 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 >>> Door.colour = 'white' Class attributes

Slide 49

Slide 49 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 >>> Door.colour = 'white' >>> Door.colour 'white' >>> door1.colour 'white' >>> door2.colour 'white' Class attributes

Slide 50

Slide 50 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 >>> 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 51

Slide 51 text

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

Slide 52

Slide 52 text

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

Slide 53

Slide 53 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 >>> 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 54

Slide 54 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 >>> 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 55

Slide 55 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 Door door1 door2 __getattribute__() __getattribute__() Let's dive into attribute resolution door1.colour Door.colour

Slide 56

Slide 56 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 Let's dive into attribute resolution >>> door1 = Door(1, 'closed') >>> door1.colour = 'white' >>> door1.__dict__['colour'] 'white' >>> door1.__class__.__dict__['colour'] 'brown'

Slide 57

Slide 57 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 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 58

Slide 58 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 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 59

Slide 59 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 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 60

Slide 60 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 H om ew ork 1. Modify the Door class adding a class attribute 'status' with value 'undefined'. Does it work? What happens to instances? 2. Modify the Door class adding a class attribute 'status' with value 'closed' and remove status from __init__(). Does it work? 3. Add a toggle() method to the previous class. What happens if you call toggle() on a fresh instance? Why?

Slide 61

Slide 61 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 H om ew ork 1. Modify the Door class adding a class attribute 'status' with value 'undefined'. Does it work? What happens to instances? class Door: colour = 'brown' status = 'undefined' def __init__(self, number, status): self.number = number self.status = status def open(self): self.status = 'open' def close(self): self.status = 'closed'

Slide 62

Slide 62 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 H om ew ork 2. Modify the Door class adding a class attribute 'status' with value 'closed' and remove status from __init__(). Does it work? class Door: colour = 'brown' status = 'closed' def __init__(self, number): self.number = number def open(self): self.status = 'open' def close(self): self.status = 'closed'

Slide 63

Slide 63 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 H om ew ork 3. Add a toggle() method to the previous class. What happens if you call toggle() on a fresh instance? Why? class Door: colour = 'brown' status = 'closed' def __init__(self, number): self.number = number def toggle(self): d = {'open': 'closed', 'closed': 'open'} self.status = d[self.status]

Slide 64

Slide 64 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 >>> 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 65

Slide 65 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 >>> 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 66

Slide 66 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 >>> 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 67

Slide 67 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 >>> 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 68

Slide 68 text

Python 2.x Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 >>> 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 69

Slide 69 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 >>> 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 70

Slide 70 text

Python 2.x Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 >>> 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 71

Slide 71 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 >>> 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 72

Slide 72 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 >>> 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 73

Slide 73 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 >>> 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 74

Slide 74 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 >>> 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 75

Slide 75 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 >>> 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 76

Slide 76 text

Python 2.x Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 >>> 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 77

Slide 77 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 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 78

Slide 78 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 >>> door1 = Door(1, 'closed') >>> door1.knock() Knock! >>> Door.knock() Knock! From functions to bound methods

Slide 79

Slide 79 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 H om ew ork 1. Modify the Door class adding a class method 'paint' that accepts a 'colour' argument and changes the class attribute 'colour'. 2. Modify the Door class adding both a class method 'paint' and a standard method 'paint'. What happens?

Slide 80

Slide 80 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 H om ew ork 1. Modify the Door class adding a class method 'paint' that accepts a 'colour' argument and changes the class attribute 'colour'. class Door: colour = 'brown' def __init__(self, number, status): self.number = number self.status = status @classmethod def paint(cls, colour): cls.colour = colour def open(self): self.status = 'open' def close(self): self.status = 'closed'

Slide 81

Slide 81 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 H om ew ork 2. Modify the Door class adding both a class method 'paint' and a standard method 'paint'. What happens? class Door: colour = 'brown' def __init__(self, number, status): self.number = number self.status = status @classmethod def paint(cls, colour): cls.colour = colour def paint(self, colour): self.colour = colour [...]

Slide 82

Slide 82 text

PART 3 Delegation

Slide 83

Slide 83 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 Specialization Cat Animal

Slide 84

Slide 84 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 Cat has all the features of Cat has all the features of Animal, i.e. 'moves' Animal, i.e. 'moves' Specialization Cat Animal

Slide 85

Slide 85 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 Cat may provide new features, i.e. Cat may provide new features, i.e. 'has whiskers' 'has whiskers' Specialization Cat Animal

Slide 86

Slide 86 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 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 87

Slide 87 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 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 88

Slide 88 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 Composition: 'has' Car Engine turn_on() Wheels steer() get_color()

Slide 89

Slide 89 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 Inheritance: 'is' look() look() Cat Animal look() mew()

Slide 90

Slide 90 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0

Slide 91

Slide 91 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 Inheritance class SecurityDoor(Door): pass

Slide 92

Slide 92 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 Inheritance class SecurityDoor(Door): pass >>> sdoor = SecurityDoor(1, 'closed')

Slide 93

Slide 93 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 Inheritance class SecurityDoor(Door): pass >>> sdoor = SecurityDoor(1, 'closed') >>> SecurityDoor.colour is Door.colour True >>> sdoor.colour is Door.colour True

Slide 94

Slide 94 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 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 95

Slide 95 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 Inheritance >>> sdoor.__dict__ {'number': 1, 'status': 'closed'}

Slide 96

Slide 96 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 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 97

Slide 97 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 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 98

Slide 98 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 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 99

Slide 99 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 Overriding class SecurityDoor(Door): colour = 'grey' locked = True def open(self): if not self.locked: self.status = 'open'

Slide 100

Slide 100 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 Overriding 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 101

Slide 101 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 H om ew ork 1. Modify the SecurityDoor class adding a custom close_and_lock() method that changes status to 'closed' and locked to True. Test it. 2. Modify the SecurityDoor class adding a custom close() method that accepts a locked flag (with default). 3. Modify the SecurityDoor class adding a custom __init__() method that sets self.locked.

Slide 102

Slide 102 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 H om ew ork 1. Modify the SecurityDoor class adding a custom close_and_lock() method that changes status to 'closed' and locked to True. Test it. class SecurityDoor(Door): colour = 'grey' locked = False def open(self): if not self.locked: self.status = 'open' def close_and_lock(self): self.status = 'closed' self.locked = True

Slide 103

Slide 103 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 H om ew ork 2. Modify the SecurityDoor class adding a custom close() method that accepts a locked flag (with default). class SecurityDoor(Door): colour = 'grey' locked = False def open(self): if not self.locked: self.status = 'open' def close(self, locked=False): self.status = 'closed' self.locked = locked

Slide 104

Slide 104 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 H om ew ork 3. Modify the SecurityDoor class adding a custom __init__() method that sets self.locked. class SecurityDoor(Door): colour = 'grey' def __init__(self, number, status, locked=False): self.number = number self.status = status self.locked = locked def open(self): if not self.locked: self.status = 'open'

Slide 105

Slide 105 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 Overriding class SecurityDoor(Door): colour = 'grey' def __init__(self, number, status, locked=True): Door.__init__(self, number, status) self.locked = locked def open(self): if self.locked: return Door.open(self)

Slide 106

Slide 106 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 Overriding class SecurityDoor(Door): colour = 'grey' def __init__(self, number, status, locked=True): Door.__init__(self, number, status) self.locked = locked def open(self): if self.locked: return Door.open(self) >>> sdoor = SecurityDoor(1, 'closed')

Slide 107

Slide 107 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 Overriding class SecurityDoor(Door): colour = 'grey' def __init__(self, number, status, locked=True): Door.__init__(self, number, status) self.locked = locked def open(self): if self.locked: return Door.open(self) >>> sdoor = SecurityDoor(1, 'closed') >>> sdoor.open() >>> sdoor.status 'closed'

Slide 108

Slide 108 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 Overriding class SecurityDoor(Door): colour = 'grey' def __init__(self, number, status, locked=True): Door.__init__(self, number, status) self.locked = locked def open(self): if self.locked: return Door.open(self) >>> sdoor = SecurityDoor(1, 'closed') >>> sdoor.open() >>> sdoor.status 'closed' >>> sdoor.locked = False >>> sdoor.open() >>> sdoor.status 'open'

Slide 109

Slide 109 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 Avoid strong coupling class SecurityDoor(Door): colour = 'grey' def __init__(self, number, status, locked=True): super().__init__(number, status) self.locked = locked def open(self): if self.locked: return super().open()

Slide 110

Slide 110 text

Python 2.x Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 Avoid strong coupling class SecurityDoor(Door): colour = 'grey' def __init__(self, number, status, locked=True): super(SecurityDoor, self).__init__(number, status) self.locked = locked def open(self): if self.locked: return super(SecurityDoor, self).open()

Slide 111

Slide 111 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 class SecurityDoor: colour = 'grey' def __init__(self, number, status, locked=True): self.door = Door(number, status) self.locked = locked def open(self): if self.locked: return self.door.open() def close(self): self.door.close() Composition

Slide 112

Slide 112 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 class SecurityDoor: colour = 'grey' def __init__(self, number, status, locked=True): self.door = Door(number, status) self.locked = locked 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

Slide 113

Slide 113 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 class SecurityDoor: colour = 'grey' def __init__(self, number, status, locked=True): self.door = Door(number, status) self.locked = locked 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 114

Slide 114 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 Python magic to the rescue class SecurityDoor: colour = 'grey' def __init__(self, number, status, locked=True): self.door = Door(number, status) self.locked = locked 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'

Slide 115

Slide 115 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 Python magic to the rescue class SecurityDoor: colour = 'grey' def __init__(self, number, status, locked=True): self.door = Door(number, status) self.locked = locked 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)

Slide 116

Slide 116 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 class ComposedDoor: def __init__(self, number, status): self.door = Door(number, status) def __getattr__(self, attr): return getattr(self.door, attr) Composed inheritance?

Slide 117

Slide 117 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 H om ew ork 1. Modify the SecurityDoor class adding a custom close_and_lock() method. Use super(). Try and implement it with composition. 2. Modify the SecurityDoor class adding a custom close() method that accepts a locked flag (with default). Use super(). Try and implement it with composition.

Slide 118

Slide 118 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 H om ew ork 1. Modify the SecurityDoor class adding a custom close_and_lock() method. Use super(). Try and implement it with composition. class SecurityDoor(Door): colour = 'grey' def __init__(self, number, status, locked=False): super().__init__(number, status) self.locked = locked def open(self): if self.locked: return super().open() def close_and_lock(self): super().close() self.locked = True

Slide 119

Slide 119 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 H om ew ork 1. Modify the SecurityDoor class adding a custom close_and_lock() method. Use super(). Try and implement it with composition. class SecurityDoor: colour = 'grey' def __init__(self, number, status, locked=False): self.door = Door(number, status) self.locked = locked def open(self): if self.locked: return self.door.open() def __getattr__(self, attr): return getattr(self.door, attr) def close_and_lock(self): self.door.close() self.locked = True

Slide 120

Slide 120 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 H om ew ork 2. Modify the SecurityDoor class adding a custom close() method that accepts a locked flag (with default). Use super(). Try and implement it with composition. class SecurityDoor(Door): colour = 'grey' def __init__(self, number, status, locked=False): super().__init__(number, status) self.locked = locked def open(self): if self.locked: return super().open() def close(self, locked=False): super().close() self.locked = locked

Slide 121

Slide 121 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 H om ew ork 2. Modify the SecurityDoor class adding a custom close() method that accepts a locked flag (with default). Use super(). Try and implement it with composition. class SecurityDoor: colour = 'grey' def __init__(self, number, status, locked=False): self.door = Door(number, status) self.locked = locked def open(self): if self.locked: return self.door.open() def __getattr__(self, attr): return getattr(self.door, attr) def close(self, locked=False): self.door.close() self.locked = locked

Slide 122

Slide 122 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 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 123

Slide 123 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 getattr() >>> l = [1,2,3] >>> dir(l) ['__add__', '__class__', '__contains__', '__delattr__', ..., 'append', 'clear', 'copy', ...] >>> l.append

Slide 124

Slide 124 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 getattr() >>> l = [1,2,3] >>> dir(l) ['__add__', '__class__', '__contains__', '__delattr__', ..., 'append', 'clear', 'copy', ...] >>> l.append >>> a = l.append >>> a

Slide 125

Slide 125 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 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 126

Slide 126 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 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 127

Slide 127 text

PART 4 Polymorphism

Slide 128

Slide 128 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 References >>> a = 5 >>> a 5

Slide 129

Slide 129 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 References >>> a = 5 >>> a 5 >>> type(a) >>> hex(id(a)) '0x83fe540'

Slide 130

Slide 130 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 References >>> a = 5 >>> a 5 >>> type(a) >>> hex(id(a)) '0x83fe540' >>> a = 'five' >>> a 'five'

Slide 131

Slide 131 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 References >>> a = 5 >>> a 5 >>> type(a) >>> hex(id(a)) '0x83fe540' >>> a = 'five' >>> a 'five' >>> type(a) >>> hex(id(a)) '0xb70d6560'

Slide 132

Slide 132 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 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 133

Slide 133 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 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 134

Slide 134 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 Every variable is a reference def echo(a): return a

Slide 135

Slide 135 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 Every variable is a reference def echo(a): return a >>> echo(5) 5 >>> echo('five') 'five'

Slide 136

Slide 136 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 >>> 5 + 6 11 What is polymorphism?

Slide 137

Slide 137 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 >>> 5 + 6 11 >>> 5.5 + 6.6 12.1 What is polymorphism?

Slide 138

Slide 138 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 >>> 5 + 6 11 >>> 5.5 + 6.6 12.1 >>> "just a" + " string" 'just a string' What is polymorphism?

Slide 139

Slide 139 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 >>> 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 140

Slide 140 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 >>> 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 141

Slide 141 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 >>> 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 142

Slide 142 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 >>> 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 143

Slide 143 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 >>> s.__len__() 15 >>> l.__len__() 3 >>> d.__len__() 2 What is polymorphism?

Slide 144

Slide 144 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 >>> 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 145

Slide 145 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 >>> [1,2,3].__add__([4,5,6]) [1, 2, 3, 4, 5, 6] Polymorphism is based on delegation

Slide 146

Slide 146 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 >>> [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 147

Slide 147 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 >>> [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 148

Slide 148 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 >>> [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 149

Slide 149 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 def sum(a, b): return a + b Polymorphism is based on delegation

Slide 150

Slide 150 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 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

Slide 151

Slide 151 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 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

Slide 152

Slide 152 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 H om ew ork 1. Create a class that contains an integer as self.value and with a __len__ method that returns the number of digits of the integer. Does len() work for instances of this class? 2. Add a __contains__() method that returns True if self.value contains the given digit. Does 'in' work for this type? 3. Try str() on an instance of your class. What happens? How can you return a better string representation (e.g. to show the actual value)?

Slide 153

Slide 153 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 H om ew ork 1. Create a class that contains an integer as self.value and with a __len__ method that returns the number of digits of the integer. Does len() work for instances of this class? class CustomInteger: def __init__(self, value): self.value = value def __len__(self): return len(str(self.value))

Slide 154

Slide 154 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 H om ew ork 2. Add a __contains__() method that returns True if self.value contains the given digit. Does 'in' work for this type? class CustomInteger: def __init__(self, value): self.value = value def __len__(self): return len(str(self.value)) def __contains__(self, digit): return str(digit) in str(self.value)

Slide 155

Slide 155 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 H om ew ork 3. Try str() on an instance of your class. What happens? How can you return a better string representation (e.g. to show the actual value)? class CustomInteger: def __init__(self, value): self.value = value def __len__(self): return len(str(self.value)) def __contains__(self, digit): return str(digit) in str(self.value) def __str__(self): return super().__str__() + ' [{}]'.format(self.value)

Slide 156

Slide 156 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 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

Slide 157

Slide 157 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 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

Slide 158

Slide 158 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 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

Slide 159

Slide 159 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 >>> door = Door() >>> bool_door = BooleanDoor() Polymorphism in action

Slide 160

Slide 160 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 >>> door = Door() >>> bool_door = BooleanDoor() >>> room = Room(door) >>> bool_room = Room(bool_door) Polymorphism in action

Slide 161

Slide 161 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 >>> 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 162

Slide 162 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 >>> 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 163

Slide 163 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 H om ew ork 1. Modify the Room, the Door and the BooleanDoor classes to add a toggle() method that changes open status to closed and vice versa. 2. Change the Room class such that it accepts a class instead of an instance. How do you manage it into __init__()? Does it still work? 3. Create a PetDoor object that inherits from Door (or BooleanDoor). Add the suitable methods to manage the small pet door. Does the Room work? 4. May you reuse the Door to create the pet door?

Slide 164

Slide 164 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 H om ew ork 1. Modify the Room, the Door and the BooleanDoor classes to add a toggle() method that changes open status to closed and vice versa. 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() def toggle(self): if self.door.is_open(): self.door.close() else: self.door.open()

Slide 165

Slide 165 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 H om ew ork 2. Change the Room class such that it accepts a class instead of an instance. How do you manage it into __init__()? Does it still work? class Room: def __init__(self, door_cls): self.door = door_cls() def open(self): self.door.open() def close(self): self.door.close() def is_open(self): return self.door.is_open() >>> room = Room(Door) >>> bool_room = Room(BooleanDoor)

Slide 166

Slide 166 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 H om ew ork 3. Create a PetDoor object that inherits from Door (or BooleanDoor). Add the suitable methods to manage the small pet door. Does the Room work? class PetDoor(BooleanDoor): def __init__(self): super().__init__() self.pet_door = "open" def open_pet_door(self): self.pet_door = "open" def close_pet_door(self): self.pet_door = "closed"

Slide 167

Slide 167 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 H om ew ork 4. May you reuse the Door to create the pet door? class PetDoor(BooleanDoor): def __init__(self): super().__init__() self.pet_door = BooleanDoor() def open_pet_door(self): self.pet_door.open() def close_pet_door(self): self.pet_door.close()

Slide 168

Slide 168 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 “Ask for permission” style if hasattr(someobj, 'open'): [...] else: [...] It It has has the attribute the attribute

Slide 169

Slide 169 text

Dive into Object-oriented Python – lgiordani.com - CC BY-SA 4.0 “Ask for permission” style try: someobj.open() [...] except AttributeError: [...] It It behaves behaves like it has like it has the attribute the attribute

Slide 170

Slide 170 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 171

Slide 171 text

Dive into Object-oriented Python Leonardo Giordani lgiordani.com DjangoCon Europe 2015 – Cardiff, Wales