Suppose you have a concrete class
class Knight(object):
    def __init__(self, name):
        self._name = name
    def __str__(self):
        return "Sir {} of Camelot".format(self.name)
Now it happens that the class hierarchy has to change. Knight should become an abstract base class, with a bunch of concrete subclasses for knights of various castles. Easy enough:
class Knight(metaclass=ABCMeta):  # Python 3 syntax
    def __str__(self):
        return "Sir {} of {}".format(self.name, self.castle)
    @abstractmethod
    def sing():
        pass
class KnightOfTheRoundTable(Knight):
    def __init__(self, name):
        self.name = name
    @property
    def castle(self):
        return "Camelot"
    @staticmethod
    def sing():
        return ["We're knights of the round table",
                "We dance whenever we're able"]
But now all code that used Knight("Galahad") to construct a Knight is broken. We can instead keep Knight as it is and introduce a BaseKnight, but then code that checks for isinstance(x, Knight) and should work on any knight may have to be changed to check for BaseKnight instead.
How does one turn a concrete class into an abstract one, sparing both the constructor and the isinstance checks?
Make the existing class a base class, but overload __new__ to return a subclass when an attempt is made to instantiate the base class:
class Knight(metaclass=ABCMeta):
    def __new__(cls, *args, **kwargs):
        if cls is Knight:
            # attempt to construct base class, defer to default subclass
            return KnightOfTheRoundTable(*args, **kwargs)
        else:
            obj = super(Knight, cls).__new__(cls)
            obj.__init__(*args, **kwargs)
            return obj
    def __str__(self):
        return "Sir {} of {}".format(self.name, self.castle)
    @abstractmethod
    def sing():
        pass
Now Knight("Galahad") continues to work but returns a KnightOfTheRoundTable. isinstance(Knight("Robin"), Knight) return True, as does an isinstance(x, Knight) check on any other subclass instance.
Your solution messing with __new__ mostly works, but it has the downside where Knight(...) does not give you a Knight, and that Knight is just an ABC.
Writing BaseKnight is a bit cleaner, but then you have the problem
code that checks for
isinstance(x, Knight)and should work on any knight may have to be changed to check for BaseKnight instead.
which can be patched by adding
    def __subclasscheck__(object):
        return issubclass(object, BaseKnight)
to Knight. You  don't want this to affect the subclasses of Knight, though, so you do this also horrible hack:
    @classmethod
    def __subclasscheck__(cls, object):
        if cls is Knight:
            return issubclass(object, BaseKnight)
        else:
            return ABCMeta.__subclasscheck__(cls, object)
from abc import ABCMeta, abstractmethod
class BaseKnight(metaclass=ABCMeta):  # Python 3 syntax
    def __str__(self):
        return "Sir {} of {}".format(self.name, self.castle)
    @abstractmethod
    def sing():
        pass
That's the base, then you have the concrete Knight that redirects isinstance and issubclass checks:
class Knight(BaseKnight):
    def __init__(self, name, castle="Camelot"):
        self._name = name
    @abstractmethod
    def sing(self):
        return ["Can't read my,",
                "Can't read my",
                "No he can't read my poker face"]
    @classmethod
    def __subclasscheck__(cls, object):
        if cls is Knight:
            return issubclass(object, BaseKnight)
        else:
            return ABCMeta.__subclasscheck__(cls, object)
Finally, some tests:
class KnightOfTheRoundTable(Knight):
    def __init__(self, name):
        self.name = name
    @property
    def castle(self):
        return "Camelot"
    def sing():
        return ["We're knights of the round table",
                "We dance whenever we're able"]
class DuckKnight(BaseKnight):
    def __init__(self, name):
        self.name = name
    def __str__(self):
        return "Knight Quacker of Quack"
    def sing():
        return ["Quack!"]
isinstance(KnightOfTheRoundTable("John"), Knight)
#>>> True
isinstance(DuckKnight("Quacker"), Knight)
#>>> True
With the edit to to delegate back to ABCMeta.__subclasscheck__(cls, object) I no longer thing either solution is particularly nice.
It's worth noting, though, that
You probably instantiate Knight way more than than you use isinstance against the concrete Knight type (prior to the ABC). It makes sense to keep crazy behaviour confined to small spaces.
Changing isinstance means you don't have to change what Knight is, which means less damage to the codebase. 
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With