简体   繁体   English

通过字符串查找解析全局命名空间中的Python对象

[英]Resolving a Python object in global namespace by string look up

Let's say you want the object at the end of strings of object names: an example string would be 'first_class.second_class.third_class.id' , and the list of strings all take the form 'X1object.X2object...XNobject.what_you_want_is_here_object' . 假设您想要对象名称字符串末尾的对象:示例字符串为'first_class.second_class.third_class.id' ,字符串列表的格式为'X1object.X2object...XNobject.what_you_want_is_here_object'

In every case, you know that there is an active instance of the X1object, whatever its specific name. 在每种情况下,您都知道X1object有一个活动实例,无论其具体名称如何。 With the example string, the code has already called an instance of first_class . 使用示例字符串,代码已经调用了first_class的实例。 You can load first_class with globals['first_class'] , and generically load X1object with globals['X1object'] . 您可以使用globals['first_class']加载first_class ,并通常使用globals['X1object']加载X1object

What you want is the object (usually a value) at then end of the string. 你想要的是字符串末尾的对象(通常是一个值)。 So with the example string, you want the value of id = first_class.second_class.third_class.id . 因此,对于示例字符串,您需要id = first_class.second_class.third_class.id的值。 Is there an easy way to convert the string so that it fetches its end object? 是否有一种简单的方法来转换字符串,以便获取其结束对象?

Below is the code I created to handle this problem, but it seems like a brute force approach that fetches each attribute in turn until it finds the last one. 下面是我为处理这个问题而创建的代码,但它似乎是一种蛮力方法,它依次获取每个属性,直到找到最后一个属性。

first_class = FirstClass()
first_class = go_do_something_wild_in_first_class(first_class)
...

attribute = 'first_class.second_class.third_class.id'
attribute_pieces = attribute.split('.')

fetch_attribute = lambda attribute, name: \
    attribute[name] if attribute == globals() else \
    getattr(attribute, name)

for name in attribute_pieces: # I changed the code from using an index to using a name
    if name == attribute_pieces[0]:
        attribute = fetch_attribute(globals(), name)
    else:
        attribute = fetch_attribute(attribute, name)

id = attribute

You can use reduce() : 你可以使用reduce()

def resolve_object(name):
    names = name.split('.')
    return reduce(getattr, names[1:], globals()[names[0]])

Here we simply look up names[0] as a global, then loop over the rest of the names to do a getattr for each one on the result so far. 在这里,我们只是将names[0]视为全局,然后循环其余的名称,为结果到目前为止为每个名称执行getattr

Demo: 演示:

>>> class Foo(object): pass
... 
>>> first_class = Foo()
>>> first_class.second_class = Foo()
>>> first_class.second_class.third_class = Foo
>>> first_class.second_class.third_class.id = 'baz'
>>> resolve_object('first_class.second_class.third_class.id')
'baz'

There is a Python library called zope.dottedname which does exactly what you want: 有一个名为zope.dottedname的Python库可以完全满足您的需求:

https://pypi.python.org/pypi/zope.dottedname https://pypi.python.org/pypi/zope.dottedname

It resolves arbitrary strings to corresponding objects in Python namespace, including attributes of objects. 它将任意字符串解析为Python命名空间中的相应对象,包括对象的属性。

You should use importlib 你应该使用importlib

attribute = 'first_class.second_class.third_class.id'
attribute_pieces = attribute.split('.')

id = getattr(importlib.import_module('.'.join(attribute_pieces[:-1]), attribute_pieces[-1])

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM