简体   繁体   中英

converting python2 to python3 getattribute

My script runs into a recursive loop on Python3, I have tried replacing iteritems with items but it doesn't fix the issue, Python2 runs fine.. is there some change to __getattribute__ I am unaware of?

class Map(object):    
    def __init__(self, *args, **kwargs):
        for arg in args:
            if isinstance(arg, dict):
                for k, v in arg.items():
                    self.__dict__[k] = v
                    self.__dict__['_' + k] = v

        if kwargs:
            for k, v in kwargs.items():
                self.__dict__[k] = v
                self.__dict__['_' + k] = v

    def __getattribute__(self, attr):
        if hasattr(self, 'get_' + attr):
            return object.__getattribute__(self, 'get_' + attr)()
        else:
            return object.__getattribute__(self, attr)

    def get(self, key):
        try:
            return self.__dict__.get('get_' + key)()
        except (AttributeError, TypeError):
            return self.__dict__.get(key)


Map(**{'hello': 'world', 'foo': 'bar'})  # infinite recursion

When run, this produces:

Traceback (most recent call last):
  File "demo.py", line 29, in <module>
    Map(**{'hello': 'world', 'foo': 'bar'})  # recursive loop
  File "demo.py", line 13, in __init__
    self.__dict__[k] = v
  File "demo.py", line 17, in __getattribute__
    if hasattr(self, 'get_' + attr):
  File "demo.py", line 17, in __getattribute__
    if hasattr(self, 'get_' + attr):
[...]
RecursionError: maximum recursion depth exceeded

You have infinite recursion here because your __getattribute__ is calling hasattr() which the documentation states works by calling getattr() (thus calling your class's __getattribute__ ).

You must not call hasattr() in your __getattribute__ .

The documentation for __getattribute__ notes this potential for infinite recursion and provides guidance on the solution:

In order to avoid infinite recursion in this method, its implementation should always call the base class method with the same name to access any attributes it needs, for example, object. getattribute (self, name).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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