在python中编译时引用继承的方法

时间:2015-06-04 23:00:57

标签: python inheritance function-pointers

我有一个Specialized类,它从@classmethod类继承Generic并将一些字符串映射到方法:

class Generic(object):

    @classmethod
    def generate_static_data(cls):
        return cls.field.upper()


class Specialized(Generic):

    field = 'Some data'

    MAPPING = {
        # NameError: name 'Specialized' is not defined
        'key': Specialized.generate_static_data,
    }

    def __init__(self):
        for key, meth in Specialized.MAPPING.iteritems():
            print(key, meth())

如何引用继承的方法?

  • 我无法通过Specialized类名称引用它(可能是因为该类尚未完全解析,但是?):# NameError: name 'Specialized' is not defined
  • 我不能在没有类名的情况下使用“本地”方法引用它:NameError: name 'generate_static_data' is not defined
  • 如果我通过Generic类引用它,则cls参数指向错误的类。

编辑:显然可能会将引用编码为字符串,并且只在运行时将其展开,但我觉得这不必要地复杂:

MAPPING = {
    'key': 'generate_static_data',
}

def __init__(self):
    for key, meth in Specialized.MAPPING.iteritems():
        print(key, getattr(Specialized, meth)())

此外,在现实世界项目中,这个例子来自,将字符串映射到字符串是默认的,我真的喜欢将一些字符串映射到callables的区别,而不是映射到恰好可解析为的另一个字符串可赎回的。

1 个答案:

答案 0 :(得分:2)

解决方案1 ​​

我知道实现这一目标的最简单方法是:

class Generic(object):

    @classmethod
    def generate_static_data(cls):
        return cls.field.upper()


class Specialized(Generic):

    field = 'Some data'    

    def __init__(self):
        for key, meth in Specialized.MAPPING.iteritems():
            print(key, meth())

Specialized.MAPPING = {
    'key': Specialized.generate_static_data,
}

基本上,定义 Specialized.MAPPING后定义了Specialized ,因此您不会遇到NameError: name 'Specialized' is not defined问题:

>>> Specialized()
('key', 'SOME DATA')
<__main__.Specialized object at 0x1049e9d50>

解决方案2

另一种方法是使用getattr函数并在映射中引用方法名称"generate_static_data"而不是方法对象本身。请注意,只有MAPPING中的所有值都是Specialized上的类方法(继承或其他)时,此特定实现才有效:

class Generic(object):

    @classmethod
    def generate_static_data(cls):
        return cls.field.upper()


class Specialized(Generic):

    field = 'Some data'    

    MAPPING = {
        'key': 'generate_static_data',
    }

    def __init__(self):
        for key, meth in Specialized.MAPPING.iteritems():
            print(key, getattr(Specialized, meth)())

这导致相同的输出:

>>> Specialized()
('key', 'SOME DATA')
<__main__.Specialized object at 0x1065a2cd0>

就个人而言,我认为第一个解决方案更清晰,但第二个解决方案将所有内容都定义在Specialized类中。