2

I have a class as follows:

class Lz:
    def __init__(self, b):
        self.b = b

    def __getattr__(self, item):
        return self.b.__getattribute__(item)

And I create an instance and print :

a = Lz('abc')
print(a)

Result is: abc

I have set a breakpoint at line return self.b.__getattribute__(item), item show __str__

I don't know why it calls __getattr__, and item is __str__ when I access the instance.

see sharper
  • 11,505
  • 8
  • 46
  • 65

2 Answers2

0

print calls __str__ (see this question for details), but as Lz does not have a __str__ method, a lookup for an attribute named '__str__' takes place using __getattr__.

So if you add a __str__ method, __getattr__ should not be called anymore when printing objects of the Lz class.

user7217806
  • 2,014
  • 2
  • 10
  • 12
0

print(obj) invokes str(obj) (to get a printable representation), which in turn tries to invokes obj.__str__() (and fallback to something else if this fails, but that's not the point here).

You defined Lz as an old-style class, so it's doesn't by default have a __str__ method (new-style classes inherit this from object), but you defined a __getattr__() method, so this is what gets invoked in the end (__getattr__() is the last thing the attribute lookup will invoke when everything else has failed).

NB: in case you don't already know, since everything in Python is an object - include classes, functions, methods etc - Python doesn't make difference between "data" attributes and "method" attributes - those are all attributes, period.

NB2: directly accessing __magic__ names is considered bad practice. Those names are implementation support for operators or operator-like generic functions (ie len(), type etc), and you are supposed to use the operator or generic function instead. IOW, this:

return self.b.__getattribute__(item)

should be written as

return getattr(self.b, item)

(getattr() is the generic function version of the "dot" attribute lookup operator (.))

bruno desthuilliers
  • 75,974
  • 6
  • 88
  • 118