我正在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
的引用?
修改:这就是我打算做的事情:
(继续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
不一定是类属性,但方法spam0
和spam1
确实需要访问类成员,所以他们必须属于这个班级。
我不确定这是最好的方法。我还在努力解决这个问题。
答案 0 :(得分:4)
在clas体中,你正在创建这个类;没有self
,所以你显然还不能引用self.anything
。但是在该体内还没有a
:名称a
在类体完成后被绑定。所以,虽然这有点不太明显,但在课堂a
中你还不能引用a.anything
。
您可以引用的是已经绑定的类属性的裸名称:例如,您可以在列表5, spam]
的末尾使用lut
。 spam
将作为一个函数存在,就像你曾经说过的那样;不是作为一个方法,而且绝对不是作为一个类方法(我没有在你的代码中看到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
本身仍未定义。