Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/309.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 访问正在创建的对象指定给的名称_Python_Python Internals - Fatal编程技术网

Python 访问正在创建的对象指定给的名称

Python 访问正在创建的对象指定给的名称,python,python-internals,Python,Python Internals,我正在写一些代码来确定对象的名称。这是为了进行一般调试工作,并进一步熟悉python内部结构 我将其结构化为类装饰器,以便在可能的情况下记录该类的所有实例的名称。代码相当长,所以我不会发布它,除非有人问。不过,一般技术如下所示 用代码装饰类“\uuuuu init\uuuu方法,以完成我想要的任务 设置caller=inspect.currentframe().f_back并打开inspect.getframeinfo(caller.filename并将其发送到ast.parse。我在这里不做任

我正在写一些代码来确定对象的名称。这是为了进行一般调试工作,并进一步熟悉python内部结构

我将其结构化为类装饰器,以便在可能的情况下记录该类的所有实例的名称。代码相当长,所以我不会发布它,除非有人问。不过,一般技术如下所示

  • 用代码装饰类“
    \uuuuu init\uuuu
    方法,以完成我想要的任务

  • 设置
    caller=inspect.currentframe().f_back
    并打开
    inspect.getframeinfo(caller.filename
    并将其发送到
    ast.parse
    。我在这里不做任何错误检查,因为(1)这只是为了调试/分析/黑客攻击(2)这个确切的过程“刚刚”完成,或者代码不会运行。这有什么问题吗

  • 查找导致当前执行的
    \uuuu init\uuu
    方法运行的
    ast.Assignment
    实例

  • 如果
    len(assignment.targets)==1
    则左侧只有一项,我可以从
    targets[0].id中获取名称。在像
    a=Foo()
    这样的简单形式中,
    assignment.value
    ast.Call
    的一个实例。如果它是一个文本(例如列表),那么
    value
    将是该列表,因为我感兴趣的对象没有被指定给名称

  • 确认
    assignment.value.func
    实际上是我感兴趣的对象的
    类型(obj)的最佳方法是什么。我很确定我保证它在“某个地方”,否则代码甚至不会运行。我只需要让它达到最高水平。显然,要做的事情是遍历它,并确保它不包含任何内部调用。那么我保证我有这个名字。(我的推理是正确的,我不确定它的假设是否正确)。但这并不理想,因为如果我对
    Foo
    感兴趣,这可能会导致我扔掉
    a=Foo(Bar())
    ,因为我不知道它是否是
    a=Bar(Foo())

    当然,我可以只检查
    assignment.value.func.id
    ,但是有人可能已经做了
    Foobar=Foo
    之类的事情,所以我不想过分依赖它

    任何帮助都将不胜感激。和往常一样,我对我可能忽略的任何其他建议或问题感兴趣


    另外,我真的很惊讶我刚刚发明了“python内部构件”标签。

    AST不能给你这个答案。尝试使用frame.f_lasti,然后查看字节码。如果下一条线不是商店快,你会接到内部电话或其他什么 除了你要找的简单任务,你还在继续

    def f():
      f = sys._getframe()
      i = f.f_lasti + 3   # capture current point of execution, advance to expected store
      print dis.disco(f.f_code, i)
    

    我不知道这有多大帮助,但您是否考虑过使用调用
    locals()
    ?它返回一个
    dict
    ,其中包含所有局部变量的名称和值

    例如:

    s = ''
    locals()
    >>> {'__builtins__': <module '__builtin__' (built-in)>, '__package__': None, 's': '', '__name__': '__main__', '__doc__': None}
    t = s  # I think this is what is of most importance to you
    locals()
    >>> {'__builtins__': <module '__builtin__' (built-in)>, '__package__': None, 's': '', 't': '', '__name__': '__main__', '__doc__': None}
    
    s=''
    本地人()
    >>>{uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
    我认为这对你来说是最重要的
    本地人()
    >>>{uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
    
    因此,您可以遍历此字典,并检查哪些变量具有(作为其值)您要查找的类型的对象

    def f():
      f = sys._getframe()
      i = f.f_lasti + 3   # capture current point of execution, advance to expected store
      print dis.disco(f.f_code, i)
    
    就像我说的,我不知道这个答案有多大帮助,但是如果你需要澄清任何事情,那么请留下评论,我会尽我所能做出最好的回应

    我在这里不做任何错误检查,因为(1)这只是为了调试/分析/黑客攻击(2)这个确切的过程“刚刚”完成,或者代码不会运行。这有什么问题吗

    是的:

  • 开播节目

  • 等待单元它导入一个特定的模块foo.py

  • 编辑foo.py

  • 现在,Python进程中加载的代码与磁盘上的代码不匹配


    分解字节码可能是一种更好的技术的另一个原因。

    下面是如何完成的。非常感谢匿名线索提供者。祝你好运,为你的alt帐户找到代表

    import inspect
    import opcode
    
    
    def get_name(f):
        """Gets the name that the return value of a function is
        assigned to. 
    
        This could be modified for classes as well. This is a
        basic version for illustration that only prints out
        the assignment instead of trying to do anything with it.
        A more flexible way would be to pass it a callback for when
        it identified an assignment.
    
        It does nothing for assignment to attributes. The solution
        for that isn't much more complicated though. If the
        instruction after the function call is a a `LOAD_GLOBAL`,
        `LOAD_FAST` or `LOAD_DEREF`, then it should be followed by
        a chain of `LOAD_ATTR`'s. The last one is the attribute
        assigned to.
        """
    
        def inner(*args, **kwargs):
            name = None
    
            frame = inspect.currentframe().f_back
            i = frame.f_lasti + 3
    
            # get the name if it exists
            code = frame.f_code
            instr = ord(code.co_code[i])
            arg = ord(code.co_code[i+1]) # no extended arg here.
            if instr == opcode.opmap['STORE_FAST']:
                name = code.co_varnames[arg]
            elif instr in (opcode.opmap['STORE_GLOBAL'],
                           opcode.opmap['STORE_NAME']):
                name = code.co_names[arg]
            elif instr == opcode.opmap['STORE_DEREF']:
                try:
                    name = code.co_cellvars[arg]
                except IndexError:
                    name = code.co_freevars[arg - len(code.co_cellvars)]
            ret = f(*args, **kwargs)
            print opcode.opname[instr]
            if name:
                print "{0} = {1}".format(name, ret)
            return ret
    
        return inner
    
    
    @get_name
    def square(x):
        return x**2
    
    def test_local():
        x = square(2)
    
    def test_deref():
        x = square(2)
        def closure():
            y = x
        return closure
    
    x = square(2)
    test_local()
    test_deref()()
    

    使用
    frame.f\u locals
    计算for
    list\ui]=foo()
    的赋值应该不会太难,包括
    i
    的值。棘手的是文字,当它作为参数传递时。这两种情况都应该是相当具有挑战性的。

    +很多——Python很酷!这不起作用,因为
    locals()
    总是引用调用它的帧,我正在查找一帧。对于
    inspect.currentframe
    ,我可以使用
    sys.\u getframe()
    来获得它。问题是
    foo=bar()。但这是获取名称的合适位置,因为我可以在
    栏上使用装饰器,而不是在每次赋值后都添加代码。@AaronMcSmooth:调用globals()而不是局部变量可以解决这个问题@InspectoG4det No,原因也一样
    globals
    只是最外面的帧的
    frame.f_locals
    ,因此在
    frame.f_locals
    中不会放置一个条目,直到内部帧(
    bar.\uu init_u()
    在本例中)返回为止。@AaronMcSmooth:非常感谢。其实我以前不知道这件事。谢谢你教我新东西(+1)。