假设我有这样的功能:
def id(x): return x
我希望能够将它绑定到任何对象(让我们说x),
x.f = id
能够做到
x.f(1) => 1
但是,类不是常规对象,因为它不起作用:
class X(object): pass X.f = id x.f(1) => unbound method f() must be called with X instance as first argument (got int instance instead)
所以我必须这样做,
X.f=staticmethod(id) X.f(1) => 1
然而,它不适用于常规对象,
x.f=staticmethod(f) x.f(1) => 'staticmethod' object is not callable
那么有没有办法让分配在通用代码中按预期工作呢? 我不知道分配给的对象是否是类对象的常规对象 当指定的对象可能是一个函数?
答案 0 :(得分:3)
import inspect
if inspect.isclass(X):
X.f = staticmethod(f)
else:
X.f = f
问题不在于作业;工作正常。这是类上的函数将self
作为它们的第一个参数,而你的函数却没有。您可以使用
X.__dict__['f']
<function f at 0x023A52F0>
或
X.f
<unbound method X.f>
X.f.im_func
<function f at 0x023A52F0>
(你得到的是一个未绑定的方法,而不是原始的函数,因为在Python 2.x中,当你访问一个类的方法时会发生这种情况。在Python 3.x中,它被改变,你只需要获得原始函数我认为这是为了向后兼容旧式课程。)
这是一件很奇怪的事情:如果你甚至不知道你正在使用的对象是否是一个类,你就是在非常高的抽象层次上工作!就此而言,如果你传递了一个内置类型,比如说一个字符串怎么办?你不能在那上面设置属性!我认为你需要在略低的水平上工作。
答案 1 :(得分:1)
定义要绑定的函数,如下所示:
def id_(self, x):
return x
现在您可以执行以下操作:
X.f = id_
x = X()
x.f(1)
=> 1
答案 2 :(得分:1)
我同意这是相当奇怪的行为。也许这是有原因的;也许它是那些从未得到充分调查的角落案例之一,或者,如果被调查,被认为是如此模糊,以至于不值得解决。有时会发生。
如果您希望将函数指定为类属性的行为始终使其成为静态方法,则可以使用元类执行此操作。
class func2static(type):
def __setattr__(cls, name, value):
if type(value) is type(lambda: 0):
value = staticmethod(value)
type.__setattr__(cls, name, value)
class X(object):
__metaclass__ = func2static
现在让我们看一下类的类和实例都可以分配一个函数,然后可以调用它。
f = lambda x: x
X.f = f
X.f(3) # no exception
x = X()
x.g = f
x.g(3) # also no exception
如果您正在修补其他模块中定义的随机类,这并不能解决问题,但不幸的是,您可能不应该这样做。 : - )