$30 off During Our Annual Pro Sale. View Details »

Object-Oriented Python From scratch

Leonardo Giordani
April 08, 2015
530

Object-Oriented Python From scratch

Leonardo Giordani

April 08, 2015
Tweet

Transcript

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

    View Slide

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

    View Slide

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

    View Slide

  4. ABOUT THIS TUTORIAL
    This tutorial covers Python 3.
    Almost all concepts are valid for Python 2.
    Relevant differences will be highlighted.
    Objects and types
    Classes and members
    Delegation
    Polymorphism
    Metaclasses
    3

    View Slide

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

    View Slide

  6. PART 1
    Objects and types

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    You already used classes

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  29. Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0
    I-24 27
    door1 = Door(1, 'closed')
    type(door1)

    The first class
    class Door:
    def __init__(self, number, status):
    self.number = number
    self.status = status
    def open(self):
    self.status = 'open'
    def close(self):
    self.status = 'closed'

    View Slide

  30. Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0
    I-25 27
    door1 = Door(1, 'closed')
    type(door1)

    door1.number
    1
    door1.status
    'closed'
    The first class
    class Door:
    def __init__(self, number, status):
    self.number = number
    self.status = status
    def open(self):
    self.status = 'open'
    def close(self):
    self.status = 'closed'

    View Slide

  31. Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0
    I-26 27
    door1 = Door(1, 'closed')
    type(door1)

    door1.number
    1
    door1.status
    'closed'
    door1.open()
    The first class
    class Door:
    def __init__(self, number, status):
    self.number = number
    self.status = status
    def open(self):
    self.status = 'open'
    def close(self):
    self.status = 'closed'

    View Slide

  32. Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0
    I-27 27
    door1 = Door(1, 'closed')
    type(door1)

    door1.number
    1
    door1.status
    'closed'
    door1.open()
    door1.number
    1
    door1.status
    'open'
    The first class
    class Door:
    def __init__(self, number, status):
    self.number = number
    self.status = status
    def open(self):
    self.status = 'open'
    def close(self):
    self.status = 'closed'

    View Slide

  33. PART 2
    Classes and members

    View Slide

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

    View Slide

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

    type(int)

    The type of an object is
    The type of an object is
    an object itself
    an object itself

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    Door.open

    What about methods?

    View Slide

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

    Door.open

    door1.open
    >
    What about methods?

    View Slide

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

    Door.open

    door1.open
    >
    What about methods?

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    From functions to bound methods

    View Slide

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

    dir(door1.__class__.__dict__['open'])
    ['__annotations__', '__call__', '__class__', '__closure__',
    '__code__', '__defaults__', '__delattr__', '__dict__',
    '__dir__', '__doc__', '__eq__', '__format__', '__ge__',
    '__get__', '__getattribute__', '__globals__', '__gt__',
    '__hash__', '__init__', '__kwdefaults__', '__le__', '__lt__',
    '__module__', '__name__', '__ne__', '__new__', '__qualname__',
    '__reduce__', '__reduce_ex__', '__repr__', '__setattr__',
    '__sizeof__', '__str__', '__subclasshook__']
    From functions to bound methods

    View Slide

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

    dir(door1.__class__.__dict__['open'])
    ['__annotations__', '__call__', '__class__', '__closure__',
    ...,'__get__',...]
    door1.__class__.__dict__['open'].__get__

    From functions to bound methods

    View Slide

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

    dir(door1.__class__.__dict__['open'])
    ['__annotations__', '__call__', '__class__', '__closure__',
    ...,'__get__',...]
    door1.__class__.__dict__['open'].__get__

    door1.__class__.__dict__['open'].__get__(door1)
    >
    From functions to bound methods

    View Slide

  67. Python
    2.x
    Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0
    II-35 42
    Door.open()
    Traceback (most recent call last):
    File "", 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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  75. PART 3
    Delegation

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  89. Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0
    III-15 36
    Inheritance
    sdoor.__dict__
    {'number': 1, 'status': 'closed'}
    sdoor.__class__.__dict__
    mappingproxy({'__doc__': None, '__module__': '__main__'})
    Door.__dict__
    mappingproxy({'__dict__': ,
    'colour': 'yellow',
    'open': ,
    '__init__': ,
    '__doc__': None,
    'close': ,
    'knock': ,
    '__weakref__': ,
    '__module__': '__main__',
    'paint': })

    View Slide

  90. Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0
    III-16 36
    Inheritance
    sdoor.__dict__
    {'number': 1, 'status': 'closed'}
    sdoor.__class__.__dict__
    mappingproxy({'__doc__': None, '__module__': '__main__'})
    Door.__dict__
    mappingproxy({'__dict__': ,
    'colour': 'yellow',
    'open': ,
    '__init__': ,
    '__doc__': None,
    'close': ,
    'knock': ,
    '__weakref__': ,
    '__module__': '__main__',
    'paint': })
    SecurityDoor.__bases__
    (,)

    View Slide

  91. Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0
    III-17 36
    Inheritance
    sdoor.__dict__
    {'number': 1, 'status': 'closed'}
    sdoor.__class__.__dict__
    mappingproxy({'__doc__': None, '__module__': '__main__'})
    Door.__dict__
    mappingproxy({'__dict__': ,
    'colour': 'yellow',
    'open': ,
    '__init__': ,
    '__doc__': None,
    'close': ,
    'knock': ,
    '__weakref__': ,
    '__module__': '__main__',
    'paint': })
    SecurityDoor.__bases__
    (,)
    sdoor.knock
    >
    sdoor.__class__.__bases__[0].__dict__['knock'].__get__(sdoor)
    >

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  107. Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0
    III-33 36
    getattr()
    l = [1,2,3]
    dir(l)
    ['__add__', '__class__', '__contains__', '__delattr__',
    ..., 'append', 'clear', 'copy', ...]
    l.append

    View Slide

  108. Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0
    III-34 36
    getattr()
    l = [1,2,3]
    dir(l)
    ['__add__', '__class__', '__contains__', '__delattr__',
    ..., 'append', 'clear', 'copy', ...]
    l.append

    a = l.append
    a

    View Slide

  109. Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0
    III-35 36
    getattr()
    l = [1,2,3]
    dir(l)
    ['__add__', '__class__', '__contains__', '__delattr__',
    ..., 'append', 'clear', 'copy', ...]
    l.append

    a = l.append
    a

    b = getattr(l, 'append')
    b

    View Slide

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

    a = l.append
    a

    b = getattr(l, 'append')
    b

    a == b
    True
    a is b
    False

    View Slide

  111. PART 4
    Polymorphism

    View Slide

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

    View Slide

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

    hex(id(a))
    '0x83fe540'

    View Slide

  114. Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0
    IV-4 34
    References
    a = 5
    a
    5
    type(a)

    hex(id(a))
    '0x83fe540'
    a = 'five'
    a
    'five'

    View Slide

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

    hex(id(a))
    '0x83fe540'
    a = 'five'
    a
    'five'
    type(a)

    hex(id(a))
    '0xb70d6560'

    View Slide

  116. Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0
    IV-6 34
    References
    a = 5
    a
    5
    type(a)

    hex(id(a))
    '0x83fe540'
    a = 'five'
    a
    'five'
    type(a)

    hex(id(a))
    '0xb70d6560'
    Strong
    Strong type system: every
    type system: every
    variable has a type
    variable has a type

    View Slide

  117. Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0
    IV-7 34
    References
    a = 5
    a
    5
    type(a)

    hex(id(a))
    '0x83fe540'
    a = 'five'
    a
    'five'
    type(a)

    hex(id(a))
    '0xb70d6560'
    Dynamic
    Dynamic type system: the type
    type system: the type
    changes with the content
    changes with the content

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  145. PART 5
    Metaclasses

    View Slide

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

    a.__class__

    a.__class__.__bases__
    (,)
    object.__bases__
    ()

    View Slide

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

    a.__class__

    a.__class__.__bases__
    (,)
    object.__bases__
    ()
    'int'
    'int' inherits from
    inherits from
    (its base is) 'object'
    (its base is) 'object'
    'a'
    'a' is an
    is an
    instance of
    instance of
    (its type is) 'int'
    (its type is) 'int'
    object
    int
    a

    View Slide

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

    a.__class__

    a.__class__.__bases__
    (,)
    object.__bases__
    ()
    Inheritance
    Inheritance: 'int' finds
    : 'int' finds
    here attributes and
    here attributes and
    methods
    methods
    Instance
    Instance: 'a'
    : 'a'
    description as a
    description as a
    class is here
    class is here
    object
    int
    a

    View Slide

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

    type(int)

    object
    int
    a

    View Slide

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

    type(int)

    type(float)

    type(dict)

    object
    int
    a

    View Slide

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

    type(int)

    type(float)

    type(dict)

    object
    a
    type
    int int

    View Slide

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

    type(int)

    type(float)

    type(dict)

    object
    a
    type
    int int
    'int'
    'int' inherits
    inherits
    from
    from
    (its base is)
    (its base is)
    'object'
    'object'
    'int'
    'int' is an instance of
    is an instance of
    (its type is) 'type'
    (its type is) 'type'

    View Slide

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

    type(int)

    type(float)

    type(dict)

    object
    a
    type
    int int
    'int' finds here
    'int' finds here
    attributes and
    attributes and
    methods
    methods
    'int' description as a
    'int' description as a
    class is here
    class is here

    View Slide

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

    type.__bases__
    (,)

    View Slide

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

    type.__bases__
    (,)
    object
    type

    View Slide

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

    type.__bases__
    (,)
    type(type)

    object
    type
    Fatality

    View Slide

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

    type.__bases__
    (,)
    type(type)

    object
    type
    Fatality

    View Slide

  158. Object-oriented Python from scratch – lgiordani.com - CC BY-SA 4.0
    V-14 20
    Metaclasses
    class MyType(type):
    pass
    class MySpecialClass(metaclass=MyType):
    pass
    part5/01.py

    View Slide

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

    View Slide

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

    View Slide

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

    type(MySpecialClass)

    MySpecialClass.__bases__
    (,)

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  165. A lot of people
    provided free information and code
    Font aswesome icons
    by Freepik
    Python 3 OOP series
    http://lgiordani.com/blog/categories/python3/
    Some links about Python OOP
    http://goo.gl/UBdJDT
    CAST

    View Slide

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

    View Slide