gpt4 book ai didi

Pythonic 类和 Python 之禅

转载 作者:太空宇宙 更新时间:2023-11-04 08:24:30 25 4
gpt4 key购买 nike

Python之禅说:

“应该有一种——最好只有一种——显而易见的方法来做到这一点。”

假设我想创建一个构建金融交易的类。该类应允许用户构建交易,然后调用 sign() 方法签署交易,为通过 API 调用广播做准备。

该类将具有以下参数:

sender
recipient
amount
signer (private key for signing)
metadata
signed_data

所有这些都是字符串,除了 amount 是一个 int,除了最后两个之外都是必需的:metadata 是一个可选参数,signed_data 在方法 sign() 被调用。

我们希望所有参数在签名发生之前都经过某种验证,这样我们就可以通过向用户提出适当的错误来拒绝格式错误的交易。

使用经典的 Python 类和构造函数,这似乎很简单:

class Transaction:
def __init__(self, sender, recipient, amount, signer, metadata=None):
self.sender = sender
self.recipient = recipient
self.amount = amount
self.signer = signer

if metadata:
self.metadata = metadata

def is_valid(self):
# check that all required parameters are valid and exist and return True,
# otherwise return false

def sign(self):
if self.is_valid():
# sign transaction
self.signed_data = "pretend signature"
else:
# raise InvalidTransactionError

或具有属性:

class Transaction:
def __init__(self, sender, recipient, amount, signer, metadata=None):
self._sender = sender
self._recipient = recipient
self._amount = amount
self._signer = signer
self._signed_data = None

if metadata:
self._metadata = metadata

@property
def sender(self):
return self._sender

@sender.setter
def sender(self, sender):
# validate value, raise InvalidParamError if invalid
self._sender = sender

@property
def recipient(self):
return self._recipient

@recipient.setter
def recipient(self, recipient):
# validate value, raise InvalidParamError if invalid
self._recipient = recipient

@property
def amount(self):
return self._amount

@amount.setter
def amount(self, amount):
# validate value, raise InvalidParamError if invalid
self._amount = amount

@property
def signer(self):
return self._signer

@signer.setter
def signer(self, signer):
# validate value, raise InvalidParamError if invalid
self._signer = signer

@property
def metadata(self):
return self._metadata

@metadata.setter
def metadata(self, metadata):
# validate value, raise InvalidParamError if invalid
self._metadata = metadata

@property
def signed_data(self):
return self._signed_data

@signed_data.setter
def signed_data(self, signed_data):
# validate value, raise InvalidParamError if invalid
self._signed_data = signed_data

def is_valid(self):
return (self.sender and self.recipient and self.amount and self.signer)

def sign(self):
if self.is_valid():
# sign transaction
self.signed_data = "pretend signature"
else:
# raise InvalidTransactionError
print("Invalid Transaction!")

我们现在可以在设置时验证每个值,所以在我们签名时我们知道我们有有效的参数,is_valid() 方法只需要检查是否已设置所有必需的参数.与在单个 is_valid() 方法中进行所有验证相比,这对我来说感觉更像 Pythonic,但我不确定所有额外的样板代码是否真的值得。

使用数据类:

@dataclass
class Transaction:
sender: str
recipient: str
amount: int
signer: str
metadata: str = None
signed_data: str = None

def is_valid(self):
# check that all parameters are valid and exist and return True,
# otherwise return false

def sign(self):
if self.is_valid():
# sign transaction
self.signed_data = "pretend signature"
else:
# raise InvalidTransactionError
print("Invalid Transaction!")

将此与方法进行比较

1,这还不错。它简洁、干净、可读,并且已经内置了 __init__()__repr__()__eq__() 方法。另一方面,与Approach相比

2 我们回到通过大量的 is_valid() 方法验证所有输入。

我们可以尝试将属性与数据类一起使用,但这实际上比听起来更难。根据this blog post可以这样做:

@dataclass
class Transaction:
sender: str
_sender: field(init=False, repr=False)
recipient: str
_recipient: field(init=False, repr=False)
. . .
# properties for all parameters

def is_valid(self):
# if all parameters exist, return True,
# otherwise return false

def sign(self):
if self.is_valid():
# sign transaction
self.signed_data = "pretend signature"
else:
# raise InvalidTransactionError
print("Invalid Transaction!")

有没有一种而且只有一种明显的方法可以做到这一点?是否建议将数据类用于此类应用程序?

最佳答案

作为一般规则,不限于 Python,编写“fails fast”代码是个好主意:也就是说,如果在运行时出现问题,您希望它被检测到并发出信号(例如,通过尽早抛出异常。

特别是在调试上下文中,如果错误是设置了无效值,您希望在设置值时抛出异常,以便堆栈跟踪包括设置无效值的方法。如果在使用该值时抛出异常,则您无法指示代码的哪一部分导致了无效值。

在您的三个示例中,只有第二个示例允许您遵循这一原则。它可能需要更多的样板代码,但与没有有意义的堆栈跟踪的调试相比,编写样板代码很容易并且不会花费太多时间。

顺便说一句,如果您有执行验证的 setter ,那么您也应该从构造函数中调用这些 setter ,否则可能会创建一个初始状态无效的对象。

关于Pythonic 类和 Python 之禅,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58702396/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com