我尝试了以下内容:
def __init__(self, name, x, y, z, cg_x = 0, cg_y = 0, cg_z = 0, mass, inertia):
self.ref_x = x
self.ref_y = y
self.ref_z = z
self.cg_x = cg_x
self.cg_y = cg_y
self.cg_z = cg_z
self.name = name
self.mass = mass
self.inertia = inertia
正如预期的那样,python抱怨构造函数不正确。
但是我怎么重塑这个呢?我确实试图阻止(A)在质量/惯性之后移动cg_x / y / z。并且(B)我仍然希望提供不必定义那些的选项。
答案 0 :(得分:1)
在Python 3中,您可以将mass
和inertia
指定为keyword-only arguments。在Python 2中,您必须使用**kwargs
并从kwargs中手动提取mass
和inertia
。
请注意,使用此设置时,mass
和inertia
必须按关键字传递。从概念上讲,除非为所有mass
参数传递值,否则无法在位置上传递inertia
和cg_
。如果您想传递mass
但不是cg_x
的值,则唯一的选择就是foo('name', 'x', 'y', 'z', mass=0, inertia=0)
。在Python中不可能定义一个带有参数的函数,“只有时候”必须通过关键字传递,所以如果必须通过关键字传递参数的任何情况,你必须使它们总是按关键字传递。
答案 1 :(得分:0)
也许创建一个classmethod
,这是一个替代构造函数?
class SomeThing(object):
def __init__(self, name, x, y, z, cg_x, cg_y, cg_z, mass, inertia):
self.ref_x = x
self.ref_y = y
self.ref_z = z
self.cg_x = cg_x
self.cg_y = cg_y
self.cg_z = cg_z
self.name = name
self.mass = mass
self.inertia = inertia
@classmethod
def no_cg(cls, name, x, y, z, mass, inertia):
return cls(name, x, y, z, 0, 0, 0, mass, inertia)
然后你可以做任何一个:
foo = SomeThing('bar', 1, 2, 3, 4, 5, 6, "10g", some_vector)
或
foo = SomeThing.no_cg('bar', 1, 2, 3, "10g", some_vector)
或者为mass
和inertia
添加默认参数,然后测试它们
class SomeThing(object):
def __init__(self, name, x, y, z, cg_x=0, cg_y=0, cg_z=0, mass=None, inertia=None):
if mass is None or inertia is None:
raise ValueError("Must provide mass and inertia values")
self.ref_x = x
self.ref_y = y
self.ref_z = z
self.cg_x = cg_x
self.cg_y = cg_y
self.cg_z = cg_z
self.name = name
self.mass = mass
self.inertia = inertia
答案 2 :(得分:0)
你声称你在重载(我假设)C ++时这样做了。但是除name
之外的所有参数看起来都是相同的类型。很明显,你只是在参数的数字上重载,而不是类型。像这样:
ClassName(string name, double x, double y, double z,
double mass, double inertia) :
name_(name), x_(x), y_(y), z_(z),
cg_x_(0), cg_y_(0), cg_z(0),
mass_(mass), inertia_(inertia) {}
ClassName(string name, double x, double y, double z,
double cg_x, double cg_y, double cg_z,
double mass, double inertia) :
name_(name), x_(x), y_(y), z_(z),
cg_x_(cg_x), cg_y_(cg_y), cg_z(cg_z),
mass_(mass), inertia_(inertia) {}
你想知道如何在Python中做类似的事情。
最好的方法可能就是:
def __init__(self, name, x, y, z, *args):
self.name, self.x, self.y, self.z = name, x, y, z
if len(args) == 2:
self.cg_x = self.cg_y = self.cg_z = 0
self.mass, self.inertia = args
else:
self.cg_x, self.cg_y, self.cg_z, self.mass, self.inertia = args
虽然你可以做一些像:
def __init__(self, name, x, y, z, cg_x_or_mass, cg_y_or_inertia,
cg_z=None, mass=None, inertia=None):
self.name, self.x, self.y, self.z = name, x, y, z
if cg_z is None:
self.cg_x = self.cg_y = self.cg_z = 0
self.mass, self.inertia = cg_x_or_mass, cg_y_or_inertia
else:
self.cg_x, self.cg_y, self.cg_z = cg_x_or_mass, cg_y_or_inertia, cg_z
self.mass, self.inertia = mass, inertia
然而,无论哪种方式,这都有点难看。在Python中,重载总是有点丑陋;我们鼓励您使用关键字参数或替代构造函数,或者在某些情况下设置一些"可选"建设后的属性。但它有时很有用。
您还提到了RTTI。 Python的RTTI比C ++更好 。您可以为任何对象编写type(spam)
,并获取一个类对象(type
或其他元类的实例);您可以使用__dict__
函数检查其vars
,您可以使用inspect
模块对对象或其类型等执行各种操作。或者,使用第三方模块,你可以得到类似Dylan或Common Lisp的多重调度(比如虚函数,但是切换所有参数的类型,而不仅仅是self
)。但我不确定你是如何在这里实际使用的。如果参数的运行时类型在某种程度上相关,那将很容易;例如,isinstance(cg_x_or_mass, int)
会告诉您cg_x_or_mass
是否为int
。但我不知道你对此做了什么。