XD blog

blog page

iterator, python, return, yield


2016-02-28 Python 2.7 and Python 3, difference with multiple inheritance

There is a little difference in the way Python 3 and Python 2.7 handles multiple inheritance. Class Cl inherits from ClA and ClB. ClA defines method1, ClB defines suffix. The question is: Does method method1 from class ClA know about method suffix from class ClB? In Python 3, it does:

class C0:
    def suffix(self):
        raise NotImplementedError()

class ClA(C0):
    def method1(self):
        return "A.method1" + self.suffix()
        
class ClB(C0):
    def suffix(self):
        return "--B"
        
class Cl(ClA, ClB):
    pass

cl = Cl()
print(cl.method1())

[1]

A.method1--B

In Python 2.7?

[2]

Traceback (most recent call last):
  File "test27.py", line 17, in <module>
    print(cl.method1())
  File "test27.py", line 7, in method1
    return "A.method1" + self.suffix()
  File "test27.py", line 3, in suffix
    raise NotImplementedError()
NotImplementedError

It does not. To fix it, the method has to be rewritten.

class Cl(ClA, ClB):
    def suffix(self):
        return ClB.suffix(self)

2016/03/08 commentaire envoyé par Romain (see also New Class Vs Classic Class)

La réelle différence ne se situe pas entre la 2.x et la 3.x mais entre la 2.1 et la 2.2. En 2.2, les "new style classes" ont été introduites, et le "nouveau comportement" de l'héritage, et en particulier de l'héritage multiple. Pour être backward compatible, les versions 2.2 à 2.7 ont forcé l'utilisateur à utiliser de manière explicite object comme classe de base pour obtenir le nouveau comportement. Si une classe n'a pas dans ses ancêtres object, alors c'est une "vieille" classe, supportée par python 2.1.

En python 3, la seule différence est le retrait de cette rétrocompatibilité avec la 2.1, et du coup class x ou class x(object) ont la même signification. Si on reprend ton bout de code, le simple fait de remplacer class C0: par class C0(object): (qui est la manière la plus correcte en python 2.2+ de déclarer une classe), ton bout de code s'exécute exactement de la même manière en python2 et en python3.

En résumé, la vraie différence que tu pointes est le cassage en 3.0 de la rétrocompatibilité des "old style classes" encore disponibles dans python 2, puisque object (la classe de base utilisant le mécanisme de la métaclasse type et permettant entre autres l'héritage multiple et l'utilisation des descripteurs) devient la classe de base par défaut de toute classe déclarée sans parent.


<-- -->

Xavier Dupré