1

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

就像这样。我有一些来自类的对象,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

然后在调试时,当我看到一些B物体漂浮在周围时,我可以知道它是哪一个。

有没有办法做到这一点?

4

4 回答 4

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__它是一个内置模块,因此检查模块无法检索其源代码行。因此,您可能希望将其包装在 try/catch 块中,以防万一您的代码被任何内置模块调用。

作为记录,这可能是一个坏主意,但您说您知道这不是一个好的做法,并且您只是为了调试而这样做,所以希望您能够明智地使用这种诡计。

于 2010-04-09T15:39:18.640 回答
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

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

于 2010-04-09T15:32:45.047 回答
0

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

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

否则,您可以使用检查模块在上一帧中通过本地人和自我并做一些伏都教。

于 2010-04-09T15:35:49.527 回答
-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 中的引用之前执行。

于 2010-04-09T15:40:03.820 回答