Autosave: 2023-02-17 12:05:32
This commit is contained in:
		
							parent
							
								
									7afcd00f8e
								
							
						
					
					
						commit
						31938fa75c
					
				
					 3 changed files with 164 additions and 5 deletions
				
			
		| 
						 | 
					@ -0,0 +1,68 @@
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					categories:
 | 
				
			||||||
 | 
					  - Programming Languages
 | 
				
			||||||
 | 
					tags: [python, OOP]
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Class inheritance in Python
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					We distinguish the **parent/source/superclass** class and the **subclass** that **extends** it.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					A subclass can have more than one parent class that it extends, but this is atypical.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					> The subclass will inherit all attributes and methods of the superclass unless it overrides them.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					In addition to overriding the methods of the parent we can extend them in the child. This is a bit like using an abstract.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Example of class inheritance
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```py
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Person:
 | 
				
			||||||
 | 
					    """ Our superclass
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    def __init__(self, name, age):
 | 
				
			||||||
 | 
					        self.name = name
 | 
				
			||||||
 | 
					        self.age = age
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def birthday(self):
 | 
				
			||||||
 | 
					        print('Happy birthday you were', self.age)
 | 
				
			||||||
 | 
					        self.age += 1
 | 
				
			||||||
 | 
					        print('You are now', self.age)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __str__(self):
 | 
				
			||||||
 | 
					        return self.name + ' is ' + str(self.age)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Employee(Person):
 | 
				
			||||||
 | 
					    """ Our subclass that extends `Person`
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    def __init__(self, name, age, id):
 | 
				
			||||||
 | 
					        super().__init__(name, age)
 | 
				
			||||||
 | 
					        self.id = id
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def calculate_pay(self, hours_worked):
 | 
				
			||||||
 | 
					        rate_of_pay = 7.50
 | 
				
			||||||
 | 
					        if self.age >= 21:
 | 
				
			||||||
 | 
					            rate_of_pay += 2.50
 | 
				
			||||||
 | 
					        return hours_worked * rate_of_pay
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __str__(self):
 | 
				
			||||||
 | 
					        return super().__str__() + ' - id(' + str(self.id) + ')'
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Key points
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- We pass the name of the parent class to the child class as a parameter
 | 
				
			||||||
 | 
					- We must include all of the parent class's attributes in the constructor of the subclass
 | 
				
			||||||
 | 
					- We must use a special `super().__init__(..,...)` method to enact the extension of the parent. This method references the `__init__` class in the parent.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Protected/private methods and attributes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					> Protected methods and attributes are private to the class but can be accessed from any subclass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					> Private methods cannot be accessed from anywhere outside of the class
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					We declare private methods and attributes with a double underscore (`__`). We declare protected methods and attributes with a single underscore (`_`).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This is **convention**, there are not actually private and protected attributes or properties.
 | 
				
			||||||
| 
						 | 
					@ -27,24 +27,112 @@ class Person:
 | 
				
			||||||
        self.age += 1
 | 
					        self.age += 1
 | 
				
			||||||
        print('You are now', self.age)
 | 
					        print('You are now', self.age)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
p1 = Person('John', 36)
 | 
					p1 = Person('John', 36)
 | 
				
			||||||
p2 = Person('Thomas', 34)
 | 
					p2 = Person('Thomas', 34)
 | 
				
			||||||
print(p1)
 | 
					print(p1)
 | 
				
			||||||
print(p2)
 | 
					print(p2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
print(p1.name)
 | 
					print(p1.name)
 | 
				
			||||||
# <__main__.Person object at 0x102e75510>
 | 
					
 | 
				
			||||||
# <__main__.Person object at 0x102e75511>
 | 
					 | 
				
			||||||
# John
 | 
					# John
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Key points to note:
 | 
					Key points to note:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- The `__init__` method is the constructor function and must exist on every class to define the properties of the class
 | 
					- The `__init__` method is the constructor function and must exist on every class to define the properties of the class
 | 
				
			||||||
- Every object that the class instantiates is a unique intem in memory as indicated by the hexadecimal log.
 | 
					 | 
				
			||||||
- `self` is a reference to the class itself and the object it will create, akin to `this` in other languages
 | 
					- `self` is a reference to the class itself and the object it will create, akin to `this` in other languages
 | 
				
			||||||
- You must pass `self` as a parameter to every method (this is a difference from JS)
 | 
					- You must pass `self` as a parameter to every method (this is a difference from JS)
 | 
				
			||||||
- As with functions, we can use docstrings to document the class. What you write here will show up in Intellisense etc
 | 
					- As with functions, we can use docstrings to document the class. What you write here will show up in Intellisense etc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## The `str` method
 | 
					## More complex class
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```py
 | 
				
			||||||
 | 
					class Person:
 | 
				
			||||||
 | 
						""" An example class to hold a persons name and age"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						def __init__(self, name, age):
 | 
				
			||||||
 | 
							self.name = name
 | 
				
			||||||
 | 
							self.age = age
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						def __str__(self):
 | 
				
			||||||
 | 
							return self.name + ' is ' + str(self.age)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						def birthday(self):
 | 
				
			||||||
 | 
							print ('Happy birthday you were', self.age)
 | 
				
			||||||
 | 
							self.age += 1
 | 
				
			||||||
 | 
							print('You are now', self.age)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						def calculate_pay(self, hours_worked):
 | 
				
			||||||
 | 
							rate_of_pay = 7.50
 | 
				
			||||||
 | 
							if self.age >= 21:
 | 
				
			||||||
 | 
								rate_of_pay += 2.50
 | 
				
			||||||
 | 
							return hours_worked * rate_of_pay
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						def is_teenager(self):
 | 
				
			||||||
 | 
							return self.age < 20
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Object references
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					When you log a class you get a reference to its hexadecimal [memory](/Computer_Architecture/Memory/Memory.md) reference.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```py
 | 
				
			||||||
 | 
					p1 = Person('John', 36)
 | 
				
			||||||
 | 
					p2 = Person('Thomas', 34)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					print(p1)
 | 
				
			||||||
 | 
					print(p2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# <__main__.Person object at 0x102e75510>
 | 
				
			||||||
 | 
					# <__main__.Person object at 0x102e75511>
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This shows each object is unique. You can also generate a specific ID with the `id()` method:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```py
 | 
				
			||||||
 | 
					print(id(p1))
 | 
				
			||||||
 | 
					print(id(p2))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# 4379088272
 | 
				
			||||||
 | 
					# 4379088656
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Copying objects
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The same principle that applies to [copying functions](/Programming_Languages/Python/Syntax/Functions_in_Python.md) applies to copying objects created through classes: redeclaration results in a duplicate entity. Thus changes to the duplicate will affect the original.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This becomes obvious when you use `id()` but otherwise might not be apparent. To copy you should therefore declare a new instance of the class.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### The `str` method
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The memory reference isn't very helpful for viewing the data contents. To get around this we can use the builtin `__string__` method which automatically logs whatever properties you put in there:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```py
 | 
				
			||||||
 | 
					class Person:
 | 
				
			||||||
 | 
					    """ An example class to hold a persons name and age"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __init__(self, name, age):
 | 
				
			||||||
 | 
					        self.name = name
 | 
				
			||||||
 | 
					        self.age = age
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __str__(self):
 | 
				
			||||||
 | 
					        return self.name + ' is ' + str(self.age)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					p3 = Person('Thomas', 34)
 | 
				
			||||||
 | 
					print(p3)
 | 
				
			||||||
 | 
					# Thomas is 34
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Deleting objects
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					You might want to delete an object reference because:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- the variable referencing the object goes out of scope
 | 
				
			||||||
 | 
					- the variable is set to `None`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					After the `del` statement is applied to a variable that holds an object, the object will no longer be available and any attempt to reference it will result in an error.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```py
 | 
				
			||||||
 | 
					p1 = Person('J-Man', 76)
 | 
				
			||||||
 | 
					del p1
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -19,6 +19,7 @@
 | 
				
			||||||
  - Modules
 | 
					  - Modules
 | 
				
			||||||
  - Error handling
 | 
					  - Error handling
 | 
				
			||||||
  - Testing
 | 
					  - Testing
 | 
				
			||||||
 | 
					  - I/O
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Bash
 | 
					## Bash
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -59,6 +60,8 @@
 | 
				
			||||||
## NodeJS
 | 
					## NodeJS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- Build examples of read stream and write stream
 | 
					- Build examples of read stream and write stream
 | 
				
			||||||
 | 
					- Can you override parent class methods in JS subclass?
 | 
				
			||||||
 | 
					  - If not in JS, can you do this in TS?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Git
 | 
					## Git
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		
		Reference in a new issue