代码之家  ›  专栏  ›  技术社区  ›  Ram Rachum

有处理Python对象地址的Python模块吗?

  •  -4
  • Ram Rachum  · 技术社区  · 14 年前

    'life.State.step' . 大多数情况下,最后一个点之前的所有对象都是包/模块,但在某些情况下,它们可以是类或其他对象。)

    Python project 我经常需要玩弄对象地址。我必须完成的一些任务:

    1. 给定一个地址,获取对象,同时导入所需的模块。
    2. 'life.life.State.step' '生活状态步骤' 指向同一个对象,我想改用它,因为它比较短。)
    3. 通过“根”指定模块来缩短对象的地址。(例如, 'garlicsim_lib.simpacks.prisoner.prisoner.State.step' prisoner 'prisoner.prisoner.State.step' 作为地址。)

    注意:请不要给我看这些东西的快速实现。它比看起来更复杂,有很多缺陷,任何快速的脏代码在许多重要情况下都可能失败。这类任务需要经过战斗测试的代码。

    更新: 当我说“object”时,我主要指的是类、模块、函数、方法等等。抱歉之前没说清楚。

    4 回复  |  直到 11 年前
        1
  •  5
  •   Thomas Wouters    14 年前

    简而言之:不,你想要的是不可能的。

    长话短说的答案是,你所认为的一个对象的“地址”决不是。 life.State.step 在那个特定的时间 . 稍后相同的“地址”可能会给您一个不同的对象,也可能是一个错误。更重要的是,你的这个“地址” 取决于上下文 . 在 生活状态步骤 ,结束对象不仅仅取决于 life.State 是的,但是 什么东西的名字 life 在该命名空间中引用

    对您要求的具体答复:

    1. 不可能 仅仅 ,具有不希望移动的特定对象,例如类和模块。即便如此,那些物体 经常走动 四处移动,这样你尝试的东西就有可能被打破。

    2. __import__() getattr()

    3. 所有可能的名字 ,表示所有模块和所有本地名称,以及 它们的所有属性 __getattr__ __getattribute__ 方法,或具有不只是返回值的属性。

    4. 和3是一样的。

        2
  •  4
  •   Ram Rachum    14 年前

    address_tools 完全符合我要求的模块。

    Here is the code Here are the tests .

    这是我们的一部分 GarlicSim installing garlicsim 做什么 from garlicsim.general_misc import address_tools . 它的主要功能是 describe resolve ,平行于 repr eval . docstring解释了这些函数的工作原理。

    网上甚至有一个python3版本 Python 3 fork of GarlicSim . 如果您想使用,请安装它 关于python3的代码。

        3
  •  1
  •   Eric O. Lebigot    14 年前

    对于第3点和第4点,我猜您正在寻找类似

    from life import life  # life represents life.life
    from garlicsim_lib.simpacks import prisoner
    

    但是,不建议这样做,因为这样会使您或阅读您的代码的人很难快速了解您的代码 prisoner 表示(它来自哪个模块?您必须查看代码的开头才能获得此信息)。

    对于第1点,您可以执行以下操作:

    from uncertainties import UFloat
    
    print UFloat.__module__  # prints 'uncertainties'
    
    import sys
    module_of_UFloat = sys.modules[UFloat.__module__]
    

    对于第2点,给定字符串'garlicsim'_lib.simpacks.cap俘,您可以通过以下方式获取它引用的对象:

    obj = eval('garlicsim_lib.simpacks.prisoner')
    

    这假设您已经导入了带有

    import garlicsim_lib  # or garlicsim_lib.simpacks
    

    import imp
    
    module_name = address_string.split('.', 1)[0]
    mod_info = imp.find_module(module_name)
    try:
        imp.load_module(module_name, *mod_info)
    finally:
        # Proper closing of the module file:
        if mod_info[0] is not None:
            mod_info[0].close()
    

    这只适用于最简单的情况( garlicsim_lib.simpacks 需要在 garlicsim_lib ,例如)。

    然而,用这种方式编码是非常不寻常的。

        4
  •  0
  •   Andrew Dalke    14 年前

    Twisted的#2与Twisted/python相同/反射.py. 你需要一些类似的东西来创建一个基于字符串的配置系统,比如Django的网址.py配置。

    您正在寻找的其他东西对Python环境有足够的限制,因此没有通用解决方案。

    >>> import pickle
    >>> def identify(f):
    ...   name = f.__name__
    ...   module_name = pickle.whichmodule(f, name)
    ...   return module_name + "." + name
    ... 
    >>> identify(math.cos)
    'math.cos'
    >>> from xml.sax.saxutils import handler
    >>> identify(handler)
    '__main__.xml.sax.handler'
    >>> 
    

    你的#3定义不清。如果我这样做了

    __builtin__.step = path.to.your.stap
    

    那么搜索代码是否应将其作为“步骤”找到?

    我能想到的最简单的实现就是简单地搜索所有模块并查找顶级元素,这些元素正是您想要的

    >>> import sys
    >>> def _find_paths(x):
    ...   for module_name, module in sys.modules.items():
    ...     if module is None:
    ...         continue
    ...     for (member_name, obj) in module.__dict__.items():
    ...       if obj is x:
    ...         yield module_name + "." + member_name
    ... 
    >>> def find_shortest_name_to_object(x):
    ...   return min( (len(name), name) for name in _find_paths(x) )[1]
    ... 
    >>> find_shortest_name_to_object(handler)
    '__builtin__._'
    >>> 5
    5
    >>> find_shortest_name_to_object(handler)
    'xml.sax.handler'
    >>> 
    

    在这里,您可以看到“handler”实际上位于上一个表达式return的uu中,使其成为最短的名称。

    如果你想要别的东西,比如递归地搜索所有模块的所有成员,那么只需要编写代码。但正如“uux”示例所示,会有惊喜。另外,这并不稳定,因为导入另一个模块可能会使另一个对象路径可用且更短。

    不管怎样,你写了

    求你了,别给我看太快 这些东西的实现。它是 比看起来更复杂的是 对于许多重要的案件。这种 许多任务需要经过战斗测试的代码。

    因此你的问题的答案是“不,没有这样的模块。”

    让您的问题更加困惑的是,Python的C实现已经定义了一个“对象地址”。这个 docs for id() 说:

    CPython实现细节:这是对象的地址。

    您要查找的是对象的名称或路径。不是“Python对象地址”

    推荐文章