일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- Protocol
- 715. Range Module
- Convert Sorted List to Binary Search Tree
- Class
- 109. Convert Sorted List to Binary Search Tree
- Generator
- 시바견
- Python
- Python Implementation
- 운영체제
- 프로그래머스
- Decorator
- shiba
- Regular Expression
- attribute
- Python Code
- data science
- 밴픽
- 컴퓨터의 구조
- concurrency
- 43. Multiply Strings
- iterator
- LeetCode
- t1
- kaggle
- 315. Count of Smaller Numbers After Self
- Substring with Concatenation of All Words
- DWG
- 30. Substring with Concatenation of All Words
- 파이썬
- Today
- Total
Scribbling
Python: Interfaces 본문
What is interface? Interface is a set of public methods. In python, 'X object', 'X protocol' and 'X interface' have the same meaning.
In Python, protocol is pretty dynamic. In below example, FrenchDeck class does not inherit any class (other than default 'object' class). However, the class has sequential protocol as it has two magic methods (__len__, __getitem__). Likewise, in Python, object's data type does not matter to the Python Interpreter if the object has valid set of protocols.
Card = namedtuple('Card', ['rank', 'suit'])
class FrenchDeck:
ranks = [str(n) for n in range(2, 11)] + list('JQKA')
suits = ['Spades', 'Diamonds', 'Hearts', 'Clubs']
def __init__(self):
self._cards = [Card(rank, suit) for suit in FrenchDeck.suits for rank in FrenchDeck.ranks]
def __len__(self):
return len(self._cards)
def __getitem__(self, index):
return self._cards[index]
However, what should we do when we want to limit a certain protocol/interface to certain data types? In that case, 'abc' or 'Abstract Base Class' can be very helpful.
We can either inherit pre-defined abcs from collections module or create one by ourselves. However, the first is usually what we should choose.
To make 'FrenchDeck' class properly function with 'random.shuffle', it inherits collections.MutableSequence. Pros and Cons of this are as below.
* Pros: Methods for MutableSequence are all available now. (append, reverse, extend, pop, remove, ...)
* Cons: Need to implement __delitem__ and insert methods as they are absract functions.
import collections
Card = collections.namedtuple('Card', ['rank', 'suit'])
class FrenchDeck(collections.MutableSequence):
ranks = [str(n) for n in range(2, 11)] + list('JQKA')
suits = ['Spades', 'Diamonds', 'Hearts', 'Clubs']
def __init__(self):
self._cards = [Card(rank, suit) for suit in FrenchDeck.suits for rank in FrenchDeck.ranks]
def __len__(self):
return len(self._cards)
def __getitem__(self, index):
return self._cards[index]
def __setitem__(self, position, value):
self._cards[position] = value
def __delitem__(self, position):
del self._cards[position]
def insert(self, position, value):
self._cards.insert(position, value)
deck = FrenchDeck()
import random
random.shuffle(deck)
Pre-defined abc are in collections.abc and numbers. If you need to check if an object is int type, isinstance(x, numbers.Integral) would work.
Although creating an ABC is not recommended, we will now make one here to practice.
import abc
class Tombola(abc.ABC):
@abc.abstractmethod
def load(self, iterable):
"""
add iterable's elements
"""
@abc.abstractmethod
def pick(self):
"""
pick one randomly and remove it from the list
if empty, raise 'LookupError'
"""
def loaded(self):
"""
True if there's at least one element, else False
"""
return bool(self.inspect())
def inspect(self):
"""
return sorted tuple with current elements
"""
items = []
while True:
try:
items.append(self.pick())
except LookupError:
break
self.load(items)
return tuple(sorted(items))
import random
class BingoCage(Tombola):
def __init__(self, items):
self._randomizer = random.SystemRandom()
self._items = []
self.load(items)
def load(self, items):
self._items.extend(items)
self._randomizer.shuffle(self._items)
def pick(self):
try:
return self._items.pop()
except IndexError:
raise LookupError('pick from empty BingoCage')
def __call__(self):
self.pick()
from random import randrange
@Tombola.register
class TomboList(list):
def pick(self):
if self:
position = randrange(len(self))
return self.pop(position)
else:
raise LookupError('pop from empty TomboList')
load = list.extend
def loaded(self):
return bool(self)
def inspect(self):
return tuple(sorted(self))
print(issubclass(TomboList, Tombola))
print(isinstance(TomboList(range(100)), Tombola))
Summary:
Use pre-defined ABCs or register data types to them and use isinstance() to inspect data types.
'Computer Science > Python' 카테고리의 다른 글
Python: Operator Overloading (0) | 2022.04.20 |
---|---|
Python: Inheritance (0) | 2022.04.19 |
Python: ABC Class (0) | 2022.04.07 |
Python: Sequence Protocol (0) | 2022.04.06 |
Python: Pythonic Object (0) | 2022.04.05 |