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. https://github.com/ lgiordani https://twitter.com/ tw_lgiordani https://plus.google.com/u/ LeonardoGiordani The Digital Cat http://lgiordani.com
you should fit at least one of the following descriptions: * A Python beginner without any knowledge of OOP languages. * A Python beginner with knowledge of other OOP languages such as C++, Java, Ruby, etc. * A Python advanced user who has some knowledge about Python OOP but now wants to know what happens “behind the scenes”. Python experts: you shouldn't be here. You are going to be bored. No, seriously.
of OOP concepts. Covers the following topics * Objects and types * Classes and members * Delegation * Polymorphism * Metaclasses This tutorial covers Python 3. Almost all concepts are valid for Python 2, when relevant differences will be highlighted. Source posts: http://lgiordani.com/blog/categories/python3/
CC BY-SA 4.0 7 163 1 2 3 4 5 6 # This is some data data = (13, 63, 5, 378, 58, 40) # This is a procedure that computes the average def avg(d): return sum(d)/len(d) Plain old procedures >>> avg(data) 92.83333333333333 >>> part1/01.py
CC BY-SA 4.0 8 163 1 2 3 4 5 6 # This is some data data = (13, 63, 5, 378, 58, 40) # This is a procedure that computes the average def avg(d): return sum(d)/len(d) Very simple data: a sequence of numbers Original data enters here This returns new data Plain old procedures part1/01.py
CC BY-SA 4.0 10 163 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 # These are two standard doors, initially closed door1 = [1, 'closed'] door2 = [2, 'closed'] # This is a lockable door, initially closed and unlocked ldoor1 = [1, 'closed', 'unlocked'] # This procedure opens a standard door def open_door(door): door[1] = 'open' # This procedure opens a lockable door def open_ldoor(door): if door[2] == 'unlocked': door[1] = 'open' Things can get complicated >>> open_door(door1) >>> door1 [1, 'open'] >>> open_ldoor(ldoor1) >>> ldoor1 [1, 'open', 'unlocked'] part1/03.py
CC BY-SA 4.0 11 163 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 # These are two standard doors, initially closed door1 = [1, 'closed'] door2 = [2, 'closed'] # This is a lockable door, initially closed and unlocked ldoor1 = [1, 'closed', 'unlocked'] # This procedure opens a standard door def open_door(door): door[1] = 'open' # This procedure opens a lockable door def open_ldoor(door): if door[2] == 'unlocked': door[1] = 'open' Things can get complicated >>> open_door(door1) >>> door1 [1, 'open'] >>> open_ldoor(ldoor1) >>> ldoor1 [1, 'open', 'unlocked'] Same “action” You must use the right function part1/03.py
CC BY-SA 4.0 18 163 Classes >>> a = 6 >>> a 6 >>> type(a) <class 'int'> >>> a.__class__ <class 'int'> >>> What is the type of 'a'? The type of 'a' is the 'int' class It is written INSIDE the variable!
CC BY-SA 4.0 21 163 The first class 1 2 3 4 5 6 7 8 9 10 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 Everything under the 'class' keyword is part of the class part1/04.py
CC BY-SA 4.0 22 163 1 2 3 4 5 6 7 8 9 10 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 first class Functions inside a class are called 'methods', and must accept 'self' as the first parameter part1/04.py
CC BY-SA 4.0 23 163 1 2 3 4 5 6 7 8 9 10 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 first class Attributes Both attributes and methods are 'members' of the class part1/04.py
CC BY-SA 4.0 24 163 1 2 3 4 5 6 7 8 9 10 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 first class The __init__() special method, part of the constructor mechanism part1/04.py
CC BY-SA 4.0 34 163 Where is the class of an object? >>> door1 = Door(1, 'closed') >>> door2 = Door(1, 'closed') >>> hex(id(door1)) '0xb67e148c' >>> hex(id(door2)) '0xb67e144c' >>>
CC BY-SA 4.0 35 163 Where is the class of an object? >>> door1 = Door(1, 'closed') >>> door2 = Door(1, 'closed') >>> hex(id(door1)) '0xb67e148c' >>> hex(id(door2)) '0xb67e144c' >>> Your numbers will be different from these
CC BY-SA 4.0 36 163 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! It is an object in the system.
CC BY-SA 4.0 48 163 Let's dive into attribute resolution >>> door1 = Door(1, 'closed') >>> door1.colour = 'white' >>> 1 2 class Door: colour = 'brown' [...] part2/01.py Remember to execute the class again (we manually changed the class 'colour' attribute)
CC BY-SA 4.0 59 163 Python 2.x Python 2.x >>> Door.open() Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unbound method open() must be called with Door instance as first argument (got nothing instead) >>> From functions to bound methods
CC BY-SA 4.0 75 163 Cat Specialization Cat can provide new features i.e. 'has whiskers' Cat performs some or all the tasks performed by Animal in a different way i.e. 'moves silently' Animal Cat has all the features of Animal i.e. 'moves'
CC BY-SA 4.0 113 163 References >>> a = 5 >>> a 5 >>> type(a) <class 'int'> >>> hex(id(a)) '0x83fe540' >>> a = 'five' >>> a 'five' >>> type(a) <class 'str'> >>> hex(id(a)) '0xb70d6560' >>> A strong type system: every variable has a type
CC BY-SA 4.0 114 163 References >>> a = 5 >>> a 5 >>> type(a) <class 'int'> >>> hex(id(a)) '0x83fe540' >>> a = 'five' >>> a 'five' >>> type(a) <class 'str'> >>> hex(id(a)) '0xb70d6560' >>> A strong type system: every variable has a type A dynamic type system: the type changes with the content
CC BY-SA 4.0 123 163 >>> l = [1, 2, 3] >>> len(l) 3 >>> s = "Just a sentence" >>> len(s) 15 >>> d = {'a': 1, 'b': 2} >>> len(d) 2 >>> i = 5 >>> len(i) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: object of type 'int' has no len() >>> What is polymorphism?
CC BY-SA 4.0 124 163 >>> l = [1, 2, 3] >>> len(l) 3 >>> s = "Just a sentence" >>> len(s) 15 >>> d = {'a': 1, 'b': 2} >>> len(d) 2 >>> i = 5 >>> len(i) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: object of type 'int' has no len() >>> l.__len__() 3 >>> s.__len__() 15 >>> d.__len__() 2 >>> i.__len__() Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'int' object has no attribute '__len__' >>> What is polymorphism?
CC BY-SA 4.0 129 163 Polymorphism is based on delegation 1 2 def sum(a, b): return a + b >>> sum(5,6) 11 >>> sum("Being ", "polymorphic") 'Being polymorphic' >>> sum([1,2,3], [4,5,6]) [1, 2, 3, 4, 5, 6] >>> sum([1,2,3], 8) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 2, in sum TypeError: can only concatenate list (not "int") to list >>> part4/02.py
CC BY-SA 4.0 137 163 “Ask for forgiveness” style 1 2 3 4 if hasattr(someobj, 'open'): [...] else: [...] 1 2 3 4 5 try: someobj.open() [...] except AttributeError: [...] It 'has' the attribute It behaves like it has the attribute
CC BY-SA 4.0 143 163 a int object >>> a = 5 >>> type(a) <class 'int'> >>> a.__class__ <class 'int'> >>> a.__class__.__bases__ (<class 'object'>,) >>> object.__bases__ () >>> Everything is an object (again) 'int' inherits from (its base is) 'object' 'a' is an instance of (its type is) 'int'
CC BY-SA 4.0 147 163 >>> type(a) <class 'int'> >>> type(int) <class 'type'> >>> type(float) <class 'type'> >>> type(dict) <class 'type'> >>> a object Everything is an object (again) 'int' inherits from (its base is) 'object' 'int' is an instance of (its type is) 'type' type int
CC BY-SA 4.0 148 163 >>> type(a) <class 'int'> >>> type(int) <class 'type'> >>> type(float) <class 'type'> >>> type(dict) <class 'type'> >>> a int object Everything is an object (again) 'int' finds here attributes and methods 'int' description as a class is here type
Feel free to contact me. https://github.com/ lgiordani https://twitter.com/ tw_lgiordani https://plus.google.com/u/ LeonardoGiordani The Digital Cat http://lgiordani.com