英文:
Is there a way to require a certain combination of optional parameters be supplied to a python class constructor?
问题
# 以下是翻译好的部分:
我有一个类,可以从两种不同的数据集构建。我希望我的类构造函数接受参数集合A或参数集合B,并在其他情况下引发异常。我想完成这个任务的代码应该如下所示:
```python
class myClass:
def __init__(self, parameterA, (parameterB 或 (parameterC 和 parameterD))):
# 构造类实例
在这里,类实例必须提供parameterA和parameterB,或者parameterA、parameterC和parameterD。
我了解可以通过为参数B、C和D的每个参数提供默认值(=None)来以编程方式执行此操作,但这会遇到这样的问题,即只有parameterA或仅有parameterA和parameterC(例如)将被接受而不会引发TypeError。我可以检查无效的参数组合并引发错误,但感觉应该有一种更简洁的方法来解决这个问题。
如果手动参数检查是唯一的选项,那么应该引发TypeError,还是自定义错误更合适?
我尝试过通过简单地给所有参数提供默认值来创建这个类,但是当函数使用不正确的参数组合调用时,会导致无效的错误。我期望有一种更简洁的方法来解决具有两种不同参数集的构造函数的问题。
<details>
<summary>英文:</summary>
I have a class which can be constructed from two different sets of data. I want my class constructor to accept either set a of parameters or set b of parameters, and raise an exception otherwise. I imagine the code to complete this would look something like:
class myClass:
def init(self, parameterA, (parameterB OR (parameterC AND parameterD))):
#Construct class instance
Where class instances must be given parameterA and parameterB, or parameterA, paramaterC and parameterD.
I understand I can do this programmatically by providing a default (=None) statement for each of parameters B, C and D, but this encounters the issue where just parameterA or just parameterA and parameterC (for example) are accepted without a TypeError. I could check for invalid parameter combinations and raise an error, but it feels there should be a cleaner way to do this.
If manual parameter checking is the only option, would this be a TypeError or is a custom error more appropriate?
I have tried creating this by simply giving all arguments default values, however this results in ineffective errors when the function is called with incorrect parameter combinations. I expect that there is a neater way to solve the issue of a constructor function with 2 different sets of parameters.
This question is similar to [this question](https://stackoverflow.com/questions/24457819/optional-parameters-certain-combination-of-them-required) but due to this being a class constructor function, I do not have the luxury of simply using two different functions.
</details>
# 答案1
**得分**: 0
你可以在你的构造函数中处理它,如下所示:
```python
class myClass:
def __init__(self, parameterA, parameterB = None,**kwargs):
if parameterB is not None:
print("第一种情况")
elif len(kwargs) == 2:
print("第二种情况")
else:
raise ValueError("")
另一种方法是定义一个第二个构造函数,如下所示:
```python
class myClass:
def __init__(self, parameterA, parameterB):
pass
@classmethod
def SecondConstructor(cls, parameterA, parameterC, parameterD):
obj = cls.__new__(cls)
# 在这里执行你需要的操作
return obj
a = myClass(1, 2)
a2 =myClass.SecondConstructor(1, 2, 3)
**注意** 如果你依赖于传递的变量数量,你可以使用 `*args` 来更简单地实现。
<details>
<summary>英文:</summary>
You can handle it in your constructor as follows:
class myClass:
def __init__(self, parameterA, parameterB = None,**kwargs):
if parameterB is not None:
print("case one")
elif len(kwargs) == 2:
print("second case")
else:
raise ValueError("")
Another way is to define a second constructor as follows:
class myClass:
def __init__(self, parameterA, parameterB):
pass
@classmethod
def SecondConstructor(cls, parameterA, parameterC, parameterD):
obj = cls.__new__(cls)
# do here what you need
return obj
a = myClass(1, 2)
a2 =myClass.SecondConstructor(1, 2, 3)
**Note** if you are depending on the number of passed variable, you can do it in a simpler way using `*args`
</details>
# 答案2
**得分**: 0
你可以使用classmethod创建多个构造函数:
```python
class myClass:
def __init__(self, a, other_stuff):
...
@classmethod
def from_parameter_b(cls, a, b):
other_stuff = ... # 可能使用`b`
return cls(a, other_stuff)
@classmethod
def from_parameter_c_and_d(cls, a, c, d):
other_stuff = ... # 可能使用`c`和`d`
return cls(a, other_stuff)
英文:
You can create multiple constructors using classmethods:
class myClass:
def __init__(self, a, other_stuff):
...
@classmethod
def from_parameter_b(cls, a, b):
other_stuff = ... # probably using `b`
return cls(a, other_stuff)
@classmethod
def from_parameter_c_and_d(cls, a, c, d):
other_stuff = ... # probably using `c` and `d`
return cls(a, other_stuff)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论