也许我完全错了但是我遇到了lambda调用@classmethod的一些奇怪的问题。
我有以下课程:
class MyClass:
LAMBDA = lambda: MyClass.ClassMethod()
@classmethod
def ClassMethod(cls):
pass
但是每当使用LAMBDA调用时,这都会失败:
TypeError: unbound method <lambda>() must be called with MyClass instance as first argument (got nothing instead)
我真的不明白为什么会这样。我已经花了一些时间试图让它工作。我需要一些由该lambda填充的类属性,并且在该阶段显然不可能自引用该类。
答案 0 :(得分:2)
您必须明白,您的代码完全等同于
class MyClass:
def LAMBDA():
return MyClass.ClassMethod()
@classmethod
def ClassMethod(cls):
pass
然后,你显然称它为MyClass.LAMBDA()
。但是看,LAMBDA是一种实例方法。并且你在没有实际实例的情况下调用它。
你究竟想做什么?
我估计,如果你给一个lambda结构命名,你也可以将它称为“正常”方式 - def
。根据我的经验,当使用lambas实际上有助于代码质量时,只有少数孤立的案例。
答案 1 :(得分:2)
LAMBDA
这里只是一种常规方法。当你在课堂上查找它时,你会得到一个未绑定的方法,这是一种愚蠢的事情,它会影响你的功能并强加它 - 虽然self
尚未通过 - 它的第一个参数必须是相关类的实例。
重申一下,LAMBDA = lambda: MyClass.ClassMethod()
与def LAMBDA(): return MyClass.ClassMethod()
没有任何区别。在后一种情况下,更清楚的是你有一种破碎的方法定义。 lambda函数和def函数形成完全相同类型的对象,Python在查找时将它们转换为具有相同规则的方法。
我怀疑你可能想要的代码是
class MyClass(object):
@classmethod
def ClassMethod(cls):
pass
MyClass.LAMBDA = MyClass.ClassMethod
或
class MyClass(object):
@classmethod
def ClassMethod(cls):
pass
@classmethod
def LAMBDA(cls):
return cls.ClassMethod()
(请注意,最后一个可以像你原来一样用lambda编写,但是没有理由。我不会在我的任何代码中使用= lambda
。请注意ClassMethod
并且LAMBDA
不遵循正常的Python大小写样式规则。)
答案 2 :(得分:1)
还有另一个直接解决方案。也许这不是最干净的事情,但我认为这是你想知道的。我自己也遇到了类似的情况。您可以使用staticmethod()
故意解除绑定。
这是错误的版本:
def bar(): return 0
class foo(object):
x = lambda:bar()
@classmethod
def grok(klass):
return klass.x()
foo().grok()
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "<console>", line 4, in grok
TypeError: unbound method <lambda>() must be called with foo instance as first argument (got nothing instead)
略有调整的版本:
def bar(): return 0
class foo(object):
x = staticmethod(lambda:bar())
@classmethod
def grok(klass):
return klass.x()
foo().grok()
0
请注意,上述两种情况也适用于:
x = bar
相反。我只是将lambda包含在对这个问题的直接回应中。以上所有建议也有效,这只是尽可能少地改变代码的直接方式。
至于为什么人们想要用lambda这样做上面的工作呢?在我的例子中,我正在制作一个工厂类,它具有偶尔使用类范围数据来获取信息的事件处理程序,而且其中一些信息具有价值或可调用性质。 (这是一个Django形式。)所以“callable”是一个由用户提交的直接lambda,必须使用self.value()
或klass.value()
调用,但value
是未绑定的功能(lambda或其他)。
答案 3 :(得分:0)
我需要一些由该lambda填充的类属性,并且在该阶段显然不可能自引用该类。
但是从您给定的代码中,所有LAMBDA在调用时都会执行调用MyClass.ClassMethod()
,这意味着执行填充的方法是ClassMethod
(这当然是假设正文ClassMethod
的{{1}}实际上并不是你所展示的唯一pass
,因为如果它正在做所有这一切都是徒劳的练习。除非您的代码的某些方面阻止您在将其用于任何内容之前引用该类,否则为什么不能在类定义之后调用MyClass.ClassMethod()
?
如果你试图在定义中修改类的属性(也就是说,在MyClass的定义中调用LAMBDA,在任何方法/函数/之外调用),你可能想看看这个部分有关metaclasses的文档。
另外,如果你想为一个类赋予属性,你甚至不需要在类本身中这样做。
>>> class cls(object): # or just "class cls:"
... pass
...
>>> cls.value = 10
>>> cls.name = 'class'
>>> cls.value
10
>>> cls.name
'class'
>>> dir(cls)
['__class__', '__delattr__', '__dict__', '__doc__', '__format__',
'__getattribute__', '__hash__', '__init__', '__module__', '__new__',
'__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__',
'__str__', '__subclasshook__', '__weakref__', 'name', 'value']