简体   繁体   English

当__str__被覆盖时,获取python中对象实例的名称?

[英]Get the name of the instance of an object in python, when __str__ overridden?

I'm creating a simple container system, in which my objects (all children of a class called GeneralWidget ) are grouped in some containers, which are in another set of containers, and so on until all is in one Global container.我正在创建一个简单的容器系统,其中我的对象(一个名为GeneralWidget的类的所有子GeneralWidget )被分组在一些容器中,这些容器在另一组容器中,依此类推,直到所有对象都在一个全局容器中。 I have a custom class, called GeneralContainer , in which I had to override the __str__ method to provide a describing name for my container, So I know what kind of objects or containers are stored inside of him.我有一个名为GeneralContainer的自定义类,在其中我必须覆盖__str__方法来为我的容器提供一个描述名称,所以我知道他里面存储了什么样的对象或容器。

I am currently writing another class called ObjectTracker in which all positions of my Objects are stored, so when a new object is created, It gives a list with its' name in it in the __init__ method to it's "parent" in my hieracy, which adds itself to the list and passes it on.我目前正在编写另一个名为ObjectTracker类,其中存储了我的对象的所有位置,因此当创建一个新对象时,它会在__init__方法中给出一个包含其名称的列表,它是我层次结构中的“父”将自己添加到列表中并将其传递。 At some point this list with all objects that are above the new created instance of GeneralWidget will reach the global GeneralWidget (containing all containers and widgets) , which can access the ObjectTracker -object in my main() .在某些时候,这个包含新创建的GeneralWidget实例之上的所有对象的列表将到达全局GeneralWidget (包含所有容器和小部件),它可以访问我的main()ObjectTracker

This is the bachground of my problem.这是我的问题的背景。 My ObjectTracker has got a dictionary, in which every "First Level container" is a key, and all objects inside such a container are stored in dictionarys as well.我的ObjectTracker有一个字典,其中每个“一级容器”都是一个键,并且这样一个容器内的所有对象也存储在字典中。 So I have many encapsulated dictionarys.所以我有很多封装的字典。

As I don't know how many levels of containers there will be, I need a dynamic syntax that is independent of the number of dictionarys I need to pass unil I get to the place in the BIG dictionary that I want.因为我不知道会有多少级别的容器,所以我需要一个动态语法,该语法与我需要传递的字典数量无关,直到我到达我想要的 BIG 字典中的位置。 A (static) call inside my ObjectRepository class would need to look something like this:我的ObjectRepository类中的(静态)调用需要如下所示:

self._OBJECTREPOSITORY[firstlevelcontainer12][secondlevel8][lastlevel4] = myNewObject

with firstlevelcontainer12 containing secondlevel8 which contains lastlevel4 in which the new object should be placed firstlevelcontainer12包含secondlevel8 ,其中包含lastlevel4 ,新对象应放置在其中

But I know neither how the containers will be called, nor how many there will be, so I decided to use exec() and compose a string with all names in it.但是我既不知道将如何调用容器,也不知道将有多少个容器,因此我决定使用exec()并组合一个包含所有名称的字符串。 I will post my actual code here, the definition of ObjectTracker :我将在这里发布我的实际代码, ObjectTracker的定义:

class ObjectTracker:
    def __init__(self):
        self._NAMEREPOSITORY = {}

    def addItem(self, pathAsList):
        usableList = list(reversed(pathAsList))
        string = "self._NAMEREPOSITORY"
        for thing in usableList:
            if usableList[-1] != [thing]:
                string += "[" + str(thing) + "]"
            else:
                string += "] = " + str(thing)
        print(string)
        exec(string)                

The problem is that I have overridden the __str__ method of the class GeneralContainer and GeneralWidget To gie back a describing name.问题是我已经覆盖了GeneralContainerGeneralWidget类的__str__方法来返回一个描述名称。 This came in VERY handy at many occasions but now it has become a big problem.这在很多情况下都非常方便,但现在它已成为一个大问题。 The code above only works if the custom name is the same as the name of the instance of the object (of course, I get why!)上面的代码仅在自定义名称与对象实例的名称相同时才有效(当然,我明白为什么!)

The question is : Does a built-in function exist to do the following:问题是:是否存在内置函数来执行以下操作:

>>> alis = ExampoleClass()
>>> DOESTHISEXIST(alis)
'alis'

If no, how can I write a custom one without destroying my well working naming system?如果不是,我怎样才能在不破坏我正常工作的命名系统的情况下编写自定义的?

Note: Since I'm not exactly sure what you want, I'll attempt provide a general solution.注意:由于我不确定你想要什么,我会尝试提供一个通用的解决方案。

First off, avoid eval/exec like the black plague.首先,避免像黑瘟疫一样使用eval/exec There are serious problems one encounters when using them , and there's almost always a better way. 使用它们时会遇到严重的问题,而且几乎总有更好的方法。 This is the way I propose below:这是我在下面建议的方式:

You seems to want a way to find a certain point a nested dictionary given a list of specific keys.您似乎想要一种在给定特定键列表的嵌套字典中找到某个点的方法。 This can be done quite easily using a for-loop and recursively traversing said dictionary.这可以很容易地使用 for 循环并递归遍历所述字典来完成。 For example:例如:

>>> def get_value(dictionary, keys):
        value = dictionary
        for key in keys:
            value = value[key]
        return value

>>> d = {'a': 1, 'b': {'c': 2, 'd': 3, 'e': {'f': 4, }, 'g': 5}}
>>> get_value(d, ('b', 'e', 'f'))
4
>>> 

If you need to assign to a specific part of a certain nested dictionary, this can also be done using the above code:如果您需要分配给某个嵌套字典的特定部分,也可以使用上面的代码来完成:

>>> dd = get_value(d, ('b', 'e')) # grab a dictionary object
>>> dd
{'f': 4}
>>> dd['h'] = 6
>>> # the d dictionary is changed.
>>> d
{'a': 1, 'b': {'c': 2, 'd': 3, 'e': {'f': 4, 'h': 6}, 'g': 5}}
>>> 

Below is a formalized version of the function above, with error testing and documentation (in a custom style):下面是上述函数的正式版本,带有错误测试和文档(以自定义样式):

NO_VALUE = object()


def traverse_mapping(mapping, keys, default=NO_VALUE):
    """
    Description
    -----------
    Given a - often nested - mapping structure and a list of keys, use the
    keys to recursively traverse the given dictionary and retrieve a certian
    keys value.

    If the function reaches a point where the mapping can no longer be
    traversed (i.e. the current value retrieved from the current mapping
    structure is its self not a mapping type) or a given key is found to
    be non-existent, a default value can be provided to return. If no
    default value is given, exceptions will be allowed to raise as normal
    (a TypeError or KeyError respectively.)

    Examples (In the form of a Python IDLE session)
    -----------------------------------------------
    >>> d = {'a': 1, 'b': {'c': 2, 'd': 3, 'e': {'f': 4, }, 'g': 5}}
    >>> traverse_mapping(d, ('b', 'e', 'f'))
    4
    >>> inner_d = traverse_mapping(d, ('b', 'e'))
    >>> inner_d
    {'f': 4}
    >>> inner_d['h'] = 6
    >>> d
    {'a': 1, 'b': {'c': 2, 'd': 3, 'e': {'f': 4, 'h': 6}, 'g': 5}}
    >>> traverse_mapping(d, ('b', 'e', 'x'))
    Traceback (most recent call last):
      File "<pyshell#14>", line 1, in <module>
        traverse_mapping(d, ('b', 'e', 'x'))
      File "C:\Users\Christian\Desktop\langtons_ant.py", line 33, in traverse_mapping
        value = value[key]
    KeyError: 'x'
    >>> traverse_mapping(d, ('b', 'e', 'x'), default=0)
    0
    >>>

    Parameters
    ----------
    - mapping : mapping
        Any map-like structure which supports key-value lookup.

    - keys : iterable
        An iterable of keys to be using in traversing the given mapping.
    """
    value = mapping
    for key in keys:
        try:
            value = value[key]
        except (TypeError, KeyError):
            if default is not NO_VALUE:
                return default
            raise
    return value

I think you might be looking for vars() .我想你可能正在寻找vars()

a = 5
# prints the value of a
print(vars()['a'])
# prints all the currently defined variables
print(vars())
# this will throw an error since b is not defined
print(vars()['b'])

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

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