分配函数时,类对象是不规则的

时间:2011-01-13 00:25:39

标签: python function functional-programming

假设我有这样的功能:

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

那么有没有办法让分配在通用代码中按预期工作呢? 我不知道分配给的对象是否是类对象的常规对象 当指定的对象可能是一个函数?

3 个答案:

答案 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

如果您正在修补其他模块中定义的随机类,这并不能解决问题,但不幸的是,您可能不应该这样做。 : - )