Autosave: 2023-02-17 12:05:32

This commit is contained in:
thomasabishop 2023-02-17 12:05:32 +00:00
parent 7afcd00f8e
commit 31938fa75c
3 changed files with 164 additions and 5 deletions

View file

@ -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.

View file

@ -27,24 +27,112 @@ class Person:
self.age += 1
print('You are now', self.age)
p1 = Person('John', 36)
p2 = Person('Thomas', 34)
print(p1)
print(p2)
print(p1.name)
# <__main__.Person object at 0x102e75510>
# <__main__.Person object at 0x102e75511>
# John
```
Key points to note:
- 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
- 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
## 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
```

View file

@ -19,6 +19,7 @@
- Modules
- Error handling
- Testing
- I/O
## Bash
@ -59,6 +60,8 @@
## NodeJS
- 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