4

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?

3 Answers 3

3

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']
Sign up to request clarification or add additional context in comments.

Comments

2

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__')]}

Comments

1

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!)

1 Comment

Thank you! I see now the recursion was caused by accessing _log_ during the logging. It still puzzles me that the logging itself worked when other attributes were accessed.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.