class Stack(list):
def push(self, item):
self.append(item)
20 OOP Tricks
20.1 Avoiding Inheritance via Composition
class Stack:
def __init__(self, *, container=None):
if container is None:
= list()
container self._items = container
def push(self, item):
self._items.append(item)
def pop(self):
return self._items.pop()
def __len__(self):
return len(self._items)
Ref: Beazley, David M. Python Distilled (p. 259). Pearson Education. Kindle Edition.
20.2 Avoiding Inheritance via Functions
class DataParser:
def parse(self, lines):
= []
records for line in lines:
= line.split(',')
row = self.make_record(row)
record
records.append(row)return records
def make_record(self, row):
raise NotImplementedError()
class PortfolioDataParser(DataParser):
def make_record(self, row):
return {
'name': row[0],
'shares': int(row[1]),
'price': float(row[2])
}
= PortfolioDataParser()
parser = parser.parse(open('portfolio.csv')) data
def parse_data(lines, make_record):
= []
records for line in lines:
= line.split(',')
row = make_record(row)
record
records.append(row)return records
def make_dict(row):
return {
'name': row[0],
'shares': int(row[1]),
'price': float(row[2])
}
= parse_data(open('portfolio.csv'), make_dict) data
20.3 Static Methods
Sometimes a class is merely used as a namespace for functions declared as static methods using @staticmethod
. Unlike a normal method or class method, a static method does not take an extra self or cls argument. A static method is just a ordinary function that happens to be defined inside a class.
20.3.1 Simple
class Ops:
@staticmethod
def add(x, y):
return x + y
@staticmethod
def sub(x, y):
return x - y
= Ops.add(2, 3)
a = Ops.sub(4, 5) b
Ref: Beazley, David M. Python Distilled (p. 272). Pearson Education. Kindle Edition.
20.3.2 Advanced
class StandardPolicy:
@staticmethod
def deposit(account, amount):
+= amount
account.balance
@staticmethod
def withdraw(account, amount):
-= amount
account.balance
@staticmethod
def inquiry(account):
return account.balance
class EvilPolicy(StandardPolicy):
@staticmethod
def deposit(account, amount):
+= 0.95*amount
account.balance
@staticmethod
def inquiry(account):
import random
if random.randint(0,4) == 1:
return 1.10 * account.balance
else:
return account.balance
class Account:
def __init__(self, owner, balance, *, policy=StandardPolicy):
self.owner = owner
self.balance = balance
self.policy = policy
def __repr__(self):
return f'Account({self.policy}, {self.owner!r}, {self.balance!r})'
def deposit(self, amount):
self.policy.deposit(self, amount)
def withdraw(self, amount):
self.policy.withdraw(self, amount)
def inquiry(self):
return self.policy.inquiry(self)
= Account('Guido', 1000.0)
a
a.policy 500)
a.deposit( a.inquiry()
1500.0
= Account('Guido', 1000.0, policy=EvilPolicy)
b 500)
b.deposit( b.inquiry()
1475.0