1.2. Interface¶
Python don't have interfaces
Cannot instantiate
Inheriting class must implement all methods
Only method declaration
Since Python 3.8: PEP 544 -- Protocols: Structural subtyping (static duck typing)
- interface¶
Software entity with public methods and attribute declaration
- implement¶
Class implements interface if has all public fields and methods from interface
1.2.1. Example¶
Interfaces:
from datetime import timedelta
class CacheInterface:
timeout: timedelta
def get(self, key: str) -> str:
raise NotImplementedError
def set(self, key: str, value: str) -> None:
raise NotImplementedError
def is_valid(self, key: str) -> bool:
raise NotImplementedError
1.2.2. Use Case - 0x01¶
Interfaces:
from datetime import timedelta
class Cache:
timeout: timedelta
def get(self, key: str) -> str:
raise NotImplementedError
def set(self, key: str, value: str) -> None:
raise NotImplementedError
def is_valid(self, key: str) -> bool:
raise NotImplementedError
class CacheDatabase(Cache):
timeout: timedelta
def is_valid(self, key: str) -> bool:
...
def get(self, key: str) -> str:
...
def set(self, key: str, value: str) -> None:
...
class CacheRAM(Cache):
timeout: timedelta
def is_valid(self, key: str) -> bool:
...
def get(self, key: str) -> str:
...
def set(self, key: str, value: str) -> None:
...
class CacheFilesystem(Cache):
timeout: timedelta
def is_valid(self, key: str) -> bool:
...
def get(self, key: str) -> str:
...
def set(self, key: str, value: str) -> None:
...
fs: Cache = CacheFilesystem()
fs.set('name', 'Mark Watney')
fs.is_valid('name')
fs.get('name')
ram: Cache = CacheRAM()
ram.set('name', 'Mark Watney')
ram.is_valid('name')
ram.get('name')
db: Cache = CacheDatabase()
db.set('name', 'Mark Watney')
db.is_valid('name')
db.get('name')
1.2.3. Assignments¶
"""
* Assignment: OOP Interface Define
* Complexity: easy
* Lines of code: 13 lines
* Time: 8 min
English:
1. Define interface `IrisInterface`
2. Attributes: `sepal_length, sepal_width, petal_length, petal_width`
3. Methods: `sum()`, `len()`, `mean()` in `IrisInterface`
4. All methods and constructor must raise exception `NotImplementedError`
5. Run doctests - all must succeed
Polish:
1. Zdefiniuj interfejs `IrisInterface`
2. Attributes: `sepal_length, sepal_width, petal_length, petal_width`
3. Metody: `sum()`, `len()`, `mean()` w `IrisInterface`
4. Wszystkie metody oraz konstruktor muszą podnosić wyjątek `NotImplementedError`
5. Uruchom doctesty - wszystkie muszą się powieść
Tests:
>>> import sys; sys.tracebacklimit = 0
>>> assert hasattr(IrisInterface, 'mean')
>>> assert hasattr(IrisInterface, 'sum')
>>> assert hasattr(IrisInterface, 'len')
>>> from inspect import isfunction
>>> assert isfunction(IrisInterface.mean)
>>> assert isfunction(IrisInterface.sum)
>>> assert isfunction(IrisInterface.len)
>>> IrisInterface.__annotations__ # doctest: +NORMALIZE_WHITESPACE
{'sepal_length': <class 'float'>,
'sepal_width': <class 'float'>,
'petal_length': <class 'float'>,
'petal_width': <class 'float'>}
>>> iris = IrisInterface(5.8, 2.7, 5.1, 1.9)
Traceback (most recent call last):
NotImplementedError
"""
"""
* Assignment: OOP Interface Implement
* Complexity: easy
* Lines of code: 12 lines
* Time: 8 min
English:
1. Define class `Setosa` implementing `IrisInterface`
2. Implement interface
3. Run doctests - all must succeed
Polish:
1. Stwórz klasę `Setosa` implementującą `IrisInterface`
2. Zaimplementuj interfejs
3. Uruchom doctesty - wszystkie muszą się powieść
Hints:
* `self.__dict__.values()`
* `mean = sum() / len()`
Tests:
>>> import sys; sys.tracebacklimit = 0
>>> assert issubclass(Setosa, IrisInterface)
>>> assert hasattr(Setosa, 'mean')
>>> assert hasattr(Setosa, 'sum')
>>> assert hasattr(Setosa, 'len')
>>> from inspect import isfunction
>>> assert isfunction(Setosa.mean)
>>> assert isfunction(Setosa.sum)
>>> assert isfunction(Setosa.len)
>>> Setosa.__annotations__ # doctest: +NORMALIZE_WHITESPACE
{'sepal_length': <class 'float'>,
'sepal_width': <class 'float'>,
'petal_length': <class 'float'>,
'petal_width': <class 'float'>}
>>> setosa = Setosa(5.1, 3.5, 1.4, 0.2)
>>> setosa.len()
4
>>> setosa.sum()
10.2
>>> setosa.mean()
2.55
"""
class IrisInterface:
sepal_length: float
sepal_width: float
petal_length: float
petal_width: float
def __init__(self,
sepal_length: float,
sepal_width: float,
petal_length: float,
petal_width: float) -> None:
raise NotImplementedError
def mean(self) -> float:
raise NotImplementedError
def sum(self) -> float:
raise NotImplementedError
def len(self) -> int:
raise NotImplementedError
# type: Type
class Setosa:
...