在新方法中创建类实例和属性

问题描述 投票:0回答:1

假设我只想在某些计算给出正数时创建一个类实例,否则返回

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`

看起来一切正常。有没有什么缺点呢?因为感觉……不寻常。恐怕我现在还没有发现任何问题,但稍后修复可能会很痛苦,所以我想向自己澄清这一点。

python attributes initialization
1个回答
0
投票

因此,用于条件实例创建的

__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`

这允许您将初始化与条件逻辑分开。

© www.soinside.com 2019 - 2024. All rights reserved.