在Python的类列表中引用类方法

在Python的类列表中引用类方法,python,class,reference,Python,Class,Reference,我正在用Python 2.6.2编写一个包含查找表的类。大多数情况非常简单,表中包含数据。有些情况更复杂,我希望能够调用函数。但是,我在引用函数时遇到了一些问题 下面是一些示例代码: class a: lut = [1, 3, 17, [12,34], 5] 其中lut是静态的,并且预期也是常量 现在我想做以下几件事: class a: def spam0(self): re

我正在用Python 2.6.2编写一个包含查找表的类。大多数情况非常简单,表中包含数据。有些情况更复杂,我希望能够调用函数。但是,我在引用函数时遇到了一些问题

下面是一些示例代码:

class a:
    lut = [1,
           3,
           17,
           [12,34],
           5]
其中
lut
是静态的,并且预期也是常量

现在我想做以下几件事:

class a:
    def spam0(self):
        return (some_calculation_based_on_self)

    def spam1(self):
        return (a_different_calculation_based_on_self)

    lut = [1,
           3,
           17,
           [12,34],
           5,
           self.spam0
           self.spam1]
这不会编译,因为
self.spam0
self.spam1
未定义。我试过使用
a.spam
,但也没有定义。如何设置
lut[5]
以返回对
self.spam
的引用

编辑:这是我计划做的:

(继续定义
a类
): 进口检验

# continue to somewhere in the definition of class a

def __init__(self, param):
    self.param = param

def eggs(self):
    tmp = lut[param]
    if (insect.isfunction(tmp)): # if tmp is self.spam()
        return tmp()             # should call it here
    return tmp
因此,我想返回一个简单的值或运行一些额外的代码,具体取决于参数

Edit:
lut
不必是类属性,但是方法
spam0
spam1
确实需要访问类成员,因此它们必须属于类


我不确定这是否是最好的方法。我仍在解决这个问题。

您需要将
a.lut
的定义移到
a
的定义之外

class a():
    def spam():pass

a.lut = [1,2,3,a.spam]
如果你仔细想想,这很有道理。使用self不起作用,因为实际上只为使用参数“
self
”的类方法定义了
self
self
在Python中没有特殊意义,不是保留字;它只是传递给绑定类方法的常规参数,但也可以是
this
,或
foo
,或任何您想要的参数


引用
a.lut
不起作用,因为
a
的定义还不完整。在代码中的这一点上,Python如何知道a是什么?在
a
的类定义范围内,
a
本身仍然未定义。

在clas主体中,您正在创建类;没有
self
,因此您显然还不能引用
self.anything
。但是在这个主体中,还没有
a
:name
a
在类主体完成后绑定。因此,尽管这不太明显,但在类
a
的主体中,您也不能引用
a

您可以引用的是已经绑定的类属性的裸名称:例如,您可以在列表的末尾使用
lut
<代码>垃圾邮件
将作为一种功能出现,正如您在某一点上所说的那样;不是作为一种方法,也绝不是作为一种类方法(我在代码中的任何地方都没有看到
classmethod
,为什么你认为类方法会神奇地出现,除非你直接或通过decorator显式地在
classmethod
内置函数中包装一个函数?——我怀疑你使用了“类方法”实际上并没有引用类方法类型(尽管它确实令人困惑;-)

因此,如果您以后需要在
a
的某个实例
x
上调用该函数,您将调用例如
a.lut[-1](x)
,并在那里显式地使用参数


如果您需要做一些更微妙的事情,那么可以在处理过程中的不同时间点获得某种类型的绑定或未绑定方法(在类创建完成之后,或者,如果您需要绑定实例方法,则仅在实例化特定实例之后)。但是你没有清楚完整地解释你到底想做什么,以便我们在后面的阶段提供非常详细的帮助。

当你在课程范围内时,你可以写

class A:
    def spam(self):
        pass

    lut = [1, 2, 3, spam]

a = A()
print a.lut
给予

[1,2,3,]

不要忘记,这是查找表中的一个函数,而不是您可能想要的数字。你可能想解决另一个问题。

我不确定我是否理解这个问题。这就是你的意思吗

class a:
    lut = [1,
           3,
           17,
           [12,34],
           5]

    def __init__(self):
        self.lut.append(self.spam)

    def spam(self, a):
        print "this is %s" % a

b = a()
b.lut[-1](4)
这将输出:“这是4”。

琐碎:

class a:
    @classmethod
    def spam(cls):
        # not really pass, but you get the idea
        pass

    lut = [1,
           3,
           17,
           [12,34],
           5,
           spam]


assert a().lut[-1] == a.spam
assert a.spam() is None

您希望将函数绑定到类。似乎没有一个答案能解决这个问题

这不会自动完成;执行此操作时:

class a:
    def spam(self): print self
    lut = [1, spam]
lut[1]
本身就是垃圾邮件,不是对象的绑定方法,所以不能简单地调用
lut[1]()
;您必须调用
lut[1](self)

如果您特别希望能够在列表中包含可以直接调用的函数,则需要安排绑定这些函数,这意味着从实例而不是从类引用它们。为此,您可能需要从
\uuuu init\uuuu
初始化此列表:

class a:
    def spam(self): print self
    def __init__(self):
        self.lut = [1, self.spam]
现在,self.lut[1]()是正确的,因为它是一个绑定方法

这样做的好处是,其他函数可以出于其他目的而放在列表中,可能会绑定到其他对象,或者不需要参数


它的缺点是没有在实例之间重用列表;这可能对您很重要,也可能不重要。

请记住,Python中没有静态或常量之类的东西。只是让它容易阅读。下面的示例为每个对象生成缓存版本的
lut

class A(object):
    def __init__(self):
        self.__cached_lut = None

    def spam0(self):
        return (some_calculation_based_on_self)

    def spam1(self):
        return (a_different_calculation_based_on_self)

    @property
    def lut(self):
         if self.__cached_lut is None:
             self.__cached_lut = [1,
               3,
               17,
               [12,34],
               5,
               self.spam0()
               self.spam1()]
         return self.__cached_lut

a = A()
print a.lut

请注意,在这个解决方案中(为了以后在实例x上通过lut调用函数),您还需要
a.lut[-1](x)
,就像我建议的方法一样,因为
a.spam
这里是一个未绑定的方法,不为您提供任何额外的功能,而不是我正在使用的函数,只是一个额外的错误检查。@Alex,您不必将垃圾邮件称为a.lut[-1](x)。我认为OP更有可能遍历a.lut并调用任何可调用的内容。这种方法很可能存在非音速设计错误,或者它很好地模拟了他的问题。这里真的没有e
class A(object):
    def __init__(self):
        self.__cached_lut = None

    def spam0(self):
        return (some_calculation_based_on_self)

    def spam1(self):
        return (a_different_calculation_based_on_self)

    @property
    def lut(self):
         if self.__cached_lut is None:
             self.__cached_lut = [1,
               3,
               17,
               [12,34],
               5,
               self.spam0()
               self.spam1()]
         return self.__cached_lut

a = A()
print a.lut