代码之家  ›  专栏  ›  技术社区  ›  aaronasterling

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

  •  6
  • aaronasterling  · 技术社区  · 14 年前

    1. 装饰教室 __init__ 方法来做我想做的事情

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

    3. 找到 ast.Assignment 导致当前正在执行的 __初始化__

    4. 如果 len(assignment.targets) == 1 那么左手边只有一个项目,我可以从中找出名字 targets[0].id . 以一种简单的形式 a = Foo() ,然后 assignment.value ast.Call . 如果它是一个文本(例如列表),那么 value 因为我感兴趣的对象没有被指定一个名字。

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

    我当然可以查一下 assignment.value.func.id 但有人会这么做的 Foobar = Foo 或者我不想太依赖这个

    另外,我真的很惊讶我刚刚发明了“python internals”标签。

    4 回复  |  直到 14 年前
        1
  •  2
  •   aaronasterling    14 年前

    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)
    
        2
  •  0
  •   inspectorG4dget Dillon Benson    14 年前

    我不知道这对你有多大帮助,但你考虑过用这个电话联系我吗 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}
    

    因此,您可以遍历这个字典并检查哪些变量(作为它们的值)具有您要查找的类型的对象。

    就像我说的,我不知道这个答案有多大帮助,但如果你需要澄清什么,那就留下评论,我会尽我所能做出最好的回应。

        3
  •  0
  •   Marius Gedminas    14 年前

    对:

    1. 它导入一个特定的模块foo.py公司

    2. 编辑foo.py公司

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

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

        4
  •  0
  •   aaronasterling    14 年前

    这是怎么做到的。非常感谢匿名提供线索的人。祝你好运,在你的搜索机架代表为您的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()()
    

    搞清楚学生的作业应该不难 list_[i] = foo() 或者,包括 i frame.f_locals . 棘手的是文字,当它作为参数传递时。这两种情况都应该很有挑战性。