获取将为其提供所创建对象的属性名称

时间:2010-04-09 15:25:12

标签: python debugging introspection magic-methods

在我问这个之前,请注意:我希望将其用于调试目的。我知道这将是一个糟糕的黑魔法,但我想在调试期间使用它,这样我就可以更容易地识别我的对象。

就是这样。我有一些来自类A的对象,它创建了一些B个实例作为属性:

class A(object):
    def __init__(self)
        self.vanilla_b = B()
        self.chocolate_b = B()

class B(object):
    def __init__(self):
        # ...

我想要的是B.__init__,它会找出"vanilla_b"或者给出的任何属性名称,然后将其作为.name属性添加到此特定B 1}}。

然后在调试中,当我看到一些B对象浮动时,我可以知道它是哪一个。

有没有办法做到这一点?

4 个答案:

答案 0 :(得分:2)

您可以使用sys._getframe获取调用B()的行号,然后您可以使用inspect.getsourcelines获取实际的代码行。从那里,您可以解析代码行以获取分配B()的内容:

import sys
import inspect

class A(object):
    def __init__(self):
        self.vanilla_b = B()
        self.chocolate_b = B()

class B(object):
    def __init__(self):
        line_num = sys._getframe().f_back.f_lineno
        lines = inspect.getsourcelines( sys.modules[__name__] )[0]
        line = lines[line_num - 1]
        attr = line.split("=")[0].split(".")[1].strip()
        print "B() is being assigned to", attr

A()

如果您将上面的代码放入python脚本并运行它,那么它将打印

B() is being assigned to vanilla_b
B() is being assigned to chocolate_b

但是,这在Python命令提示符下不起作用,因为__main__是内置模块,因此inspect模块无法检索其源代码行。因此,您可能希望将其包装在try / catch块中,以防万一您的代码从任何内置模块调用。

为了记录,这可能是一个坏主意,但是你说你知道这不是一个好习惯而你只是为了调试而做,所以希望你能够使用这种技巧明智。

答案 1 :(得分:0)

这可能不是您正在寻找的答案,但也许您可以采取以下措施:

class A(object):
    def __init__(self):
        attrs = ('vanilla_b', 'chocolate_b')

        for attr in attrs:
            instance = B()
            setattr(self, attr, instance)
            instance.name = attr

尝试将该行为包装到某个超类中,您可能会很高兴。

答案 2 :(得分:0)

如果您可以控制代码,那么最好这样做,然后依靠一些黑魔法,例如做

class A(object):
    def __init__(self)
        self.vanilla_b = B(name="vanilla_b")
        self.chocolate_b = B(name="chocolate_b")

否则你可以使用检查模块通过本地人和自己在prev框架中做一些vodoo。

答案 3 :(得分:-1)

不是很神奇,但是:

class A(object):
    def __init__(self)
        self.vanilla_b = B(self)
        self.chocolate_b = B(self)

class B(object):
    def __init__(self, a):
        for i in dir(a):
            if getattr(a, i) == self:
                pass # store it somewhere now
编辑:抱歉,这不起作用。 B. init 在A中的引用设置之前执行。