Python中依赖于上下文的方法 - 我做错了什么?

时间:2013-04-11 08:43:12

标签: python class methods

我想创建一个类,其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)方法来获得相同的功能吗?

3 个答案:

答案 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”是可执行文件语句)块已结束,因此您无法在此块中引用名称或类对象本身。