python - OOP:如何编写类之间的pythonic交互?
问题描述
我想对两个类之间的交互进行建模,其中一个类将另一个类作为其方法之一中的参数。哪个类应该在另一个类的方法的参数中?
我已经为该问题编写了两种替代解决方案,但我不确定其中哪一种被认为是处理此问题的正确方法。也许还有更好的方法,但这是我的两个选择:
class BankAccount:
def __init__(self, balance):
self._balance = balance
def transaction(self, cash):
self._balance += cash._value
cash._value = 0
class Cash:
def __init__(self, value):
self._value = value
def transfer(self, bank_account):
bank_account._balance += self._value
self._value = 0
if __name__ == "__main__":
# First alternative
acc = BankAccount(balance=100)
cash = Cash(value=10)
print('-' * 30)
print('First alternative')
print(f'Account balance before: {acc._balance}')
print(f'Cash value before: {cash._value}')
acc.transaction(cash=cash)
print(f'Account balance after: {acc._balance}')
print(f'Cash value after: {cash._value}')
# Second alternative
acc = BankAccount(balance=100)
cash = Cash(value=10)
print('-' * 30)
print('Second alternative')
print(f'Account balance before: {acc._balance}')
print(f'Cash value before: {cash._value}')
cash.transfer(bank_account=acc)
print(f'Account balance after: {acc._balance}')
print(f'Cash value after: {cash._value}')
正如您所看到的,这两种替代方案都显示了相同的结果,但我很高兴获得对这种类交互建模的 Pythonic 方式的建议。谢谢。
解决方案
该示例格式不正确,这使我们无法专注于实际的 OOP。一些现金因为被转移而失去价值是没有意义的。一张 20 美元的钞票是否会因为您将其存入银行而失去其价值?
一个新的例子
相反,让我们考虑表示两个银行账户之间的资金转移的问题。
OOP 的一个关键概念是不应直接更新实例的属性。相反,实例应该通过提供对其状态进行一些控制的方法来提供 API。
我们可以通过定义方法deposit
和withdraw
为BankAccount
. 这样,我们就可以定义transfer_to
只使用这个 API 的方法。
class BankAccount:
def __init__(self):
self.balance = 0
def deposit(self, amount):
self.balance += amount
def withdraw(self, amount):
if amount >= self.balance:
self.balance -= amount
else:
raise ValueError('Insufficient funds')
def transfer_to(self, target, amount):
if isinstance(target, BankAccount):
self.withdraw(amount)
target.deposit(amount)
else:
raise ValueError("'target' must be another BankAccount")
优势
通过封装和的逻辑withdraw
,我们允许通过继承简单地实现更复杂的账户类型。deposit
tranfer_to
BankAccount
在这里,让我们举一个允许负余额的新型示例。
class CreditAccount(BankAccount):
def withdraw(self, amount):
self._balance -= amount
通过将提款的责任完全委托给 的实例BankAccount
,我们允许外部代理在无需了解提款和存款的内部逻辑的情况下操纵账户。
推荐阅读
- java - Spring Boot 单元测试如何加载文件
- wordpress - 如何将 Authorize.net API 导入 Wordpress?
- node.js - NodeJS express 添加 style.css 静态
- javascript - 猫鼬返回空数组
- java - Spring Boot JPA Native Query - 不是基于参数的空检查
- spring-tools-4 - sts 4.7.0.RELEASE 启动嵌入式mongo
- c# - 如何检查 RGB 颜色以及如何知道此范围是绿色还是红色?
- excel - 如何使用VBA获取excel中每个类别的总和?
- swift - 在主 VC 到第二个 VC 之间传递数据在 Swift 中不起作用
- ios - [[String:String]] 和有什么区别!和 Swift 中的 [[String:String]]()