假设我只想在某些计算给出正数时创建一个类实例,否则返回
None
。
我可以创建一个静态方法,然后在里面使用
if - else
...但是为什么我不使用公共实例初始化来创建对象并不直观。如果我希望它成为创建实例的唯一“有效”方式 - 我需要在 __init__
方法中引发异常。
我想知道我是否可以使用
__new__
做不同的事情。所以我编了这样的东西(简化的例子):
class A:
n_contracts: int
def __new__(cls, cash: float, margin: float):
n_contracts = int(cash // margin)
if n_contracts <= 0:
return None
instance = super().__new__(cls)
instance.n_contracts = n_contracts
return instance
def __repr__(self):
return f"A(n_contracts={self.n_contracts})"
a = A(1000, 100)
print(a) # prints `A(n_contracts=10)`
try:
print(A.n_contracts)
except AttributeError as err:
print(err.name)
b = A(-1000, 100)
print(b) # prints `None`
A.n_contracts = 100000
print(a) # prints `A(n_contracts=10)`
c = A(1000, 10)
print(c) # prints `A(n_contracts=100)`
print(A.n_contracts) # prints `100000`
看起来一切正常。有没有什么缺点呢?因为感觉……不寻常。恐怕我现在还没有发现任何问题,但稍后修复可能会很痛苦,所以我想向自己澄清这一点。
因此,用于条件实例创建的
__new__
并不常见,并且预计始终返回类的实例,而不是 None
。您可以创建一个 @classmethod
,如果 n_contracts
为正,则初始化并返回一个实例。
class A:
def __init__(self, n_contracts: int):
self.n_contracts = n_contracts
@classmethod
def create(cls, cash: float, margin: float):
n_contracts = int(cash // margin)
if n_contracts <= 0:
return None
return cls(n_contracts)
def __repr__(self):
return f"A(n_contracts={self.n_contracts})"
a = A.create(1000, 100)
print(a) # prints `A(n_contracts=10)`
try:
print(A.n_contracts)
except AttributeError as err:
print(err.name)
b = A.create(-1000, 100)
print(b) # prints `None`
A.n_contracts = 100000
print(a) # prints `A(n_contracts=10)`
c = A.create(1000, 10)
print(c) # prints `A(n_contracts=100)`
print(A.n_contracts) # prints `100000`
这允许您将初始化与条件逻辑分开。