Jonathan
Jonathan

Reputation: 2845

Getting name of subclass from superclass?

I have a base class bc and a number of subclasses based on bc.

class bc(Object):
  def get_subclass_name(self):
      # Retrieve the name of the most derived subclass of this instance
      pass
  def somemethod(self):
      x = self.get_subclass_name()

class sc1(bc):
    pass

class sc2(bc)
    pass

The idea is that when somemethod() is invoked on an instance of a subclass of bc, it will be able to use the name of the most derived subclass of that instance without needing to know in advance what potential subclasses may exist.

I have put together a test case for this:

class base_class(object):
    @classmethod
    def get_subclass_name(cls):
        return cls.__name__

    def somemethod(self):
        print(base_class.get_subclass_name())

class sub_class(base_class):
    pass

sub_class().somemethod()

When this code is run it produces base_class rather than sub_class.

Upvotes: 9

Views: 16058

Answers (2)

tobias_k
tobias_k

Reputation: 82899

Just as an alternative to @poorsod's solution, which works perfectly fine for me, here's another, perhaps simpler variant without class methods, using self.__class__. Just as self always points to the current instance, self.__class__ always points to the actual class of that instance.

class bc(object):
    def get_subclass_name(self):
        return self.__class__.__name__

Example, tested in Python 2.6.6:

>>> class sc1(bc): pass
>>> class sc2(sc1): pass
>>> class sc3(sc2): pass
>>> print sc2().get_subclass_name()
sc2

If this does not work, please be more specific as to what output you expect and what output you are getting instead.

Upvotes: 16

Benjamin Hodgson
Benjamin Hodgson

Reputation: 44634

You need a class method.

class bc(Object):
    @classmethod
    def get_subclass_name(cls):
        return cls.__name__

    def somemethod(self):
        x = self.get_subclass_name()

Normal methods, when invoked, get passed the instance as the first parameter. This is why you see self everywhere in Python.

When you invoke a class method, however, the concrete class of the instance is passed to the function. We usually use the name cls, as I have done here.

The classic use case for class methods is alternative constructors. For example, the standard library's dict class provides a fromkeys class method, which constructs a new dict from the supplied keys and a single value. You could construct such a dict manually, but the Python developers made life easy for you!

Upvotes: 9

Related Questions