Explication détaillée de la méthode super() en Python

爱喝马黛茶的安东尼
Libérer: 2019-08-22 17:27:13
avant
2381 Les gens l'ont consulté

Explication détaillée de la méthode super() en Python

1. Appelez la méthode de la classe parent séparément

Exigence : écrivez une classe, puis écrivez une sous-classe Hériter et utilisez la sous-classe pour appeler la méthode 1 de la classe parent.

Utilisez la méthode 1 pour imprimer : Gros patron, viens emballer de la noix de bétel.

Ensuite, écrivez d'abord une classe parent du gros patron et exécutez-la :

class FatFather(object):
    def __init__(self, name):
        print('FatFather的init开始被调用')
        self.name = name
        print('FatFather的name是%s' % self.name)
        print('FatFather的init调用结束')
def main():
    ff = FatFather("胖子老板的父亲")
Copier après la connexion

Exécutez le constructeur init de la classe parent gros patron comme suit :

if __name__ == "__main__":
    main()
FatFather的init开始被调用
FatFather的name是胖子老板的父亲
FatFather的init调用结束
Copier après la connexion

D'accord, alors Écrivons une sous-classe, c'est-à-dire la classe Fat Boss, qui hérite de la classe ci-dessus.

# 胖子老板的父类
class FatFather(object):
    def __init__(self, name):
        print('FatFather的init开始被调用')
        self.name = name
        print('调用FatFather类的name是%s' % self.name)
        print('FatFather的init调用结束')
# 胖子老板类 继承 FatFather 类
class FatBoss(FatFather):
    def __init__(self, name, hobby):
        print('胖子老板的类被调用啦!')
        self.hobby = hobby
        FatFather.__init__(self, name)  # 直接调用父类的构造方法
        print("%s 的爱好是 %s" % (name, self.hobby))
def main():
    #ff = FatFather("胖子老板的父亲")
    fatboss = FatBoss("胖子老板", "打斗地主")
Copier après la connexion

Dans le code ci-dessus, j'utilise FatFather.init(self,name) pour appeler directement la méthode de la classe parent.

Les résultats d'exécution sont les suivants :

if __name__ == "__main__":
    main()
胖子老板的类被调用啦!
FatFather的init开始被调用
调用FatFather类的name是胖子老板
FatFather的init调用结束
胖子老板 的爱好是 打斗地主
Copier après la connexion
Copier après la connexion

2. Concepts de base de la méthode super()

En plus de la méthode d'utilisation directe de FatFather .init(self,name) , et peut également être appelé à l'aide de la méthode super().

Ensuite, vous devez d'abord lire la description et la syntaxe de la méthode super() pour comprendre l'utilisation de la méthode super().

2.1 Description

La fonction super() est une méthode utilisée pour appeler la classe parent (super classe).

super est utilisé pour résoudre le problème de l'héritage multiple. Appeler la méthode de classe parent directement en utilisant le nom de la classe ne pose aucun problème lors de l'utilisation de l'héritage unique, mais si vous utilisez l'héritage multiple, cela impliquera un ordre de recherche (MRO) et des appels répétés (héritage de diamant) et d'autres problèmes.

MRO est la méthode d'analyse de la table de séquence de la classe. En fait, c'est la table de séquence lors de l'héritage de la méthode de la classe parent.

Recommandations associées : "Tutoriel vidéo Python"

Syntaxe 2.2

Ce qui suit est la syntaxe du super() method:

super(type[, object-or-type])
Copier après la connexion

Parameter

type -- Classe

object-or-type -- Classe, généralement self

L'un des Python3.x et Python2 .x La différence est la suivante : Python 3 peut utiliser super().xxx directement au lieu de super(Class, self).xxx :

Exemple Python3.x :

class A:
    pass
class B(A):
    def add(self, x):
        super().add(x)
Copier après la connexion

Exemple Python2.x :

class A(object):   # Python2.x 记得继承 object
    pass
class B(A):
    def add(self, x):
        super(B, self).add(x)
Copier après la connexion

2.3 L'héritage unique utilise super()

Utilisez la méthode super() pour réécrire le constructeur d'initialisation du gros patron héritant de la classe parent tout à l'heure

# 胖子老板的父类
class FatFather(object):
    def __init__(self, name):
        print('FatFather的init开始被调用')
        self.name = name
        print('调用FatFather类的name是%s' % self.name)
        print('FatFather的init调用结束')
# 胖子老板类 继承 FatFather 类
class FatBoss(FatFather):
    def __init__(self, name, hobby):
        print('胖子老板的类被调用啦!')
        self.hobby = hobby
        #FatFather.__init__(self,name)   # 直接调用父类的构造方法
        super().__init__(name)
        print("%s 的爱好是 %s" % (name, self.hobby))
def main():
    #ff = FatFather("胖子老板的父亲")
    fatboss = FatBoss("胖子老板", "打斗地主")
Copier après la connexion

Utiliser par le haut Lorsque vous utilisez la super méthode, elle peut être utilisée directement car il s'agit d'un héritage unique.

fonctionne comme suit :

if __name__ == "__main__":
    main()
胖子老板的类被调用啦!
FatFather的init开始被调用
调用FatFather类的name是胖子老板
FatFather的init调用结束
胖子老板 的爱好是 打斗地主
Copier après la connexion
Copier après la connexion

Alors pourquoi dit-on que l'héritage unique peut être utilisé directement ? Parce que si la méthode super() a un héritage multiple, cela impliquera un problème d’ordre d’appel MRO (table de séquence lors de l’héritage de la méthode de classe parent).

Vous pouvez l'imprimer ci-dessous pour voir la séquence MRO d'héritage unique (FatBoss.mro).

# 胖子老板的父类
class FatFather(object):
    def __init__(self, name):
        print('FatFather的init开始被调用')
        self.name = name
        print('调用FatFather类的name是%s' % self.name)
        print('FatFather的init调用结束')
# 胖子老板类 继承 FatFather 类
class FatBoss(FatFather):
    def __init__(self, name, hobby):
        print('胖子老板的类被调用啦!')
        self.hobby = hobby
        #FatFather.__init__(self,name)   # 直接调用父类的构造方法
        super().__init__(name)
        print("%s 的爱好是 %s" % (name, self.hobby))
def main():
    print("打印FatBoss类的MRO")
    print(FatBoss.__mro__)
    print()
    print("=========== 下面按照 MRO 顺序执行super方法 =============")
    fatboss = FatBoss("胖子老板", "打斗地主")
Copier après la connexion

Le code ci-dessus utilise FatBoss.mro pour imprimer la séquence d'appels d'héritage de la classe FatBoss calculée par l'algorithme C3 de l'analyseur python.

Exécutez comme suit :

if __name__ == "__main__":
    main()
打印FatBoss类的MRO
(<class &#39;__main__.FatBoss&#39;>, <class &#39;__main__.FatFather&#39;>, <class &#39;object&#39;>)
=========== 下面按照 MRO 顺序执行super方法 =============
胖子老板的类被调用啦!
FatFather的init开始被调用
调用FatFather类的name是胖子老板
FatFather的init调用结束
胖子老板 的爱好是 打斗地主
Copier après la connexion

À partir des résultats ci-dessus (, ,

Alors, quels sont les problèmes en cas d'héritage multiple ?

2.4 Héritage multiple utilisant super()

Supposons que nous écrivions une autre classe pour la fille du gros patron et une classe pour la femme du gros patron. À ce moment-là, la fille doit hériter des deux en même temps. Catégorie (catégorie gros patron, catégorie grosse patronne).

Parce que le gros patron a un passe-temps, la femme du gros patron a besoin de travailler et de faire le ménage, donc sa fille doit l'aider en même temps.

A cette époque, la fille a besoin d'hériter et d'utiliser les méthodes de ces deux classes parentales, alors comment l'écrire ?

Jetons un coup d'œil au code d'implémentation :

# 胖子老板的父类
class FatFather(object):
    def __init__(self, name, *args, **kwargs):
        print()
        print("=============== 开始调用 FatFather  ========================")
        print(&#39;FatFather的init开始被调用&#39;)
        self.name = name
        print(&#39;调用FatFather类的name是%s&#39; % self.name)
        print(&#39;FatFather的init调用结束&#39;)
        print()
        print("=============== 结束调用 FatFather  ========================")
# 胖子老板类 继承 FatFather 类
class FatBoss(FatFather):
    def __init__(self, name, hobby, *args, **kwargs):
        print()
        print("=============== 开始调用 FatBoss  ========================")
        print(&#39;胖子老板的类被调用啦!&#39;)
        #super().__init__(name)
        ## 因为多继承传递的参数不一致,所以使用不定参数
        super().__init__(name, *args, **kwargs)
        print("%s 的爱好是 %s" % (name, hobby))
        print()
        print("=============== 结束调用 FatBoss  ========================")
# 胖子老板的老婆类 继承 FatFather类
class FatBossWife(FatFather):
    def __init__(self, name, housework, *args, **kwargs):
        print()
        print("=============== 开始调用 FatBossWife  ========================")
        print(&#39;胖子老板的老婆类被调用啦!要学会干家务&#39;)
        #super().__init__(name)
        ## 因为多继承传递的参数不一致,所以使用不定参数
        super().__init__(name, *args, **kwargs)
        print("%s 需要干的家务是 %s" % (name, housework))
        print()
        print("=============== 结束调用 FatBossWife  ========================")
# 胖子老板的女儿类 继承 FatBoss FatBossWife类
class FatBossGril(FatBoss, FatBossWife):
    def __init__(self, name, hobby, housework):
        print(&#39;胖子老板的女儿类被调用啦!要学会干家务,还要会帮胖子老板斗地主&#39;)
        super().__init__(name, hobby, housework)
def main():
    print("打印FatBossGril类的MRO")
    print(FatBossGril.__mro__)
    print()
    print("=========== 下面按照 MRO 顺序执行super方法 =============")
    gril = FatBossGril("胖子老板", "打斗地主", "拖地")
Copier après la connexion

Les résultats d'exécution sont les suivants :

if __name__ == "__main__":
    main()
打印FatBossGril类的MRO
(<class &#39;__main__.FatBossGril&#39;>, <class &#39;__main__.FatBoss&#39;>, <class &#39;__main__.FatBossWife&#39;>, 
<class &#39;__main__.FatFather&#39;>, <class &#39;object&#39;>)
=========== 下面按照 MRO 顺序执行super方法 =============
胖子老板的女儿类被调用啦!要学会干家务,还要会帮胖子老板斗地主
=============== 开始调用 FatBoss  ========================
胖子老板的类被调用啦!
=============== 开始调用 FatBossWife  ========================
胖子老板的老婆类被调用啦!要学会干家务
=============== 开始调用 FatFather  ========================
FatFather的init开始被调用
调用FatFather类的name是胖子老板
FatFather的init调用结束
=============== 结束调用 FatFather  ========================
胖子老板 需要干的家务是 拖地
=============== 结束调用 FatBossWife  ========================
胖子老板 的爱好是 打斗地主
=============== 结束调用 FatBoss  ========================
Copier après la connexion

À partir des résultats d'exécution ci-dessus, je donne délibérément le début et la fin de l'appel à chaque classe Tous sont imprimés et marqués, ce qui est visible.

L'appel de départ de chaque classe démarre selon la séquence MRO, puis se termine un par un.

De plus, comme différentes classes parents doivent être héritées, les paramètres ne sont pas nécessairement certains.

Par conséquent, toutes les classes parents doivent ajouter des paramètres variables *args et **kwargs, sinon une erreur sera signalée si les paramètres ne correspondent pas.

3. Notes

·Super().init n'a fondamentalement aucune différence d'utilisation par rapport à la classe name.init en héritage unique.

·Mais il existe une différence dans l'héritage multiple. La super méthode peut garantir que chaque méthode de classe parent ne sera exécutée qu'une seule fois, tandis que la méthode utilisant le nom de classe entraînera l'exécution de la méthode. être exécuté plusieurs fois. Vous pouvez essayer d'écrire un code pour voir le résultat.

·Lors de l'utilisation de l'héritage multiple, utilisez la super méthode pour transmettre les paramètres à la classe parente. Cela devrait être dû au super algorithme de Python. Tous les paramètres doivent être transmis, sinon une erreur. sera signalé.

·Lors de l'utilisation de la super méthode lors de l'utilisation de l'héritage unique, vous ne pouvez pas transmettre tous les paramètres. Vous ne pouvez transmettre que les paramètres requis par la méthode de la classe parent, sinon une erreur sera signalée.

·Lors de l'utilisation de l'héritage multiple, par rapport à l'utilisation de la méthode nom de classe.init, vous devez écrire toutes les classes parents une fois, mais en utilisant la super méthode, vous n'avez besoin d'en écrire qu'une seule. phrase pour tout exécuter La méthode de la classe parent, qui est également l'une des raisons pour lesquelles l'héritage multiple nécessite que tous les paramètres soient transmis.

4. Exercice

Quel sera le résultat du code suivant ? Dites votre réponse et expliquez.

class Parent(object):
    x = 1
class Child1(Parent):
    pass
class Child2(Parent):
    pass
print(Parent.x, Child1.x, Child2.x)
1 1 1
Child1.x = 2
print(Parent.x, Child1.x, Child2.x)
1 2 1
Copier après la connexion

Remarque : Child1 a déjà son propre x

Parent.x = 3
print(Parent.x, Child1.x, Child2.x)
3 2 3
Copier après la connexion

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Étiquettes associées:
source:jianshu.com
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal