假设我有一个类
AmbiguousClass
,它有两个属性,a
和b
(假设它们都是int
,但它可以更通用)。它们通过一些可逆方程相关,这样我就可以从 b 计算 a 并计算出 a 的倒数。
我想让用户可以通过提供
AmbiguousClass
或 a
来实例化 b
,具体取决于对他们来说更容易的方式。请注意,实例化变量的两种方法可以具有相同的签名,因此这不是典型的多态性示例。不提供或两者都提供应该会导致错误/警告。
在
__init__
函数中执行此操作的最 Pythonic 方法或最佳实践是什么?
我最好的猜测是类似的东西,但对我来说它感觉不太Pythonic:
class AmbiguousClass():
def __init__(self, a=None, b=None):
#if no parameter is provided, we raise an error (can not instantiate)
if a is None and b is None:
raise SomeCustomError()
#if both a and b are provided, this seems redundant, a warning is raised
elif a is not None and b is not None:
warnings.warn(f"are you sure that you need to specify both a and b?")
self.a = a
self.b = b
# if a is provided, we calculate b from it
elif a is not None:
self.a = a
self.b = calculateB(self.a)
# if b is provided:
elif b is not None:
self.b =b
self.a = calculateA(self.b)
然后,用户必须通过指定他提供的关键字来实例化该类:
var1, var2 = AmbiguousClass(a=3), AmbiguousClass(b=6)
这感觉有点笨拙,特别是如果用户决定提供参数而不提供关键字(默认情况下为
a
,但从用户角度来看并不清楚,可能会导致意外行为)
您当前的实现实际上非常Pythonic,并且使用带有默认值的关键字参数是Python 中处理可选参数的常见方法。然而,总是有改进的空间。这是使用类方法的另一种方法:
class AmbiguousClass:
def __init__(self, a, b):
self.a = a
self.b = b
@classmethod
def from_a(cls, a):
return cls(a, calculateB(a))
@classmethod
def from_b(cls, b):
return cls(calculateA(b), b)
@staticmethod
def calculateA(b):
# Your formula for calculating a from b here
pass
@staticmethod
def calculateB(a):
# Your formula for calculating b from a here
pass
通过此实现,用户将使用两个类方法之一实例化该类: 蟒蛇
var1 = AmbiguousClass.from_a(3)
var2 = AmbiguousClass.from_b(6)
通过使用具有描述性名称的类方法,用户可以更明确地了解它们提供的值。它还可以防止用户同时使用 a 和 b 或两者都不使用 a 和 b 实例化类的潜在情况,这会导致原始实现中出现错误。