Héritage et polymorphisme
Héritage et polymorphisme - c'est un concept très important en Python. Vous devez mieux le comprendre si vous voulez apprendre.
Héritage
L'un des principaux avantages de la programmation orientée objet est la réutilisation. L'héritage est l'un des mécanismes pour y parvenir. L'héritage permet au programmeur de créer d'abord une classe générale ou de base, puis de l'étendre ultérieurement à une classe plus spécialisée. Cela permet au programmeur d'écrire un meilleur code.
En utilisant l'héritage, vous pouvez utiliser ou hériter de tous les champs de données et méthodes disponibles dans votre classe de base. Plus tard, vous pouvez ajouter vos propres méthodes et champs de données, ainsi l'héritage fournit un moyen d'organiser le code, plutôt que de le réécrire à partir de zéro.
Dans la terminologie orientée objet, lorsque la classe X étend la classe Y, alors Y est appelé super / parent / classe de base et X est appelé sous-classe / enfant / classe dérivée. Un point à noter ici est que seuls les champs de données et les méthodes qui ne sont pas privés sont accessibles par les classes enfants. Les champs et méthodes de données privées ne sont accessibles qu'à l'intérieur de la classe.
la syntaxe pour créer une classe dérivée est -
class BaseClass:
Body of base class
class DerivedClass(BaseClass):
Body of derived class
Hériter des attributs
Maintenant, regardez l'exemple ci-dessous -
Production
Nous avons d'abord créé une classe appelée Date et passons l'objet comme argument, ici-object est une classe intégrée fournie par Python. Plus tard, nous avons créé une autre classe appelée time et appelé la classe Date comme argument. Grâce à cet appel, nous avons accès à toutes les données et attributs de la classe Date dans la classe Time. Pour cette raison, lorsque nous essayons d'obtenir la méthode get_date à partir de l'objet de classe Time tm que nous avons créé plus tôt.
Hiérarchie de recherche Object.Attribute
- L'instance
- La classe
- Toute classe dont cette classe hérite
Exemples d'héritage
Jetons un coup d'oeil de clôture à l'exemple d'héritage -
Créons quelques classes pour participer à des exemples -
- Animal - La classe simule un animal
- Chat - Sous-classe d'animaux
- Chien - Sous-classe d'animaux
En Python, constructeur de classe utilisé pour créer un objet (instance) et affecter la valeur des attributs.
Constructeur de sous-classes toujours appelé à un constructeur de classe parent pour initialiser la valeur des attributs de la classe parent, puis il commence à attribuer une valeur à ses attributs.
Production
Dans l'exemple ci-dessus, nous voyons les attributs de commande ou les méthodes que nous mettons dans la classe parente afin que toutes les sous-classes ou classes enfants héritent de cette propriété de la classe parente.
Si une sous-classe essaie d'hériter des méthodes ou des données d'une autre sous-classe, elle le fera via une erreur comme nous le voyons lorsque la classe Dog essaie d'appeler les méthodes swatstring () de cette classe cat, elle lève une erreur (comme AttributeError dans notre cas).
Polymorphisme («BEAUCOUP DE FORMES»)
Le polymorphisme est une fonctionnalité importante de la définition de classe en Python qui est utilisée lorsque vous avez couramment nommé des méthodes dans des classes ou des sous-classes. Cela permet aux fonctions d'utiliser des entités de types différents à des moments différents. Ainsi, il offre une flexibilité et un couplage lâche afin que le code puisse être étendu et facilement maintenu au fil du temps.
Cela permet aux fonctions d'utiliser des objets de l'une de ces classes polymorphes sans avoir besoin d'être conscient des distinctions entre les classes.
Le polymorphisme peut être effectué par héritage, les sous-classes utilisant des méthodes de classe de base ou les surchargeant.
Comprenons le concept de polymorphisme avec notre exemple d'héritage précédent et ajoutez une méthode commune appelée show_affection dans les deux sous-classes -
De l'exemple que nous pouvons voir, il fait référence à une conception dans laquelle un objet de type différent peut être traité de la même manière ou plus spécifiquement deux classes ou plus avec une méthode du même nom ou une interface commune car la même méthode (show_affection dans l'exemple ci-dessous) est appelé avec l'un ou l'autre type d'objets.
Production
Ainsi, tous les animaux montrent des affections (show_affection), mais ils le font différemment. Le comportement «show_affection» est donc polymorphe en ce sens qu'il a agi différemment selon l'animal. Ainsi, le concept abstrait «animal» ne signifie pas réellement «show_affection», mais des animaux spécifiques (comme les chiens et les chats) ont une implémentation concrète de l'action «show_affection».
Python lui-même a des classes polymorphes. Par exemple, la fonction len () peut être utilisée avec plusieurs objets et tous renvoient la sortie correcte en fonction du paramètre d'entrée.
Primordial
En Python, lorsqu'une sous-classe contient une méthode qui remplace une méthode de la superclasse, vous pouvez également appeler la méthode de la superclasse en appelant
Super (sous-classe, self) .method au lieu de self.method.
Exemple
class Thought(object):
def __init__(self):
pass
def message(self):
print("Thought, always come and go")
class Advice(Thought):
def __init__(self):
super(Advice, self).__init__()
def message(self):
print('Warning: Risk is always involved when you are dealing with market!')
Hériter du constructeur
Si nous voyons dans notre exemple d'héritage précédent, __init__ était situé dans la classe parente dans le haut parce que la classe enfant dog ou cat n'avait pas la méthode __init__ dedans. Python a utilisé la recherche d'attributs d'héritage pour trouver __init__ dans la classe animale. Lorsque nous avons créé la classe enfant, elle cherchera d'abord la méthode __init__ dans la classe dog, puis elle ne l'a pas trouvée, puis elle a regardé dans la classe parent Animal et l'a trouvée là et l'a appelée là. Ainsi, à mesure que notre conception de classe devenait complexe, nous souhaitons peut-être initialiser une instance en la traitant d'abord via le constructeur de classe parent, puis via le constructeur de classe enfant.
Production
Dans l'exemple ci-dessus, tous les animaux ont un nom et tous les chiens une race particulière. Nous avons appelé le constructeur de classe parent avec super. Donc, le chien a son propre __init__ mais la première chose qui arrive est que nous l'appelons super. Super est une fonction intégrée et est conçu pour relier une classe à sa super classe ou à sa classe parente.
Dans ce cas, nous disons que récupérez la super classe de dog et passez l'instance de chien à la méthode que nous disons ici le constructeur __init__. Donc, en d'autres termes, nous appelons la classe parent Animal __init__ avec l'objet chien. Vous pouvez vous demander pourquoi nous ne disons pas simplement Animal __init__ avec l'instance de chien, nous pourrions le faire, mais si le nom de la classe animale venait à changer, dans le futur. Et si nous voulions réorganiser la hiérarchie des classes, de sorte que le chien hérite d'une autre classe. Utiliser super dans ce cas nous permet de garder les choses modulaires et faciles à changer et à entretenir.
Ainsi, dans cet exemple, nous pouvons combiner la fonctionnalité générale __init__ avec des fonctionnalités plus spécifiques. Cela nous donne l'occasion de séparer les fonctionnalités communes des fonctionnalités spécifiques qui peuvent éliminer la duplication de code et relier les classes les unes aux autres d'une manière qui reflète la conception globale du système.
Conclusion
__init__ est comme toute autre méthode; il peut être hérité
Si une classe n'a pas de constructeur __init__, Python vérifiera sa classe parente pour voir s'il peut en trouver un.
Dès qu'il en trouve un, Python l'appelle et cesse de chercher
Nous pouvons utiliser la fonction super () pour appeler des méthodes dans la classe parent.
Nous pouvons vouloir initialiser dans le parent ainsi que dans notre propre classe.
Héritage multiple et arborescence de recherche
Comme son nom l'indique, l'héritage multiple est Python lorsqu'une classe hérite de plusieurs classes.
Par exemple, un enfant hérite des traits de personnalité des deux parents (mère et père).
Syntaxe d'héritage multiple Python
Pour qu'une classe hérite de plusieurs classes parents, nous écrivons les noms de ces classes entre parenthèses dans la classe dérivée lors de sa définition. Nous séparons ces noms par une virgule.
Voici un exemple de cela -
>>> class Mother:
pass
>>> class Father:
pass
>>> class Child(Mother, Father):
pass
>>> issubclass(Child, Mother) and issubclass(Child, Father)
True
L'héritage multiple fait référence à la capacité d'hériter de deux classes ou plus. La complexité survient lorsque l'enfant hérite du parent et les parents héritent de la classe des grands-parents. Python grimpe dans une arborescence héréditaire à la recherche d'attributs dont la lecture est demandée à partir d'un objet. Il vérifiera le dans l'instance, dans la classe puis dans la classe parente et enfin à partir de la classe des grands-parents. Maintenant, la question se pose dans quel ordre les classes seront recherchées - souffle d'abord ou profondeur d'abord. Par défaut, Python utilise la profondeur d'abord.
C'est pourquoi dans le diagramme ci-dessous, Python recherche la méthode dothis () en premier dans la classe A. Ainsi, l'ordre de résolution de la méthode dans l'exemple ci-dessous sera
Mro- D→B→A→C
Regardez le diagramme d'héritage multiple ci-dessous -
Passons en revue un exemple pour comprendre la fonctionnalité «mro» d'un Python.
Production
Exemple 3
Prenons un autre exemple d'héritage multiple «en forme de diamant».
Le diagramme ci-dessus sera considéré comme ambigu. De notre exemple précédent comprenant «l'ordre de résolution des méthodes» .ie mro sera D → B → A → C → A mais ce n'est pas le cas. En obtenant le deuxième A du C, Python ignorera le A. précédent donc le mro sera dans ce cas D → B → C → A.
Créons un exemple basé sur le diagramme ci-dessus -
Production
Une règle simple pour comprendre la sortie ci-dessus est la suivante: si la même classe apparaît dans l'ordre de résolution de la méthode, les apparitions antérieures de cette classe seront supprimées de l'ordre de résolution de la méthode.
En conclusion -
Toute classe peut hériter de plusieurs classes
Python utilise normalement un ordre «profondeur d'abord» lors de la recherche de classes héritées.
Mais lorsque deux classes héritent de la même classe, Python élimine les premières apparitions de cette classe du mro.
Décorateurs, méthodes statiques et de classe
Les fonctions (ou méthodes) sont créées par l'instruction def.
Bien que les méthodes fonctionnent exactement de la même manière qu'une fonction, sauf un point où le premier argument de la méthode est un objet d'instance.
Nous pouvons classer les méthodes en fonction de leur comportement, comme
Simple method- défini en dehors d'une classe. Cette fonction peut accéder aux attributs de classe en alimentant l'argument d'instance:
def outside_func(():
Instance method -
def func(self,)
Class method - si nous devons utiliser des attributs de classe
@classmethod
def cfunc(cls,)
Static method - ne pas avoir d'informations sur la classe
@staticmethod
def sfoo()
Jusqu'à présent, nous avons vu la méthode d'instance, il est maintenant temps d'avoir un aperçu des deux autres méthodes,
Méthode de classe
Le décorateur @classmethod est un décorateur de fonction intégré qui obtient la classe sur laquelle il a été appelé ou la classe de l'instance sur laquelle il a été appelé comme premier argument. Le résultat de cette évaluation occulte la définition de votre fonction.
syntaxe
class C(object):
@classmethod
def fun(cls, arg1, arg2, ...):
....
fun: function that needs to be converted into a class method
returns: a class method for function
Ils ont accès à cet argument cls, il ne peut pas modifier l'état de l'instance d'objet. Cela nécessiterait un accès à soi.
Il est lié à la classe et non à l'objet de la classe.
Les méthodes de classe peuvent toujours modifier l'état de classe qui s'applique à toutes les instances de la classe.
Méthode statique
Une méthode statique ne prend ni un paramètre self ni un paramètre cls (class), mais elle est libre d'accepter un nombre arbitraire d'autres paramètres.
syntax
class C(object):
@staticmethod
def fun(arg1, arg2, ...):
...
returns: a static method for function funself.
- Une méthode statique ne peut ni modifier l'état de l'objet ni l'état de la classe.
- Ils sont limités dans les données auxquelles ils peuvent accéder.
Quand utiliser quoi
Nous utilisons généralement la méthode de classe pour créer des méthodes d'usine. Les méthodes d'usine renvoient un objet de classe (similaire à un constructeur) pour différents cas d'utilisation.
Nous utilisons généralement des méthodes statiques pour créer des fonctions utilitaires.