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
H om ew ork 1. Find some types that Python provides out of the box. 2. Can you create a float variable without using the '.' character? 3. What is the difference between {1,2,3} and {'a':1, 'b':2}?
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'
BY-SA 4.0 The first class class Door(object): def __init__(self, number, status): self.number = number self.status = status def open(self): self.status = 'open' def close(self): self.status = 'closed'
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'
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'
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'
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'
>>> 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'
H om ew ork 1. Create a ColouredDoor class that has the 'colour' attribute. 2. Create a ClosedDoor class that has a default status of 'closed'. 3. Create a ToggleDoor class that has a method toggle() that toggles the status of the door.
H om ew ork 1. Create a ColouredDoor class that has the 'colour' attribute. class ColouredDoor: def __init__(self, number, status, colour): self.number = number self.status = status self.colour = colour def open(self): self.status = 'open' def close(self): self.status = 'closed'
H om ew ork 2. Create a ClosedDoor class that has a default status of 'closed'. class ClosedDoor: def __init__(self, number, status='closed'): self.number = number self.status = status def open(self): self.status = 'open' def close(self): self.status = 'closed'
H om ew ork 3. Create a ToggleDoor class that has a method toggle() that toggles the status of the door. class ToggleDoor: def __init__(self, number, status): self.number = number self.status = status def open(self): self.status = 'open' def close(self): self.status = 'closed' def toggle(self): d = {'open': 'closed', 'closed': 'open'} self.status = d[self.status]
Where is the class of an object? >>> door1 = Door(1, 'closed') >>> door2 = Door(1, 'closed') >>> hex(id(door1)) '0xb67e148c' >>> hex(id(door2)) '0xb67e144c'
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'
H om ew ork 1. Modify the Door class adding a class attribute 'status' with value 'undefined'. Does it work? What happens to instances? 2. Modify the Door class adding a class attribute 'status' with value 'closed' and remove status from __init__(). Does it work? 3. Add a toggle() method to the previous class. What happens if you call toggle() on a fresh instance? Why?
H om ew ork 1. Modify the Door class adding a class attribute 'status' with value 'undefined'. Does it work? What happens to instances? class Door: colour = 'brown' status = 'undefined' def __init__(self, number, status): self.number = number self.status = status def open(self): self.status = 'open' def close(self): self.status = 'closed'
H om ew ork 2. Modify the Door class adding a class attribute 'status' with value 'closed' and remove status from __init__(). Does it work? class Door: colour = 'brown' status = 'closed' def __init__(self, number): self.number = number def open(self): self.status = 'open' def close(self): self.status = 'closed'
H om ew ork 3. Add a toggle() method to the previous class. What happens if you call toggle() on a fresh instance? Why? class Door: colour = 'brown' status = 'closed' def __init__(self, number): self.number = number def toggle(self): d = {'open': 'closed', 'closed': 'open'} self.status = d[self.status]
BY-SA 4.0 >>> 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
H om ew ork 1. Modify the Door class adding a class method 'paint' that accepts a 'colour' argument and changes the class attribute 'colour'. 2. Modify the Door class adding both a class method 'paint' and a standard method 'paint'. What happens?
H om ew ork 1. Modify the Door class adding a class method 'paint' that accepts a 'colour' argument and changes the class attribute 'colour'. class Door: colour = 'brown' def __init__(self, number, status): self.number = number self.status = status @classmethod def paint(cls, colour): cls.colour = colour def open(self): self.status = 'open' def close(self): self.status = 'closed'
H om ew ork 2. Modify the Door class adding both a class method 'paint' and a standard method 'paint'. What happens? class Door: colour = 'brown' def __init__(self, number, status): self.number = number self.status = status @classmethod def paint(cls, colour): cls.colour = colour def paint(self, colour): self.colour = colour [...]
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
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
H om ew ork 1. Modify the SecurityDoor class adding a custom close_and_lock() method that changes status to 'closed' and locked to True. Test it. 2. Modify the SecurityDoor class adding a custom close() method that accepts a locked flag (with default). 3. Modify the SecurityDoor class adding a custom __init__() method that sets self.locked.
H om ew ork 1. Modify the SecurityDoor class adding a custom close_and_lock() method that changes status to 'closed' and locked to True. Test it. class SecurityDoor(Door): colour = 'grey' locked = False def open(self): if not self.locked: self.status = 'open' def close_and_lock(self): self.status = 'closed' self.locked = True
H om ew ork 2. Modify the SecurityDoor class adding a custom close() method that accepts a locked flag (with default). class SecurityDoor(Door): colour = 'grey' locked = False def open(self): if not self.locked: self.status = 'open' def close(self, locked=False): self.status = 'closed' self.locked = locked
H om ew ork 3. Modify the SecurityDoor class adding a custom __init__() method that sets self.locked. class SecurityDoor(Door): colour = 'grey' def __init__(self, number, status, locked=False): self.number = number self.status = status self.locked = locked def open(self): if not self.locked: self.status = 'open'
H om ew ork 1. Modify the SecurityDoor class adding a custom close_and_lock() method. Use super(). Try and implement it with composition. 2. Modify the SecurityDoor class adding a custom close() method that accepts a locked flag (with default). Use super(). Try and implement it with composition.
H om ew ork 1. Modify the SecurityDoor class adding a custom close_and_lock() method. Use super(). Try and implement it with composition. class SecurityDoor(Door): colour = 'grey' def __init__(self, number, status, locked=False): super().__init__(number, status) self.locked = locked def open(self): if self.locked: return super().open() def close_and_lock(self): super().close() self.locked = True
H om ew ork 1. Modify the SecurityDoor class adding a custom close_and_lock() method. Use super(). Try and implement it with composition. class SecurityDoor: colour = 'grey' def __init__(self, number, status, locked=False): self.door = Door(number, status) self.locked = locked def open(self): if self.locked: return self.door.open() def __getattr__(self, attr): return getattr(self.door, attr) def close_and_lock(self): self.door.close() self.locked = True
H om ew ork 2. Modify the SecurityDoor class adding a custom close() method that accepts a locked flag (with default). Use super(). Try and implement it with composition. class SecurityDoor(Door): colour = 'grey' def __init__(self, number, status, locked=False): super().__init__(number, status) self.locked = locked def open(self): if self.locked: return super().open() def close(self, locked=False): super().close() self.locked = locked
H om ew ork 2. Modify the SecurityDoor class adding a custom close() method that accepts a locked flag (with default). Use super(). Try and implement it with composition. class SecurityDoor: colour = 'grey' def __init__(self, number, status, locked=False): self.door = Door(number, status) self.locked = locked def open(self): if self.locked: return self.door.open() def __getattr__(self, attr): return getattr(self.door, attr) def close(self, locked=False): self.door.close() self.locked = locked
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.append >>> a <built-in method append of list object at 0xb70a2c2c>
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.append >>> a <built-in method append of list object at 0xb70a2c2c> >>> b = getattr(l, 'append') >>> b <built-in method append of list object at 0xb70a2c2c>
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.append >>> a <built-in method append of list object at 0xb70a2c2c> >>> b = getattr(l, 'append') >>> b <built-in method append of list object at 0xb70a2c2c> >>> a == b True >>> a is b False
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' Strong Strong type system: every type system: every variable has a type variable has a type
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' Dynamic Dynamic type system: the type type system: the type changes with the content changes with the content
>>> 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 "<stdin>", line 1, in <module> TypeError: object of type 'int' has no len() What is polymorphism?
>>> s.__len__() 15 >>> l.__len__() 3 >>> 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?
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 Polymorphism is based on delegation
H om ew ork 1. Create a class that contains an integer as self.value and with a __len__ method that returns the number of digits of the integer. Does len() work for instances of this class? 2. Add a __contains__() method that returns True if self.value contains the given digit. Does 'in' work for this type? 3. Try str() on an instance of your class. What happens? How can you return a better string representation (e.g. to show the actual value)?
H om ew ork 1. Create a class that contains an integer as self.value and with a __len__ method that returns the number of digits of the integer. Does len() work for instances of this class? class CustomInteger: def __init__(self, value): self.value = value def __len__(self): return len(str(self.value))
H om ew ork 2. Add a __contains__() method that returns True if self.value contains the given digit. Does 'in' work for this type? class CustomInteger: def __init__(self, value): self.value = value def __len__(self): return len(str(self.value)) def __contains__(self, digit): return str(digit) in str(self.value)
H om ew ork 3. Try str() on an instance of your class. What happens? How can you return a better string representation (e.g. to show the actual value)? class CustomInteger: def __init__(self, value): self.value = value def __len__(self): return len(str(self.value)) def __contains__(self, digit): return str(digit) in str(self.value) def __str__(self): return super().__str__() + ' [{}]'.format(self.value)
H om ew ork 1. Modify the Room, the Door and the BooleanDoor classes to add a toggle() method that changes open status to closed and vice versa. 2. Change the Room class such that it accepts a class instead of an instance. How do you manage it into __init__()? Does it still work? 3. Create a PetDoor object that inherits from Door (or BooleanDoor). Add the suitable methods to manage the small pet door. Does the Room work? 4. May you reuse the Door to create the pet door?
H om ew ork 1. Modify the Room, the Door and the BooleanDoor classes to add a toggle() method that changes open status to closed and vice versa. class Room: def __init__(self, door): self.door = door def open(self): self.door.open() def close(self): self.door.close() def is_open(self): return self.door.is_open() def toggle(self): if self.door.is_open(): self.door.close() else: self.door.open()
H om ew ork 2. Change the Room class such that it accepts a class instead of an instance. How do you manage it into __init__()? Does it still work? class Room: def __init__(self, door_cls): self.door = door_cls() def open(self): self.door.open() def close(self): self.door.close() def is_open(self): return self.door.is_open() >>> room = Room(Door) >>> bool_room = Room(BooleanDoor)
H om ew ork 3. Create a PetDoor object that inherits from Door (or BooleanDoor). Add the suitable methods to manage the small pet door. Does the Room work? class PetDoor(BooleanDoor): def __init__(self): super().__init__() self.pet_door = "open" def open_pet_door(self): self.pet_door = "open" def close_pet_door(self): self.pet_door = "closed"
H om ew ork 4. May you reuse the Door to create the pet door? class PetDoor(BooleanDoor): def __init__(self): super().__init__() self.pet_door = BooleanDoor() def open_pet_door(self): self.pet_door.open() def close_pet_door(self): self.pet_door.close()
“Ask for permission” style try: someobj.open() [...] except AttributeError: [...] It It behaves behaves like it has like it has the attribute the attribute