我有一个像下面这样的课程:
class Invoice
def __init__(self, invoice_id):
self.invoice_id = invoice_id
self._amount = None
@property
def amount(self):
return self._amount
@amount.setter
def amount(self, amount):
self._amount = amount
在上面的示例中,每当我尝试在不设置发票金额的情况下尝试获取发票金额时,都将显示“无”,如下所示:
invoice = Invoice(invoice_id='asdf234')
invoice.amount
>> None
但是在这种情况下,“ None”不是正确的金额默认值。我应该能够区分金额值,因为根本没有设置任何值。所以问题如下:
self._amount = None
,我将为self._amount获取AttributeError,而self.amount仅在调用invoice.amount = 5
之后才返回有效值。这是正确的处理方式吗?但这也会导致对象状态不一致,因为应用程序将在运行时更改实例属性。答案 0 :(得分:2)
在这种情况下,请勿使用property
。您的获取器和设置器除了返回并设置值之外,什么都不做。只需使用常规属性。如果以后要控制访问,则可以稍后再添加该属性,而无需更改类的界面!
对于处理未设置的值,只需创建自己的对象来表示从未设置过的值即可。它可以很简单:
>>> NOT_SET = object()
>>> class Invoice:
... def __init__(self, invoice_id):
... self.invoice_id = invoice_id
... self.amount = NOT_SET
...
>>> inv = Invoice(42)
>>> if inv.amount is NOT_SET:
... inv.amount = 1
...
如果想要更好的打字支持,也可以使用enum
。
答案 1 :(得分:2)
None
通常用于不存在值的情况,但是有时您实际上需要将其作为允许的值。如果您希望能够区分None
和未设置的值,只需为此定义您自己的单例。
class Undefined:
__str__ = __repr__ = lambda self: "Undefined"
Undefined = Undefined()
class Invoice
def __init__(self, invoice_id):
self.invoice_id = invoice_id
self._amount = Undefined
@property
def amount(self):
return self._amount
@amount.setter
def amount(self, amount):
if amount is Undefined:
raise ValueError("amount must be an actual value")
self._amount = amount
当然,您现在可能需要使用其他方法测试Undefined
,以确保在实例正确初始化之前未使用它们。更好的方法可能是在初始化期间设置属性,并要求将其值传递到__init__()
中。这样,可以避免使Invoice
处于无效(未完全初始化)状态。有人仍然可以将_amount
设置为无效值,但是他们只会遇到他们想要的麻烦。我们都是成年人。
答案 2 :(得分:1)
您可以创建一个静态类,并使用它来确定是否设置了一个值。
class AmountNotSet(object):
pass
class Invoice(object):
def __init__(self, invoice_id):
self.invoice_id = invoice_id
self._amount = AmountNotSet
# ...etc...
然后您可以像这样检查发票是否已设置:
invoice1 = Invoice(1)
invoice2 = Invoice(2)
invoice2.amount = None
invoice1.amount is AmountNotSet # => True
invoice2.amount is None # => True