object-oriented python from scratch

166
OBJECT-ORIENTED PYTHON From scratch Leonardo Giordani lgiordani.com O O P

Upload: giordanileonardo

Post on 17-Jul-2015

352 views

Category:

Technology


15 download

TRANSCRIPT

Page 1: Object-Oriented Python From scratch

OBJECT-ORIENTED PYTHONFrom scratch

Leonardo Giordanilgiordani.comO

OP

Page 2: Object-Oriented Python From scratch

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.comhttps://twitter.com/

tw_lgiordanihttps://github.com/

lgiordanihttps://plus.google.com/u/

LeonardoGiordani

Page 3: Object-Oriented Python From scratch

import usersimport talk

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

about_you.py

Page 4: Object-Oriented Python From scratch

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

Page 5: Object-Oriented Python From scratch

https://github.com/lgiordani/oopy

Code available as IPython Notebooks

Page 6: Object-Oriented Python From scratch

PART 1

Objects and types

Page 7: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0I-2 27

data = (13, 63, 5, 378, 58, 40)

def avg(d): return sum(d)/len(d)

avg(data)92.83333333333333

Plain old procedurespart1/01.py

Page 8: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0I-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 numbersa sequence of numbers

This returns new dataThis returns new data

part1/01.py

Source data enters hereSource data enters here

Plain old procedures

Page 9: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0I-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

Page 10: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0I-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

Page 11: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0I-6 27

Same “action”Same “action”

You must useYou must usethe right functionthe 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

Page 12: Object-Oriented Python From scratch

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

BehavesBehaveslike a ducklike a duck

Behavioural meaning

The meaning of the word 'type'

Page 13: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0I-8 27

DissectionDissectionrevealsreveals

the the truthtruth

Structural meaning

The meaning of the word 'type'

Page 14: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0I-9 27

The behavioural meaning is important

Page 15: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0I-10 27

Duck typing: make it behave like a duck

Page 16: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0I-11 27

Duck typing joke #1

Page 17: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0I-12 27

Duck typing joke #2

Page 18: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0I-13 27

The meaning of the word 'class'

Page 19: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0I-14 27

The meaning of the word 'instance'

Page 20: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0I-15 27

a = 6a6

type(a)<class 'int'>

You already used classes

Page 21: Object-Oriented Python From scratch

Python

2.x

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0I-16 27

You already used classes

a = 6a6

type(a)<type 'int'>

Page 22: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0I-17 27

The first classpart1/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'

Page 23: Object-Oriented Python From scratch

Python

2.x

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

Page 24: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0I-19 27

The first classpart1/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 classThe 'class' keyword defines the class

Page 25: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0I-20 27

The first classpart1/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 classkeyword is part of the class

Page 26: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0I-21 27

The first classpart1/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'

MethodMethod

Page 27: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0I-22 27

The first classpart1/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'

AttributesAttributes

Constructor (part of)Constructor (part of)

Page 28: Object-Oriented Python From scratch

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

Page 29: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0I-24 27

door1 = Door(1, 'closed')type(door1)<class '__main__.Door'>

The first class

class Door: def __init__(self, number, status): self.number = number self.status = status

def open(self): self.status = 'open'

def close(self): self.status = 'closed'

Page 30: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0I-25 27

door1 = Door(1, 'closed')type(door1)<class '__main__.Door'>door1.number1door1.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'

Page 31: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0I-26 27

door1 = Door(1, 'closed')type(door1)<class '__main__.Door'>door1.number1door1.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'

Page 32: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0I-27 27

door1 = Door(1, 'closed')type(door1)<class '__main__.Door'>door1.number1door1.status'closed'door1.open()door1.number1door1.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'

Page 33: Object-Oriented Python From scratch

PART 2

Classes and members

Page 34: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0II-2 42

Everything is an object

a = 1type(a)<class 'int'>

Page 35: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0II-3 42

Everything is an object

a = 1type(a)<class 'int'>type(int)<class 'type'> The type of an object is The type of an object is

an object itselfan object itself

Page 36: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0II-4 42

Where is the class of an object?

door1 = Door(1, 'closed')door2 = Door(1, 'closed')

Page 37: Object-Oriented Python From scratch

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

Page 38: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0II-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.

Page 39: Object-Oriented Python From scratch

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

Class attributespart2/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'

Page 40: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0II-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' hereNo 'self' here

Class attributes

Page 41: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0II-9 42

door1 = Door(1, 'closed')door2 = Door(2, 'closed')

Class attributes

Page 42: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0II-10 42

door1 = Door(1, 'closed')door2 = Door(2, 'closed')Door.colour'brown'door1.colour'brown'door2.colour'brown'

Class attributes

Page 43: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0II-11 42

Door.colour = 'white'

Class attributes

Page 44: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0II-12 42

Door.colour = 'white'Door.colour'white'door1.colour'white'door2.colour'white'

Class attributes

Page 45: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0II-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

Page 46: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0II-14 42

Door.__dict__mappingproxy({'open': <function Door.open at 0xb68604ac>, 'colour': 'white', '__dict__': <attribute '__dict__' of 'Door' objects>, '__weakref__': <attribute '__weakref__' of 'Door' objects>, '__init__': <function Door.__init__ at 0xb7062854>, '__module__': '__main__', '__doc__': None, 'close': <function Door.close at 0xb686041c>})

Class attributes

Page 47: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0II-15 42

Door.__dict__mappingproxy({'open': <function Door.open at 0xb68604ac>, 'colour': 'white', '__dict__': <attribute '__dict__' of 'Door' objects>, '__weakref__': <attribute '__weakref__' of 'Door' objects>, '__init__': <function Door.__init__ at 0xb7062854>, '__module__': '__main__', '__doc__': None, 'close': <function Door.close at 0xb686041c>})door1.__dict__{'number': 1, 'status': 'closed'}

Class attributes

Page 48: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0II-16 42

Door.__dict__mappingproxy({'open': <function Door.open at 0xb68604ac>, 'colour': 'white', '__dict__': <attribute '__dict__' of 'Door' objects>, '__weakref__': <attribute '__weakref__' of 'Door' objects>, '__init__': <function Door.__init__ at 0xb7062854>, '__module__': '__main__', '__doc__': None, 'close': <function Door.close at 0xb686041c>})door1.__dict__{'number': 1, 'status': 'closed'}door1.__dict__['colour']Traceback (most recent call last): File "<stdin>", line 1, in <module>KeyError: 'colour'

Class attributes

Page 49: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0II-17 42

Door.__dict__mappingproxy({'open': <function Door.open at 0xb68604ac>, 'colour': 'white', '__dict__': <attribute '__dict__' of 'Door' objects>, '__weakref__': <attribute '__weakref__' of 'Door' objects>, '__init__': <function Door.__init__ at 0xb7062854>, '__module__': '__main__', '__doc__': None, 'close': <function Door.close at 0xb686041c>})door1.__dict__{'number': 1, 'status': 'closed'}door1.__dict__['colour']Traceback (most recent call last): File "<stdin>", line 1, in <module>KeyError: 'colour'door1.__class__.__dict__['colour']'white'door1.colour is Door.colourTrue

Class attributes

Page 50: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0II-18 42

Door

door1 door2

__getattribute__()__getattribute__()

Let's dive into attribute resolution

door1.colour

Door.colour

Page 51: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0II-19 42

Let's dive into attribute resolution

door1 = Door(1, 'closed')door1.colour = 'white'door1.__dict__['colour']'white'door1.__class__.__dict__['colour']'brown'

Page 52: Object-Oriented Python From scratch

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

Page 53: Object-Oriented Python From scratch

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

Page 54: Object-Oriented Python From scratch

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

Page 55: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0II-23 42

Door.__dict__mappingproxy({'open': <function Door.open at 0xb68604ac>, 'colour': 'white', '__dict__': <attribute '__dict__' of 'Door' objects>, '__weakref__': <attribute '__weakref__' of 'Door' objects>, '__init__': <function Door.__init__ at 0xb7062854>, '__module__': '__main__', '__doc__': None, 'close': <function Door.close at 0xb686041c>})door1.__dict__{'number': 1, 'status': 'closed'}door1.colour is Door.colourTrue

What about methods?

Page 56: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0II-24 42

Door.__dict__mappingproxy({'open': <function Door.open at 0xb68604ac>, 'colour': 'white', '__dict__': <attribute '__dict__' of 'Door' objects>, '__weakref__': <attribute '__weakref__' of 'Door' objects>, '__init__': <function Door.__init__ at 0xb7062854>, '__module__': '__main__', '__doc__': None, 'close': <function Door.close at 0xb686041c>})door1.__dict__{'number': 1, 'status': 'closed'}door1.colour is Door.colourTruedoor1.open is Door.openFalse

What about methods?

Page 57: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0II-25 42

Door.__dict__mappingproxy({'open': <function Door.open at 0xb68604ac>, 'colour': 'white', '__dict__': <attribute '__dict__' of 'Door' objects>, '__weakref__': <attribute '__weakref__' of 'Door' objects>, '__init__': <function Door.__init__ at 0xb7062854>, '__module__': '__main__', '__doc__': None, 'close': <function Door.close at 0xb686041c>})door1.__dict__{'number': 1, 'status': 'closed'}door1.colour is Door.colourTruedoor1.open is Door.openFalseDoor.__dict__['open']<function Door.open at 0xb68604ac>Door.open<function Door.open at 0xb68604ac>

What about methods?

Page 58: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0II-26 42

Door.__dict__mappingproxy({'open': <function Door.open at 0xb68604ac>, 'colour': 'white', '__dict__': <attribute '__dict__' of 'Door' objects>, '__weakref__': <attribute '__weakref__' of 'Door' objects>, '__init__': <function Door.__init__ at 0xb7062854>, '__module__': '__main__', '__doc__': None, 'close': <function Door.close at 0xb686041c>})door1.__dict__{'number': 1, 'status': 'closed'}door1.colour is Door.colourTruedoor1.open is Door.openFalseDoor.__dict__['open']<function Door.open at 0xb68604ac>Door.open<function Door.open at 0xb68604ac>door1.open<bound method Door.open of <__main__.Door object at 0xb67e162c>>

What about methods?

Page 59: Object-Oriented Python From scratch

Python

2.x

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0II-27 42

Door.__dict__mappingproxy({'open': <function Door.open at 0xb68604ac>, 'colour': 'white', '__dict__': <attribute '__dict__' of 'Door' objects>, '__weakref__': <attribute '__weakref__' of 'Door' objects>, '__init__': <function Door.__init__ at 0xb7062854>, '__module__': '__main__', '__doc__': None, 'close': <function Door.close at 0xb686041c>})door1.__dict__{'number': 1, 'status': 'closed'}door1.colour is Door.colourTruedoor1.open is Door.openFalseDoor.__dict__['open']<function Door.open at 0xb68604ac>Door.open<unbound method Door.open>door1.open<bound method Door.open of <__main__.Door object at 0xb67e162c>>

What about methods?

Page 60: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0II-28 42

Door.open()Traceback (most recent call last): File "<stdin>", line 1, in <module>TypeError: open() missing 1 required positional argument: 'self'

From functions to bound methods

Page 61: Object-Oriented Python From scratch

Python

2.x

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0II-29 42

Door.open()Traceback (most recent call last): File "<stdin>", line 1, in <module>TypeError: unbound method open() must be called with Door instanceas first argument (got nothing instead)

From functions to bound methods

Page 62: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0II-30 42

Door.open()Traceback (most recent call last): File "<stdin>", line 1, in <module>TypeError: open() missing 1 required positional argument: 'self'Door.open(door1)door1.status'open'

From functions to bound methods

Page 63: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0II-31 42

Door.open()Traceback (most recent call last): File "<stdin>", line 1, in <module>TypeError: open() missing 1 required positional argument: 'self'Door.open(door1)door1.status'open'door1.__class__.__dict__['open']<function Door.open at 0xb68604ac>

From functions to bound methods

Page 64: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0II-32 42

Door.open()Traceback (most recent call last): File "<stdin>", line 1, in <module>TypeError: open() missing 1 required positional argument: 'self'Door.open(door1)door1.status'open'door1.__class__.__dict__['open']<function Door.open at 0xb68604ac>dir(door1.__class__.__dict__['open'])['__annotations__', '__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__get__', '__getattribute__', '__globals__', '__gt__', '__hash__', '__init__', '__kwdefaults__', '__le__', '__lt__', '__module__', '__name__', '__ne__', '__new__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']

From functions to bound methods

Page 65: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0II-33 42

Door.open()Traceback (most recent call last): File "<stdin>", line 1, in <module>TypeError: open() missing 1 required positional argument: 'self'Door.open(door1)door1.status'open'door1.__class__.__dict__['open']<function Door.open at 0xb68604ac>dir(door1.__class__.__dict__['open'])['__annotations__', '__call__', '__class__', '__closure__', ...,'__get__',...]door1.__class__.__dict__['open'].__get__<method-wrapper '__get__' of function object at 0xb68604ac>

From functions to bound methods

Page 66: Object-Oriented Python From scratch

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

Door.open()Traceback (most recent call last): File "<stdin>", line 1, in <module>TypeError: open() missing 1 required positional argument: 'self'Door.open(door1)door1.status'open'door1.__class__.__dict__['open']<function Door.open at 0xb68604ac>dir(door1.__class__.__dict__['open'])['__annotations__', '__call__', '__class__', '__closure__', ...,'__get__',...]door1.__class__.__dict__['open'].__get__<method-wrapper '__get__' of function object at 0xb68604ac>door1.__class__.__dict__['open'].__get__(door1)<bound method Door.open of <__main__.Door object at 0xb67e162c>>

From functions to bound methods

Page 67: Object-Oriented Python From scratch

Python

2.x

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0II-35 42

Door.open()Traceback (most recent call last): File "<stdin>", line 1, in <module>TypeError: open() missing 1 required positional argument: 'self'Door.open(door1)door1.status'open'door1.__class__.__dict__['open']<function Door.open at 0xb68604ac>dir(door1.__class__.__dict__['open'])['__annotations__', '__call__', '__class__', '__closure__', ...,'__get__',...]door1.__class__.__dict__['open'].__get__<method-wrapper '__get__' of function object at 0xb68604ac>door1.__class__.__dict__['open'].__get__(door1)<bound method ?.open of <__main__.Door instance at 0xb6977aac>>door1.__class__.__dict__['open'].__get__(door1, Door)<bound method Door.open of <__main__.Door object at 0xb73f956c>>

From functions to bound methods

Page 68: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0II-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

Page 69: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0II-37 42

door1 = Door(1, 'closed')door1.knock()Knock!Door.knock()Knock!

From functions to bound methods

Page 70: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0II-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

Page 71: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0II-39 42

door1 = Door(1, 'closed')door2 = Door(2, 'closed')

Class methods

Page 72: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0II-40 42

door1 = Door(1, 'closed')door2 = Door(2, 'closed')Door.colour'brown'door1.colour'brown'door2.colour'brown'

Class methods

Page 73: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0II-41 42

Door.paint('white')Door.colour'white'door1.colour'white'door2.colour'white'

Class methods

Page 74: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0II-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

Page 75: Object-Oriented Python From scratch

PART 3

Delegation

Page 76: Object-Oriented Python From scratch

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

Specialization

CatAnimal

Page 77: Object-Oriented Python From scratch

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

Cat has all the features of Cat has all the features of Animal, i.e. 'moves'Animal, i.e. 'moves'

Specialization

CatAnimal

Page 78: Object-Oriented Python From scratch

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

Cat can provide new features, i.e. Cat can provide new features, i.e. 'has whiskers''has whiskers'

Specialization

CatAnimal

Page 79: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0III-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

CatAnimal

Page 80: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0III-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 Animalfeatures to Animal

Delegation

CatAnimal

Page 81: Object-Oriented Python From scratch

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

Composition: 'has'

Car

Engine turn_on()

Wheels steer()

get_color()

Page 82: Object-Oriented Python From scratch

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

Inheritance: 'is'

look()look()

Cat

Animal

look()

mew()

Page 83: Object-Oriented Python From scratch

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

Page 84: Object-Oriented Python From scratch

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

Inheritancepart3/01.py

class SecurityDoor(Door): pass

Page 85: Object-Oriented Python From scratch

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

Inheritance

class SecurityDoor(Door): pass

sdoor = SecurityDoor(1, 'closed')

Page 86: Object-Oriented Python From scratch

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

Inheritance

class SecurityDoor(Door): pass

sdoor = SecurityDoor(1, 'closed')SecurityDoor.colour is Door.colourTruesdoor.colour is Door.colourTrue

Page 87: Object-Oriented Python From scratch

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

Inheritance

class SecurityDoor(Door): pass

sdoor = SecurityDoor(1, 'closed')SecurityDoor.colour is Door.colourTruesdoor.colour is Door.colourTrue

sdoor.coloursdoor.colour

SecurityDoor.colourSecurityDoor.colour

Door.colourDoor.colour

Page 88: Object-Oriented Python From scratch

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

Inheritancesdoor.__dict__{'number': 1, 'status': 'closed'}

Page 89: Object-Oriented Python From scratch

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

Inheritancesdoor.__dict__{'number': 1, 'status': 'closed'}sdoor.__class__.__dict__mappingproxy({'__doc__': None, '__module__': '__main__'})Door.__dict__mappingproxy({'__dict__': <attribute '__dict__' of 'Door' objects>, 'colour': 'yellow', 'open': <function Door.open at 0xb687e224>, '__init__': <function Door.__init__ at 0xb687e14c>, '__doc__': None, 'close': <function Door.close at 0xb687e1dc>, 'knock': <classmethod object at 0xb67ff6ac>, '__weakref__': <attribute '__weakref__' of 'Door' objects>, '__module__': '__main__', 'paint': <classmethod object at 0xb67ff6ec>})

Page 90: Object-Oriented Python From scratch

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

Inheritancesdoor.__dict__{'number': 1, 'status': 'closed'}sdoor.__class__.__dict__mappingproxy({'__doc__': None, '__module__': '__main__'})Door.__dict__mappingproxy({'__dict__': <attribute '__dict__' of 'Door' objects>, 'colour': 'yellow', 'open': <function Door.open at 0xb687e224>, '__init__': <function Door.__init__ at 0xb687e14c>, '__doc__': None, 'close': <function Door.close at 0xb687e1dc>, 'knock': <classmethod object at 0xb67ff6ac>, '__weakref__': <attribute '__weakref__' of 'Door' objects>, '__module__': '__main__', 'paint': <classmethod object at 0xb67ff6ec>})SecurityDoor.__bases__(<class '__main__.Door'>,)

Page 91: Object-Oriented Python From scratch

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

Inheritancesdoor.__dict__{'number': 1, 'status': 'closed'}sdoor.__class__.__dict__mappingproxy({'__doc__': None, '__module__': '__main__'})Door.__dict__mappingproxy({'__dict__': <attribute '__dict__' of 'Door' objects>, 'colour': 'yellow', 'open': <function Door.open at 0xb687e224>, '__init__': <function Door.__init__ at 0xb687e14c>, '__doc__': None, 'close': <function Door.close at 0xb687e1dc>, 'knock': <classmethod object at 0xb67ff6ac>, '__weakref__': <attribute '__weakref__' of 'Door' objects>, '__module__': '__main__', 'paint': <classmethod object at 0xb67ff6ec>})SecurityDoor.__bases__(<class '__main__.Door'>,)sdoor.knock<bound method type.knock of <class '__main__.SecurityDoor'>>sdoor.__class__.__bases__[0].__dict__['knock'].__get__(sdoor)<bound method type.knock of <class '__main__.SecurityDoor'>>

Page 92: Object-Oriented Python From scratch

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

Overridingpart3/02.py

class SecurityDoor(Door): colour = 'grey' locked = True

def open(self): if not self.locked: self.status = 'open'

Page 93: Object-Oriented Python From scratch

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

Overridingpart3/02.py

Overriding blocks implicit Overriding blocks implicit delegationdelegation

class SecurityDoor(Door): colour = 'grey' locked = True

def open(self): if not self.locked: self.status = 'open'

SecurityDoor.__dict__mappingproxy({'__doc__': None, '__module__': '__main__', 'open': <function SecurityDoor.open at 0xb6fcf89c>, 'colour': 'grey', 'locked': True})

Page 94: Object-Oriented Python From scratch

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

Overridingpart3/03.py

class SecurityDoor(Door): colour = 'grey' locked = True

def open(self): if self.locked: return Door.open(self)

Page 95: Object-Oriented Python From scratch

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

Overridingpart3/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'

Page 96: Object-Oriented Python From scratch

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

Overridingpart3/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'

Page 97: Object-Oriented Python From scratch

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

Overridingpart3/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 = Falsesdoor.open()sdoor.status'open'

Page 98: Object-Oriented Python From scratch

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

Avoid strong couplingpart3/04.py

class SecurityDoor(Door): colour = 'grey' locked = True

def open(self): if self.locked: return super().open()

Page 99: Object-Oriented Python From scratch

Python

2.x

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

class SecurityDoor(Door): colour = 'grey' locked = True

def open(self): if self.locked: return super(SecurityDoor, self).open(self)

Avoid strong coupling

Page 100: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0III-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()

Compositionpart3/05.py

Page 101: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0III-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.statusTraceback (most recent call last): File "<stdin>", line 1, in <module>AttributeError: 'SecurityDorr' object has no attribute 'status'

Compositionpart3/05.py

Page 102: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0III-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

Page 103: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0III-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

Page 104: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0III-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

Page 105: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0III-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

Page 106: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0III-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']

Page 107: Object-Oriented Python From scratch

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

getattr()

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

Page 108: Object-Oriented Python From scratch

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

getattr()

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

Page 109: Object-Oriented Python From scratch

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

getattr()

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

Page 110: Object-Oriented Python From scratch

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

getattr()

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

Page 111: Object-Oriented Python From scratch

PART 4

Polymorphism

Page 112: Object-Oriented Python From scratch

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

References

a = 5a5

Page 113: Object-Oriented Python From scratch

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

References

a = 5a5type(a)<class 'int'>hex(id(a))'0x83fe540'

Page 114: Object-Oriented Python From scratch

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

References

a = 5a5type(a)<class 'int'>hex(id(a))'0x83fe540'a = 'five'a'five'

Page 115: Object-Oriented Python From scratch

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

References

a = 5a5type(a)<class 'int'>hex(id(a))'0x83fe540'a = 'five'a'five'type(a)<class 'str'>hex(id(a))'0xb70d6560'

Page 116: Object-Oriented Python From scratch

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

References

a = 5a5type(a)<class 'int'>hex(id(a))'0x83fe540'a = 'five'a'five'type(a)<class 'str'>hex(id(a))'0xb70d6560'

StrongStrong type system: every type system: every variable has a typevariable has a type

Page 117: Object-Oriented Python From scratch

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

References

a = 5a5type(a)<class 'int'>hex(id(a))'0x83fe540'a = 'five'a'five'type(a)<class 'str'>hex(id(a))'0xb70d6560'

DynamicDynamic type system: the type type system: the type changes with the contentchanges with the content

Page 118: Object-Oriented Python From scratch

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

Every variable is a reference

def echo(a): return a

part4/01.py

Page 119: Object-Oriented Python From scratch

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

Every variable is a reference

def echo(a): return a

echo(5)5echo('five')'five'

part4/01.py

Page 120: Object-Oriented Python From scratch

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

5 + 611

What is polymorphism?

Page 121: Object-Oriented Python From scratch

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

5 + 6115.5 + 6.612.1

What is polymorphism?

Page 122: Object-Oriented Python From scratch

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

5 + 6115.5 + 6.612.1"just a" + " string"'just a string'

What is polymorphism?

Page 123: Object-Oriented Python From scratch

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

5 + 6115.5 + 6.612.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?

Page 124: Object-Oriented Python From scratch

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

5 + 6115.5 + 6.612.1"just a" + " string"'just a string'[1,2,3] + [4,5,6][1, 2, 3, 4, 5, 6](1,2,3) + (4,5,6)(1, 2, 3, 4, 5, 6){'a':4, 'b':5} + {'c':7}Traceback (most recent call last): File "<stdin>", line 1, in <module>TypeError: unsupported operand type(s) for +: 'dict' and 'dict'

What is polymorphism?

Page 125: Object-Oriented Python From scratch

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

s = "Just a sentence"len(s)15l = [1, 2, 3]len(l)3d = {'a': 1, 'b': 2}len(d)2

What is polymorphism?

Page 126: Object-Oriented Python From scratch

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

s = "Just a sentence"len(s)15l = [1, 2, 3]len(l)3d = {'a': 1, 'b': 2}len(d)2i = 5len(i)Traceback (most recent call last): File "<stdin>", line 1, in <module>TypeError: object of type 'int' has no len()

What is polymorphism?

Page 127: Object-Oriented Python From scratch

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

s.__len__()15l.__len__()3d.__len__()2

What is polymorphism?

Page 128: Object-Oriented Python From scratch

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

s.__len__()15l.__len__()3d.__len__()2i.__len__()Traceback (most recent call last): File "<stdin>", line 1, in <module>AttributeError: 'int' objecthas no attribute '__len__'

What is polymorphism?

Page 129: Object-Oriented Python From scratch

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

[1,2,3].__add__([4,5,6])[1, 2, 3, 4, 5, 6]

Polymorphism is based on delegation

Page 130: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0IV-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

Page 131: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0IV-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

Page 132: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0IV-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)True6 in [1,2,3]False[1,2,3].__contains__(6)False

Polymorphism is based on delegation

Page 133: Object-Oriented Python From scratch

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

def sum(a, b): return a + b

Polymorphism is based on delegationpart4/02.py

Page 134: Object-Oriented Python From scratch

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

def sum(a, b): return a + b

sum(5,6)11sum("Being ", "polymorphic")'Being polymorphic'sum([1,2,3], [4,5,6])[1, 2, 3, 4, 5, 6]

Polymorphism is based on delegationpart4/02.py

Page 135: Object-Oriented Python From scratch

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

def sum(a, b): return a + b

sum(5,6)11sum("Being ", "polymorphic")'Being polymorphic'sum([1,2,3], [4,5,6])[1, 2, 3, 4, 5, 6]sum([1,2,3], 8)Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 2, in sumTypeError: can only concatenate list (not "int") to list

Polymorphism is based on delegationpart4/02.py

Page 136: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0IV-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 actionpart4/03.py

Page 137: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0IV-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 actionpart4/03.py

Page 138: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0IV-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 actionpart4/03.py

Page 139: Object-Oriented Python From scratch

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

door = Door()bool_door = BooleanDoor()

Polymorphism in action

Page 140: Object-Oriented Python From scratch

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

door = Door()bool_door = BooleanDoor()room = Room(door)bool_room = Room(bool_door)

Polymorphism in action

Page 141: Object-Oriented Python From scratch

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

door = Door()bool_door = BooleanDoor()room = Room(door)bool_room = Room(bool_door)room.open()room.is_open()Trueroom.close()room.is_open()False

Polymorphism in action

Page 142: Object-Oriented Python From scratch

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

door = Door()bool_door = BooleanDoor()room = Room(door)bool_room = Room(bool_door)room.open()room.is_open()Trueroom.close()room.is_open()Falsebool_room.open()bool_room.is_open()Truebool_room.close()bool_room.is_open()False

Polymorphism in action

Page 143: Object-Oriented Python From scratch

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

“Ask for permission” style

if hasattr(someobj, 'open'): [...]else: [...]

It It hashas the attribute the attribute

Page 144: Object-Oriented Python From scratch

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

“Ask for permission” style

try: someobj.open() [...]except AttributeError: [...]

It It behavesbehaves like it has like it has the attributethe attribute

Page 145: Object-Oriented Python From scratch

PART 5

Metaclasses

Page 146: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0V-2 20

Everything is an object (again)

a = 5type(a)<class 'int'>a.__class__<class 'int'>a.__class__.__bases__(<class 'object'>,)object.__bases__()

Page 147: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0V-3 20

Everything is an object (again)

a = 5type(a)<class 'int'>a.__class__<class 'int'>a.__class__.__bases__(<class 'object'>,)object.__bases__()

'int' 'int' inherits frominherits from(its base is) 'object'(its base is) 'object'

'a' 'a' is an is an instance ofinstance of

(its type is) 'int' (its type is) 'int'

object

int

a

Page 148: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0V-4 20

Everything is an object (again)

a = 5type(a)<class 'int'>a.__class__<class 'int'>a.__class__.__bases__(<class 'object'>,)object.__bases__()

InheritanceInheritance: 'int' finds : 'int' finds here attributes and here attributes and

methodsmethods

InstanceInstance: 'a' : 'a' description as a description as a class is hereclass is here

object

int

a

Page 149: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0V-5 20

Everything is an object (again)

type(a)<class 'int'>type(int)<class 'type'>

object

int

a

Page 150: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0V-6 20

Everything is an object (again)

type(a)<class 'int'>type(int)<class 'type'>type(float)<class 'type'>type(dict)<class 'type'>

object

int

a

Page 151: Object-Oriented Python From scratch

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

Everything is an object (again)

type(a)<class 'int'>type(int)<class 'type'>type(float)<class 'type'>type(dict)<class 'type'>

object

a

type

int int

Page 152: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0V-8 20

Everything is an object (again)

type(a)<class 'int'>type(int)<class 'type'>type(float)<class 'type'>type(dict)<class 'type'>

object

a

type

int int'int' 'int' inherits inherits

fromfrom(its base is) (its base is)

'object''object'

'int' 'int' is an instance ofis an instance of(its type is) 'type' (its type is) 'type'

Page 153: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0V-9 20

Everything is an object (again)

type(a)<class 'int'>type(int)<class 'type'>type(float)<class 'type'>type(dict)<class 'type'>

object

a

type

int int

'int' finds here 'int' finds here attributes and attributes and

methodsmethods

'int' description as a 'int' description as a class is hereclass is here

Page 154: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0V-10 20

Food for thought

type(object)<class 'type'>type.__bases__(<class 'object'>,)

Page 155: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0V-11 20

Food for thought

type(object)<class 'type'>type.__bases__(<class 'object'>,)

object

type

Page 156: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0V-12 20

type(object)<class 'type'>type.__bases__(<class 'object'>,)type(type)<class 'type'>

object

type

Fatality

Page 157: Object-Oriented Python From scratch

Python

2.x

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0V-13 20

type(object)<class 'type'>type.__bases__(<class 'object'>,)type(type)<type 'type'>

object

type

Fatality

Page 158: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0V-14 20

Metaclasses

class MyType(type): pass

class MySpecialClass(metaclass=MyType): pass

part5/01.py

Page 159: Object-Oriented Python From scratch

Python

2.x

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0V-15 20

Metaclasses

class MyType(type): pass

class MySpecialClass(object):__metaclass__ = MyType

Page 160: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0V-16 20

Metaclasses

class MyType(type): pass

class MySpecialClass(metaclass=MyType): pass

msp = MySpecialClass()type(msp)<class '__main__.MySpecialClass'>

Page 161: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0V-17 20

Metaclasses

class MyType(type): pass

class MySpecialClass(metaclass=MyType): pass

msp = MySpecialClass()type(msp)<class '__main__.MySpecialClass'>type(MySpecialClass)<class '__main__.MyType'>MySpecialClass.__bases__(<class 'object'>,)

Page 162: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0V-18 20

Metaclasses in action: singletonpart5/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

Page 163: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0V-19 20

Metaclasses in action: singletonpart5/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()

Page 164: Object-Oriented Python From scratch

Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0V-20 20

Metaclasses in action: singletonpart5/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 bTruehex(id(a))'0xb68030ec'hex(id(b))'0xb68030ec'

Page 165: Object-Oriented Python From scratch

A lot of peopleprovided free information and code

Font aswesome iconsby Freepik

Python 3 OOP serieshttp://lgiordani.com/blog/categories/python3/

Some links about Python OOPhttp://goo.gl/UBdJDT

CAST

Page 166: Object-Oriented Python From scratch

OBJECT-ORIENTED PYTHONFrom scratch

Leonardo Giordanilgiordani.comO

OP