3

I have one weird problem. I have following code:

class A:
    def f():
        return __class__()

class B(A):
    pass
a = A.f()
b = B.f()
print(a, b)

And output is something like this:

<__main__.A object at 0x01AF2630> <__main__.A object at 0x01B09B70>

So how can I get B instead of second A?

mustaccio
  • 18,234
  • 16
  • 48
  • 57
knowledge
  • 383
  • 3
  • 15

1 Answers1

7

The magic __class__ closure is set for the method context and only really meant for use by super().

For methods you'd want to use self.__class__ instead:

return self.__class__()

or better still, use type(self):

return type(self)()

If you want to be able to call the method on a class, then use the classmethod decorator to be handed a reference to the class object, rather than remain unbound:

@classmethod
def f(cls):
    return cls()

classmethods are always bound to the class they are called on, so for A.f() that'd be A, for B.f() you get handed in B.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343