在Python类构造函数中只允许一对参数中的一个的最佳方法是什么?

2024-10-04 01:27:06 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个类,它的基本功能与下面的示例类似。构造函数接受两个参数,如果没有给定值,则这两个参数都默认为None。该类的目标是,给定foo的值,用户可以调用calculateBar()函数来计算bar的值。相反,用户应该能够为bar提供一个值,然后调用calculateFoo()函数来计算foo的值。值得注意的是,这些函数本质上是彼此的逆函数

class ExampleClass:
    def __init__(self, foo=None, bar=None):
        self.foo = foo
        self.bar = bar

        # Essentially an XNOR. Raises an exception if:
        # 1. Both foo and bar are 'None' (no value given for either)
        # 2. Neither foo, nor bar are 'None' (value given for both)
        if bool(foo == None) == bool(bar == None):
            raise ValueError("Please give a value for Foo or Bar (but not both)")

    def calculateFoo(self):
        return self.bar / 2.0

    def calculateBar(self):
        return self.foo * 2.0

我遇到的问题是,我想限制类只允许用户为foobar提供一个值,但不能同时提供这两个值,也就是说,其中一个值应该正好包含一个值,另一个值应该是None。我当前的方法是在foo=None and bar=Nonefoo!=None and bar!=None的情况下简单地引发一个异常。然而,这似乎是一个不雅观的解决方案。是否有更好的方法限制用户只输入两个参数中的一个,但仍然允许正确使用calculateFoo()calculateBar()函数?有没有更好的方法来组织课程,以满足我的需要


Tags: and方法函数用户selfnoneanfor
2条回答

正如评论中所建议的,您可以将类ExampleClass拆分为两个独立的类。目前,您的类正在尝试执行foobar操作,但如果未定义一个,则可能会引发异常,因为调用calculateFoo()calculateBar()时未定义一个成员

您可以做的是使用带有函数calculate()abstract base class并由此派生两个独立的类FooBar。派生类将被强制重写该函数。抽象基类纯粹是一个模板——您将无法创建它的实例,但它充当派生类的模板

例如:

from abc import ABC, abstractmethod

class BaseClass(ABC):
    @abstractmethod
    def calculate(self):
        pass

class Foo(BaseClass):
    def __init__(self, foo):
        self.foo = foo

    def calculate(self):
        return self.foo / 2.0

class Bar(BaseClass):
    def __init__(self, bar):
        self.bar = bar

    def calculate(self):
        return self.bar * 2.0


foo = Foo(10)
print(foo.calculate())

bar = Bar(10)
print(bar.calculate())

输出:

5.0
20.0

我认为你的__init__基本上是好的,但是首先检查两个参数

一旦确定只传递了一个值,请根据它设置另一个值

class ExampleClass:
    def __init__(self, foo=None, bar=None):
        if foo is not None and bar is not None:
            raise ValueError("Please give a value for Foo or Bar (but not both)")

        if foo is None:
            self.bar = bar
            self.foo = bar / 2.0
        else:
            self.foo = foo
            self.bar = foo * 2.0

一个改进是提供特定的类方法来为单个值创建实例,并且不鼓励使用ExampleClass.__new__本身

class ExampleClass:

    def __init__(self, foo, bar):
        self.foo = foo
        self.bar = bar

    @classmethod
    def from_foo(cls, value):
        return cls(foo=value, bar=value/2)

    @classmethod
    def from_bar(cls, value):
        return cls(bar=value, foo=value*2)

相关问题 更多 >