Both time.gmtime and tmp are functions that take a single argument, so why do the two scripts behave differently?
让我们了解Python的作用
self.func
When an instance attribute is referenced that isn’t a data attribute, its class is searched. If the name denotes a valid class attribute that is a function object, a method object is created by packing (pointers to) the instance object and the function object just found together in an abstract object: this is the method object. When the method object is called with an argument list, a new argument list is constructed from the instance object and the argument list, and the function object is called with this new argument list.
因此,如果func是self中的有效函数对象,那么将创建一个绑定方法对象,该对象期望第一个参数成为调用此函数的对象.
我们现在比较,
print type(time.gmtime)
class Foo(object):
func = time.gmtime
def go(self):
print type(self.func)
return self.func(0.0)
当用Foo().go()调用go时,它将打印出来
那就对了.由于time.gmtime是内置函数(与函数对象不同),因此此处没有创建绑定方法对象.让我们现在尝试你的第二个例子,
def tmp(stamp):
return time.gmtime(stamp)
print type(tmp), tmp
class Foo(object):
func = tmp
def go(self):
print type(self.func), self.func
return self.func(0.0)
会打印
>
由于tmp是一个函数对象,根据上面显示的文档,创建了一个绑定的方法对象,它期望一个Object of Foo成为第一个参数.所以,tmp实际上是以Foo作为实例方法绑定的.当你调用像Foo().go()时,它会在内部调用tmp
Foo.func(self, 0.0)
这是有效的
tmp(self, 0.0)
这就是您收到以下错误的原因
TypeError: tmp() takes exactly 1 argument (2 given)
How can I safely save an ordinary function in a class/instance attribute and call it later from an instance method?
解决方案1:
It is also important to note that user-defined functions which are attributes of a class instance are not converted to bound methods; this only happens when the function is an attribute of the class.
这意味着,当您将用户定义的函数分配给类变量时,将发生绑定的方法构造.但是,如果将其分配给实例,则不会发生.
所以,你可以利用这个优势,就像这样
import time
def tmp(stamp):
return time.gmtime(stamp)
class Foo(object):
def __init__(self):
self.func = tmp # Instance variable, not a class variable
def go(self):
return self.func(0.0)
print time.strftime('%Y', Foo().go())
这里,self.func将转换为tmp(0.0),因为没有绑定方法构造发生.
解决方案2:
class Foo(object):
func = staticmethod(tmp)
def go(self):
# `return Foo.func(0.0)` This will also work
return self.func(0.0)
现在,self.func仍然会引用tmp.它类似于像这样定义你的类
class Foo(object):
@staticmethod
def func(stamp):
return time.gmtime(stamp)
def go(self):
# `return Foo.func(0.0)` This will also work
return self.func(0.0)