Python: how to access an attribute from a __getattribute__ method
-
16-06-2021 - |
質問
I have the following class:
class StrLogger(str):
def __init__(self, *args):
self._log_ = []
str.__init__(self, *args)
def __getattribute__(self, attr):
self._log_.append((self.__name__, attr))
return str.__getattribute__(self, attr)
I can initialize a StrLogger
with slog = StrLogger('foo')
and I can access all of its inherited methods from str
and it runs with no problem. The problem is, when I try to retreive the log with either slog._log_
or slog.__dict__['_log_']
, the __getattribute__
method gets stuck in an infinite recursion. I understand why this is happening but my question is, how can I access the log?
解決
Your __getattribute__
should exclude __dict__
and maybe as well _log_
from logging. Alternatively, you could do something like
slog = StrLogger('foo')
thelog = slog._log_
do_stuff_with(slog)
print thelog
(untested!)
他のヒント
I can think of one way. Use object.__getattribute__
(or whatever your superclass is) whenever you need to bypass your customized attribute access.
class C(object):
def __init__(self):
self._log = []
def __getattribute__(self, attr):
_log = object.__getattribute__(self, '_log')
_log.append(attr)
return object.__getattribute__(self, attr)
>>> a = C()
>>> a.x = 1
>>> a.x
1
>>> a._log
['x', '_log']
The following slightly modified class works:
class StrLogger(str):
def __init__(self, *args):
self._log_ = []
str.__init__(self, *args)
def __getattribute__(self, attr):
log = str.__getattribute__(self, '_log_')
cls = str.__getattribute__(self, '__class__')
name = cls.__name__
log.append((name, attr))
return str.__getattribute__(self, attr)
s = StrLogger('abc')
print(s.title())
print(s.lower())
print(s.upper())
print(s.__dict__)
Running it results in
Abc
abc
ABC
{'_log_': [('StrLogger', 'title'), ('StrLogger', 'lower'), ('StrLogger', 'upper'), ('StrLogger', '__dict__')]}