Python 2.x中的super()没有args

时间:2010-04-24 23:48:00

标签: python

尝试将 super(B, self).method() 转换为简单的bubble()简单调用。 是吗see below

在这个例子中是否可以引用B类?

class A(object): pass

class B(A):
    def test(self):
        test2()

class C(B): pass

import inspect
def test2():
    frame = inspect.currentframe().f_back
    cls = frame.[?something here?]
    # cls here should == B (class)

c = C()
c.test()

基本上,CB的孩子,BA的孩子。然后我们创建c类型的C。然后,对c.test()的调用实际上调用B.test()(通过继承),调用test2()

test2()可以获得父框架frame;通过frame.f_code对方法的代码引用;  self来自frame.f_locals['self'];但是type(frame.f_locals['self'])C(当然),但不是B,其中定义了方法。

获取B的任何方式?

3 个答案:

答案 0 :(得分:3)

找到一种更短的方式super(B, self).test() - > bubble()来自下方。

(与多重继承一起使用,不需要参数,与子类相关)

解决方案是使用inspect.getmro(type(back_self))(其中back_self是来自被调用方的self),然后使用cls将其重复为method_name in cls.__dict__并验证我们的代码引用是这个类中的一个(在find_class_by_code_object(self)嵌套函数中实现)。

bubble()可以使用*args, **kwargs轻松扩展。

import inspect
def bubble(*args, **kwargs):
    def find_class_by_code_object(back_self, method_name, code):
        for cls in inspect.getmro(type(back_self)):
            if method_name in cls.__dict__:
                method_fun = getattr(cls, method_name)
                if method_fun.im_func.func_code is code:
                    return cls

    frame = inspect.currentframe().f_back
    back_self = frame.f_locals['self']
    method_name = frame.f_code.co_name

    for _ in xrange(5):
        code = frame.f_code
        cls = find_class_by_code_object(back_self, method_name, code)
        if cls:
            super_ = super(cls, back_self)
            return getattr(super_, method_name)(*args, **kwargs)
        try:
            frame = frame.f_back
        except:
            return



class A(object):
    def test(self):
        print "A.test()"

class B(A):
    def test(self):
        # instead of "super(B, self).test()" we can do
        bubble()

class C(B):
    pass

c = C()
c.test() # works!

b = B()
b.test() # works!

如果有人有更好的想法,那就听听吧。

已知错误:(感谢doublep)如果C.test = B.test - > “无限”的递归。虽然对于儿童班来说实际上有一种方法似乎是不现实的,但是从父母的方法来看,这已经是=

已知错误2:(感谢doublep)装饰方法不起作用(可能无法修复,因为装饰器返回一个闭包)... 修复了{{1的装饰器问题}}:... for _ in xrange(5) - 最多可处理5个装饰器,如果需要可以增加。 我喜欢Python!

性能比frame = frame.f_back呼叫差5倍,但我们说的是200K呼叫,而不是每秒100万次呼叫,如果这不是你最严重的环路 - 没有理由担心。

答案 1 :(得分:0)

虽然此代码绝不能用于任何正常目的。为了回答这个问题,这里有一些工作;)

import inspect

def test2():
    funcname = inspect.stack()[1][3]
    frame = inspect.currentframe().f_back
    self = frame.f_locals['self']

    return contains(self.__class__, funcname)

def contains(class_, funcname):
    if funcname in class_.__dict__:
        return class_

    for class_ in class_.__bases__:
        class_ = contains(class_, funcname)
        if class_:
            return class_

答案 2 :(得分:-1)

由于Python中的函数没有绑定到类[1],因此一般答案是“不可能的”。 但是,对于遵循标准命名约定的非静态函数,您可以尝试

inspect.currentframe()。f_back.f_locals ['self']。 class

例如,

[1],你可以这样做:

class X: pass
X.foo = (lambda self: None)

编辑:

我设法提出了问题中已有的方法: - /。但是,我仍然很好奇你是如何设法做到这一点的,因为我仍然确定某些函数没有绑定到Python中的类。