假设我在Python 2.7中有以下类:
class X():
def __init__(self, alpha=1):
self.alpha = alpha
print self.alpha
def beta(self, gamma=1):
self.gamma = gamma
self.omega = self.alpha + self.gamma
print self.omega
我想使用类定义来创建具有不同默认参数的另一个类定义,例如类似的东西:
Y = f(X, alpha=2, gamma=2)
或
Y = f(X, __init__.alpha=2, beta.gamma=2)
应该相当于:
class Y():
def __init__(self, alpha=2):
self.alpha = alpha
print self.alpha
def beta(self, gamma=2):
self.gamma = gamma
self.omega = self.alpha + self.gamma
print self.omega
是否可以在Python 2.7(或3?)中执行类似的操作?
(我知道你可以使用functools.partial
来完成函数的等价物;所以我想知道类中是否有类似的东西)
答案 0 :(得分:2)
您可以编写一个为您创建类的函数:
def makeclass(alpha, gamma):
class C():
def __init__(self, alpha=alpha):
self.alpha = alpha
print self.alpha
def beta(self, gamma=gamma):
self.gamma = gamma
self.omega = self.alpha + self.gamma
print self.omega
return C
>>> X = makeclass(1, 1)
>>> Y = makeclass(2, 2)
>>> x = X() # X is the class, x is an instance
1
>>> x.beta()
2
>>> y = Y()
2
>>> y.beta()
4
答案 1 :(得分:0)
这个可以完成,但它有点乱。
此代码:
class Foo(base1, base2, ...):
bar = something
baz = something_else
def qux(self):
...
...等同于此代码,但如果Foo
是经典类,我不确定这是否正确:
Foo = type('Foo', (base1, base2, ...), {'bar': something, 'baz': something_else,
'qux': lambda self: ...})
因此我们可以动态创建类,并将自定义方法对象附加到它们。
对于您的具体情况,我们需要进行这些调用(假设您通过继承object
将X转换为新式类)。首先,我们从X中提取方法并应用functools.partial
:
new_init = functools.partial(X.__init__.im_func, # Just X.__init__ in 3.x
alpha=2)
new_beta = functools.partial(X.beta.im_func, # Just X.beta in 3.x
gamma=2)
im_func
属性从未绑定的方法对象中获取基础函数。在Python 3中,没有非绑定方法,所以我们不需要使用这个属性; X.__init__
只是函数本身。
接下来,我们创建类:
Y = type('Y', (object,), {'__init__': new_init, 'beta': new_beta})
不幸的是,我们没有任何合理的方法来获取我们需要重新定义的函数列表。如果我们使用dir()
,我们将获得许多不相关的特殊属性。我们可以使用类的__dict__
,但不包括任何继承的方法。我想我们可能需要在X.__mro__
中搜索完整正确的方法列表:
result = {}
for class_ in X.__mro__:
for name, value in class_.__dict__.items():
if name not in result:
result[name] = value
我们还需要确定在每种情况下要覆盖哪些参数; inspect.getargspec()
是一个很好的起点,但是如果任何方法都是可变参数(例如,如果它们采用*args
或**kwargs
参数),它将无济于事。