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

时间:2009-08-29 15:11:45

标签: python class reference

我正在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.spam0self.spam1未定义,因此无法编译。我尝试使用a.spam,但这也是未定义的。如何设置lut[5]以返回对self.spam的引用?

修改:这就是我打算做的事情:

(继续class 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

所以我要么返回一个简单的值,要么运行一些额外的代码,具体取决于参数。

修改: lut不一定是类属性,但方法spam0spam1确实需要访问类成员,所以他们必须属于这个班级。

我不确定这是最好的方法。我还在努力解决这个问题。

7 个答案:

答案 0 :(得分:4)

在clas体中,你正在创建这个类;没有self,所以你显然还不能引用self.anything。但是在该体内还没有a:名称a在类体完成后被绑定。所以,虽然这有点不太明显,但在课堂a中你还不能引用a.anything

您可以引用的是已经绑定的类属性的裸名称:例如,您可以在列表5, spam]的末尾使用lutspam将作为一个函数存在,就像你曾经说过的那样;不是作为一个方法,而且绝对不是作为一个类方法(我没有在你的代码中看到classmethod ANYWHERE,为什么你认为一个类方法会神奇地存在,除非你明确地将一个函数包装在{ {1}}内置,直接或由装饰器?) - 我怀疑你使用“类方法”实际上并没有引用类方法类型(尽管它确实令人困惑; - )。

因此,如果您以后需要在classmethod的某个x实例上调用该函数,那么您将调用例如a,其中明确有论据。

如果你需要做一些更微妙的事情,有可能在处理过程中的各个点获得某种绑定或未绑定的方法(在类创建完成之后,或者,如果你想要一个绑定的实例方法,只有在特定实例被实例化)。但是你没有清楚而完整地解释你想做什么,为我们提供关于这个后期替代品的非常详细的帮助。

答案 1 :(得分:2)

当你在班级范围内时,你可以写

class A:
    def spam(self):
        pass

    lut = [1, 2, 3, spam]

a = A()
print a.lut

给出

[1, 2, 3, <function spam at 0xb7bb764c>]

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

答案 2 :(得分: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

答案 3 :(得分:0)

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

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”。

答案 4 :(得分:0)

琐碎:

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

答案 5 :(得分:0)

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

这不会自动完成;当你这样做时:

class a:
    def spam(self): print self
    lut = [1, spam]

lut[1]本身就是垃圾邮件,不是对象的绑定方法,因此您不能简单地调用lut[1]();你必须致电lut[1](self)

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

初始化此列表
class a:
    def spam(self): print self
    def __init__(self):
        self.lut = [1, self.spam]

现在self.lut[1]()是正确的,因为它是一种绑定方法。

这一切都具有以下优点:其他函数可以放在列表中用于其他目的,可能绑定到其他对象或者不期望参数。

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

答案 6 :(得分:-1)

您需要将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本身仍未定义。