【问题标题】:Getting the attribute name that the created object will be given获取创建的对象将被赋予的属性名称
【发布时间】:2011-02-06 05:01:37
【问题描述】:

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

是这样的。我有一些来自 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 对象漂浮在周围时,我可以知道它是哪个。

有什么办法吗?

【问题讨论】:

    标签: python debugging introspection magic-methods


    【解决方案1】:

    您可以使用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 块或其他东西中,以防您的代码被任何内置模块调用。

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

    【讨论】:

    • @cool-RR:我已经编辑了使用检查模块的答案,这样您就不必输入文件名了。
    【解决方案2】:

    这可能不是您正在寻找的答案,但也许您可以这样做:

    class A(object):
        def __init__(self):
            attrs = ('vanilla_b', 'chocolate_b')
    
            for attr in attrs:
                instance = B()
                setattr(self, attr, instance)
                instance.name = attr
    

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

    【讨论】:

    • 有点问题,我想在创建每个B时有不同的参数。如果没有足够好的魔法,我可能会采取这种方法。
    • 好的。要解决这个问题,您可以将属性实例化为 dict (key=name, value=object)。
    【解决方案3】:

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

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

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

    【讨论】:

    • 我知道这种方法,谢谢。我的整个问题是,“我该怎么做巫术?”
    【解决方案4】:

    不是很神奇,但是:

    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 中的引用之前执行。

    【讨论】:

    • 不好,B 对象不应该获得对 A 的引用。
    猜你喜欢
    • 2019-08-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-08
    • 2017-05-21
    • 2022-08-23
    • 1970-01-01
    相关资源
    最近更新 更多