继承与多态

继承和多态 - 这是Python中一个非常重要的概念.如果你想学习,你必须更好地理解它.

继承

面向对象编程的一个主要优点是重复使用.继承是实现同样的机制之一.继承允许程序员首先创建通用类或基类,然后将其扩展到更专业的类.它允许程序员编写更好的代码.

使用继承,您可以使用或继承基类中可用的所有数据字段和方法.稍后您可以添加自己的方法和数据字段,因此继承提供了一种组织代码的方法,而不是从头开始重写.

在类X扩展类Y时面向对象的术语,那么Y被称为超级/父/基类,X被称为子类/子/派生类.这里要注意的一点是,子类只能访问非私有的数据字段和方法.私有数据字段和方法只能在类中访问.

创建派生类的语法是 :

class BaseClass:
   Body of base class
class DerivedClass(BaseClass):
   Body of derived class

继承属性

现在看下面的例子 :

继承属性

输出

继承属性输出

我们首先创建了一个名为Date的类,并将该对象作为参数传递,here-object是Python提供的内置类.后来我们创建了另一个名为time的类,并将Date类称为参数.通过此调用,我们可以访问Date类的所有数据和属性到Time类中.因此,当我们尝试从我们之前创建的Time类对象tm获取get_date方法时.

Object.Attribute Lookup Hierarchy

  • 实例

  • 此类继承的任何类

继承示例

让我们看一下继承示例 :

继承示例

让我们创建几个类来参与示例 :

  • 动物与减号;类模拟动物

  • Cat : 动物的子类

  • 狗和负;动物的子类

在Python中,类的构造函数用于创建对象(实例),并为属性赋值.

子类的构造函数总是调用父类的构造函数来初始化父类中的属性的值,然后它开始为其属性赋值.

Python构造函数

输出

Python构造函数输出

在上面的示例中,我们看到了我们在父类中放置的命令属性或方法,以便所有子类或子类都将继承该属性父类.

如果一个子类尝试从另一个子类继承方法或数据,那么当我们看到Dog类尝试从该cat类调用swatstring()方法时,它将会出现错误,它扔了一个电子邮件rror(在我们的例子中就像AttributeError一样).

多态性("MANY SHAPES")

多态性是Python中类定义的一个重要特征,在跨类或子类使用通常命名的方法时使用.这允许函数在不同时间使用不同类型的实体.因此,它提供了灵活性和松散耦合,因此代码可以随着时间的推移而扩展和维护.

这允许函数使用任何这些多态类的对象,而无需了解区别跨类.

多态性可以通过继承来实现,子类使用基类方法或覆盖它们.

让我们理解这个概念我们以前的继承示例中的多态性,并在子类和减号中添加一个名为show_affection的常用方法;

从我们可以看到的示例中,它指的是一种设计,其中不同类型的对象可以是使用相同名称或公共接口的方法以相同的方式处理或更具体地处理两个或多个类,因为使用相同类型的对象调用相同的方法(以下示例中的show_affection).

Polymorphism

输出

Polymorphism Output

因此,所有动物都表现出情感(show_affection),但它们的表现不同.因此,"show_affection"行为是多态的,因为它根据动物的不同而不同.因此,抽象的"动物"概念实际上并不是"show_affection",而是特定的动物(如狗和猫)具有动作"show_affection"的具体实现.

Python本身有类这是多态的.例如,len()函数可以与多个对象一起使用,并且所有对象都根据输入参数返回正确的输出.

Polymorphic

覆盖

在Python中,当子类包含覆盖超类方法的方法时,您还可以调用超类方法通过调用

Super(Subclass,self).method而不是self.method.

示例

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!')

继承构造函数

如果我们从之前的继承中看到例如,__ init__位于up类中的父类中,因为子类中的狗或猫没有__init__方法. Python使用继承属性查找在动物类中查找__init__.当我们创建子类时,首先它将在dog类中查找__init__方法,然后它没有找到它然后查看父类Animal并在那里找到并在那里调用它.因此,当我们的类设计变得复杂时,我们可能希望初始化一个实例,首先通过父类构造函数然后通过子类构造函数处理它.

构造函数

输出

构造函数输出

在上面的例子中 - 所有动物都有一个名字,所有的狗都是特定品种.我们用super调用了父类构造函数.所以狗有自己的__init__但是第一件事就是我们称之为超级. Super内置于函数中,它被设计为将类与其超类或其父类相关联.

在这种情况下,我们说获取超级类的狗并传递dog实例我们在这里说的任何方法构造函数__init__.换句话说,我们用dog对象调用父类Animal __init__.你可能会问为什么我们不会只用dog实例说动物__init__,我们可以这样做但是如果动物类的名字要改变,将来某个时候.如果我们想要重新排列类层次结构,那么狗会从另一个类继承.在这种情况下使用super可以让我们保持模块化,易于更改和维护.

因此,在本例中,我们可以将一般的__init__功能与更具体的功能结合起来.这使我们有机会将常见功能与特定功能分开,这些功能可以消除代码重复,并以反映系统整体设计的方式将类相互关联.

结论

  • __ init__与任何其他方法一样;它可以被继承

  • 如果一个类没有__init__构造函数,Python会检查它的父类,看它是否可以找到它.

  • 一旦找到一个,Python就会调用它并停止查看

  • 我们可以使用超级()函数调用父类中的方法.

  • 我们可能想要在父类和我们自己的类中初始化.

多重继承和查找树

正如其名称所示,多重继承是Python,当一个类从多个继承时例如,一个孩子从父母双方(母亲和父亲)继承人格特质.

Python多重继承语法

为了使类继承自多个父类,我们在定义它时将括号内的这些类的名称写入派生类.我们用逗号分隔这些名称.

以下是 : 的示例;

>>> class Mother:
   pass

>>> class Father:
   pass

>>> class Child(Mother, Father):
   pass

>>> issubclass(Child, Mother) and issubclass(Child, Father)
True

多重继承是指从两个或两个以上继承的能力类.当孩子从父母继承而父母继承祖父母阶级时,就会出现复杂性. Python爬上继承树,查找要求从对象读取的属性.它将检查实例,在类中然后在父类中检查,最后从祖父类中检查.现在问题出现了类的搜索顺序 - 先呼吸还是深度优先.默认情况下,Python使用深度优先.

这就是为什么在下图中Python首先在A类中搜索dothis()方法.所以下面的方法解析顺序例子是

Mro-D →  B →  A →  C

请看下面的多重继承图 :

多重继承

让我们通过一个例子来理解"mro" "Python的特性.

输出

Python mro功能输出

示例3

让我们再看一个"钻石形状"多重继承的例子.

钻石形状多重继承

上图将被视为含糊不清.从我们之前的例子中了解"方法解析顺序".i.e. mro将是D →  B →  A →  C →  A但不是.在从C获得第二个A时,Python将忽略之前的A.因此mro将在这种情况下将是D →  B →  C →  A.

让我们创建一个基于示例的示例在上图 :

方法解析顺序

输出

方法解析订单输出

了解上述输出的简单规则是 - 如果同一类出现在方法解析顺序中,此类的早期外观将从方法解析顺序中删除.

结论 :

  • 任何类都可以从多个类继承

  • Python通常使用"深度优先"顺序在搜索继承类时.

  • 但是当两个类继承自同一个类时,Python会删除f第一次从mro出现该类.

装饰器,静态和类方法

函数(或方法)由def语句创建.

虽然方法的工作方式与函数完全相同,但方法第一个参数是实例对象的一点除外.

我们可以根据行为方式对方法进行分类,例如

  • 简单方法  : 去;在课堂外定义.此函数可以通过提供实例参数来访问类属性:

 
 def outside_func(():

  • 实例方法 :

 
 def func(self,)

  • 类方法 : 如果我们需要使用类属性

 
 @classmethod 
 def cfunc(cls,)

  • 静态方法 : 没有关于该类的任何信息

 
 @staticmethod 
 def sfoo()

直到现在我们已经看到了实例方法,现在是时候深入了解其他两种方法了,

类方法

@classmethod装饰器,是一个内置函数装饰器,得到了它的课程调用它或作为第一个参数调用的实例的类.该评估的结果会影响您的函数定义.

语法

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

他们可以访问这个cls参数,它不能修改对象实例状态.这需要访问self.

  • 它绑定到类而不是类的对象.

  • 类方法仍然可以修改适用于所有类实例的类状态.

静态方法

静态方法既不接受self也不接受cls(class)参数,但它可以自由地接受任意数量的其他参数.

语法

class C(object):
   @staticmethod
   def fun(arg1, arg2, ...):
   ...
returns: a static method for function funself.

  • 静态方法既不能修改对象状态也不能修改类状态.

  • 他们受限于他们可以访问的数据.

何时使用

  • 我们通常使用class方法来创建工厂方法.工厂方法为不同的用例返回类对象(类似于构造函数).

  • 我们通常使用静态方法来创建实用程序函数.