可调用对象作为类的方法 - 我可以让`self`成为拥有该方法的类吗?

时间:2015-03-22 16:21:38

标签: python

在python中,如果类实例具有__call__方法,则它几乎可以像函数一样使用。我希望有一个类B,其方法为A,其中A是具有__call__方法的类的实例。为了进行比较,我还在"传统"中定义了另外两种方法foobar。方式(即使用def)。这是代码:

class A(object):
    def __call__(*args):
        print args

def foo(*args):
    print args

class B(object):
    A = A()
    foo = foo
    def bar(*args):
        print args

当我调用B的任何方法时,它们被传递一个类实例作为隐式的第一个参数(通常称为self)。 然而,我很惊讶地发现b.A()传递了一个A实例,我希望在那里B实例。

In [13]: b = B()

In [14]: b.A()
(<__main__.A object at 0xb6251e0c>,)

In [15]: b.foo()
(<__main__.B object at 0xb6251c0c>,)

In [16]: b.bar()
(<__main__.B object at 0xb6251c0c>,)

是否有一种方法(可能是functools技巧或类似方法)以A()传递对b.A()对象的引用的方式绑定b? / p>

请注意,上述示例是为了说明我的问题而简化的。我没有就我的实际实施用例提出建议,这是不同的。

修改:如果我像这样定义我的班级B,我会得到相同的输出:

class B(object):

    def __init__(self):
        self.A = A()
    foo = foo
    def bar(*args):
        print args

1 个答案:

答案 0 :(得分:1)

您的代码存在问题:

class B(object):
    A = A()

B有一个名为A的成员,它是A的一个实例。当您执行B.A()时,它会调用该__call__实例的方法A(这个实例容易混淆为A);由于它始终是A,而A的方法,args中的实际对象当然是A


你所追求的是descriptor;也就是说,A应该有魔术方法__get__; :

class A(object):
    def __get__(self, cls, instance):
        print(cls, instance)
        return self

class B(object):
    a = A()

b = B()
c = b.a

现在执行b.a时,__get__方法获得Bb作为clsinstance参数,无论它返回什么是属性查找的值(存储在c中的值) - 它可以返回另一个实例,甚至是函数,或抛出AttributeError - 由您自己决定。要有另一个知道Bb的函数;你可以这样做:

class A(object):
    def __get__(self, cls, instance):
        if instance is not None:
            def wrapper():
                print("I was called with", cls, "and", instance)
            return wrapper
        return self

class B(object):
    a = A()

B.a()

代码输出:

I was called with <__main__.B object at 0x7f5d52a7b8> and <class '__main__.B'>

完成任务。