我想创建一个类,其f方法依赖于已创建类对象的“模式”。
下面的代码不起作用,但希望它让您了解我想要做的事情。我的想法是有一个字典,我在其中定义每个模式的设置(在这种情况下是分配给self.f的函数或方法,所以不要使用很多if if ifif语句 在init函数中,我只需使用字典分配正确的值。
class A(object):
_methods_dict={
'a':A.f1,
'b':A.f2
}
def __init__(self,mode = 'a'):
self.f = _methods_dict[mode]
def f1(self,x):
return x
def f2(self,x):
return x**2
我无法理解为什么这不起作用,你会如何解决它? 还有更好的(和更多的pythonic)方法来获得相同的功能吗?
答案 0 :(得分:4)
存储两个函数的名称,然后使用getattr()
检索__init__
中的绑定方法:
class A(object):
_methods_dict = {
'a': 'f1',
'b': 'f2'
}
def __init__(self, mode='a'):
self.f = getattr(self, self._methods_dict[mode])
def f1(self, x):
return x
def f2(self, x):
return x ** 2
或者,只需代理该方法:
class A(object):
_methods_dict = {
'a': 'f1',
'b': 'f2'
}
def __init__(self,mode = 'a'):
self._mode = mode
@property
def f(self):
return getattr(self, self._methods_dict[self._mode])
def f1(self, x):
return x
def f2(self, x):
return x ** 2
f
属性只返回当前模式的正确绑定方法。使用属性可简化调用签名处理,并为用户提供实际的内省方法。
两种方法都有相同的最终结果:
>>> a1 = A()
>>> a2 = A('b')
>>> a1.f(10)
10
>>> a2.f(10)
100
区别在于实例中存储的内容,第一种方法存储绑定方法:
>>> vars(a1)
{'f': <bound method A.f1 of <__main__.A object at 0x10aa1ec50>>}
>>> vars(a2)
{'f': <bound method A.f2 of <__main__.A object at 0x10aa1ed50>>}
与另一种方法相比:
>>> vars(a1)
{'_mode': 'a'}
>>> vars(a2)
{'_mode': 'b'}
这可能看起来没什么大不同,但后一种方法创建的实例可以被腌制和深度复制而没有问题。
答案 1 :(得分:0)
您可以创建两个单独的类:
class Base(object):
# place here all attributes shared in common among the Modes
pass
class ModeA(Base):
def f(self, x):
return x
class ModeB(Base):
def f(self, x):
return x**2
def make_mode(mode, *args, **kwargs):
mode_dict = {'a':ModeA, 'b':ModeB}
return mode_dict[mode](*args, **kwargs)
a = make_mode('a')
print(a.f(10))
# 10
b = make_mode('b')
print(b.f(10))
# 100
答案 2 :(得分:0)
回答你的第一个问题(“为什么这不起作用”):类对象“A”仅在整个类语句之后被创建并绑定到模块名“A”(是的,“class”是可执行文件语句)块已结束,因此您无法在此块中引用名称或类对象本身。