面向对象-继承和多态

在这一节中,你将体会到面向对象的诸多特色.

1、单继承

class Person(Object):
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def walk(self):
        print("%s is walking..." % self.name)

    def talk(self):
        print("%s is talking..." % self.name)

# 定义子类1  py2\3都支持
class Teacher(Person):
    def __init__(self, name, age, level):
        super(Teacher, self).__init__(name, age)  # python提供了这个函数,创建一个父类的对象,用来调用父类的__init__()
        # 避免了再次定义这些属性
        self.level = level

    def walk(self):  # 继承父类的方法并 拓展 实践中,继承的这种用途意义并不很大,甚至常常是有害的。因为它使得子类与基类出现强耦合。
        super().walk()  # 避免再写一遍父类中的功能代码
        print("加速...")

    def teach(self):
        print("%s is teaching..." % self.name)

# 定义子类2
class Student(Person):
    def __init__(self, name, age, grade):
        Person.__init__(self, name, age)  # 这样写避免了自己再次定义这些属性
        self.grade = grade

    def fight(self):
        print("%s is fighting..." % self.name)

t1 = Teacher("mr z", 30, "一级")
s1 = Student("xiao ming", 15, "高中一年级")

所谓继承,就像上述代码中,定义Person 类时,class Person(Object)  表示Person 类拥有Object 类的属性和方法(一些内置方法和属性),class Teacher(Person),Teacher 类拥有Person 类的属性和方法...

(walk和talk). Person 是Teacher 的父类(基类、父类或超类(Base class、Super class)),Teacher 是Person 的子类..父类上还可以有父类,子类下也可以还有子类,这就是继承关系.

Python 有两个判断继承的函数:isinstance() 用于检查实例类型;issubclass() 用于检查类继承。参见下方示例:

class Person(object):
    pass

class Child(Person):                 # Child 继承 Person
    pass

May = Child()
Peter = Person()    

print(isinstance(May,Child))         # True
print(isinstance(May,Person))        # True
print(isinstance(Peter,Child))       # False
print(isinstance(Peter,Person))      # True
print(issubclass(Child,Person))      # True

2、多继承

多继承是指一个类有多个父类的情况.多继承使用的比较少,但是你需要知道,多继承时,是怎样的继承顺序:首先提出两个概念:新式类和经典类.

新式类:python3中默认所有的类都是新式类:以Object为最终的父类(我喜欢叫它 祖先类) 创建对象时需要申请名称空间 将对象属性放进去 这些事情在新式类里 都是objeck类自动执行

经典类:python2中,继承于哪个类都需要在()里说明 ,没有显式的继承object类的类,以及该类的子类,都是经典类

有的地方会这样定义新式类和经典类:

Python 与其他语言不同点在于,当我们定义一个 class 的时候,我们实际上就定义了一种数据类型。我们定义的数据类型和Python自带的数据类型,比如str、list、dict没什么两样。由任意内置类型派生出的类(只要一个内置类型位于类树的某个位置),都属于“新式类”,都会获得所有“新式类”的特性.反之,即不由任意内置类型派生出的类,则称之为“经典类”。  “新式类”和“经典类”的区分在Python 3之后就已经不存在,在Python 3.x之后的版本,因为所有的类都派生自内置类型objec.(即使没有显示的继承object类型),即所有的类都是“新式类”。

大抵上是一致的.

经典列和新式类在继承顺序(继承的查找)方式山有区别:

新式类的继承顺序是按照C3算法来的

经典类则是按照“从左至右,深度优先”的方式去查找属性。当有菱形继承时,祖先类最后查找.

了解 C3算法

merge操作是C3算法的核心。

遍历执行merge操作的序列,如果一个序列的第一个元素,是其他序列中的第一个元素,或不在其他序列出现,则从所有执行merge操作序列中删除这个元素,合并到当前的mro中。

举例:

# 简易的定义几个类
class A(object): pass

class B(object): pass

class C(object): pass

class E(A, B): pass

class F(B, C): pass

class G(E, F): pass

‘‘‘
O表示object类
A、B、C都继承至一个基类,所以mro序列依次为[A,O]、[B,O]、[C,O]
mro(E) = [E] + merge(mro(A), mro(B), [A,B])
       = [E] + merge([A,O], [B,O], [A,B])
执行merge操作的序列为[A,O]、[B,O]、[A,B]
A是序列[A,O]中的第一个元素,在序列[B,O]中不出现,在序列[A,B]中也是第一个元素,所以从执行merge操作的序列([A,O]、[B,O]、[A,B])中删除A,合并到当前mro,[E]中。
mro(E) = [E,A] + merge([O], [B,O], [B])
再执行merge操作,O是序列[O]中的第一个元素,但O在序列[B,O]中出现并且不是其中第一个元素。继续查看[B,O]的第一个元素B,B满足条件,所以从执行merge操作的序列中删除B,合并到[E, A]中。
mro(E) = [E,A,B] + merge([O], [O])
       = [E,A,B,O]

‘‘‘

C3算法

查看和判断继承有如下方法:

Python 有两个判断继承的函数:isinstance() 用于检查实例类型;issubclass() 用于检查类继承。参见下方示例:

class Person(object):
    pass

class Child(Person):                 # Child 继承 Person
    pass

May = Child()
Peter = Person()    

print(isinstance(May,Child))         # True
print(isinstance(May,Person))        # True
print(isinstance(Peter,Child))       # False
print(isinstance(Peter,Person))      # True
print(issubclass(Child,Person))      # True

isinstance和issubclass

类名.__bases__方法 返回该类继承于哪些类(多继承时的从左到右的类都将被返回)

类名.__base__方法 只返回从左到右继承的第一个类.

类名.__mro__或  类名.mro()  可以返回该类的查找顺序列表  在最上面的实例中 : print(Teacher.mro()) 打印[<class ‘__main__.Teacher‘>, <class ‘__main__.Person‘>, <class ‘object‘>]

在python3中,使用类和对象来编程,要求你能把握好类和对象的定义,比如一个学生管理系统中,有老师,学生,,这两个类应该有一个父类 Person,而不能将Teacher设置成Student的父类,即便Teacher

的 name age 等属性在Student中也有. 把握好这一"先抽象,后继承"的原则,在安排各种类和父类时就不易出错.

使用python3的新式类时,Object为默认的父类,所有的类都会继承它的一些属性和方法,它们的名称是以双下划线__开头,同时又以双下划线__结尾。

这些属性和方法不再是私有属性和私有方法,它们是可以在类的外部通过实例对象去直接访问的,且它们都有着各自特殊的意义,我们可以通过这些特殊属性和特殊方法来获取一些重要的信息,

或执行一些有用的操作。

属性:

属性名称 说明
__doc__ 类的描述性信息 类似函数的‘‘‘ ‘‘‘ 注释
__module__ 当前操作对象的类的定义所在模块名
__class__ 当前操作的对象的类名
__dict__ 一个字典,保存类的所有成员(属性和方法)或实例对象的成员属性

实例应用:

class Dog(object):
    """这是一个Dog类"""
    # print(‘Hello, This is a dog.‘)
    color = ‘白色‘

    def __init__(self, name):
        self.name = name
        self.__id = 1234

    def func1(self):
        pass

    def __func1(self):
        pass

    @classmethod
    def func2(cls):
        pass

    @staticmethod
    def func3():
        pass

dog.py中定义Dog类

from dog import Dog

dog1 = Dog(‘泰迪‘)
print(dog1.__doc__)
print(dog1.__module__)
print(dog1.__class__)
print(dog1.__dict__)
print(Dog.__dict__)

test.py中应用实例对象

打印结果:

这是一个Dog类
dog
<class ‘dog.Dog‘>
{‘name‘: ‘泰迪‘, ‘_Dog__id‘: 1234}
{‘__dict__‘: <attribute ‘__dict__‘ of ‘Dog‘ objects>, ‘__module__‘: ‘dog‘, ‘func2‘: <classmethod object at 0x000001DF0C658F98>, ‘color‘: ‘白色‘, ‘func3‘: <staticmethod object at 0x000001DF0C658FD0>, ‘_Dog__func1‘: <function Dog.__func1 at 0x000001DF0C63E400>, ‘__weakref__‘: <attribute ‘__weakref__‘ of ‘Dog‘ objects>, ‘__doc__‘: ‘这是一个Dog类‘, ‘__init__‘: <function Dog.__init__ at 0x000001DF0C63E2F0>, ‘func1‘: <function Dog.func1 at 0x000001DF0C63E378>}

方法:

方法 说明
__init__ 初始化构造方法,创建类时自动执行
__del__ 析构方法,当对象在内存中被释放(回收)前,会自动执行
__str__ 如果类中定义了__str__方法,并有返回值,在打印对象时会自动输出_-str__的返回值
__xxxitem__
是指__getitem__、__setitem__、__delitem这3个方法,它们用于索引操作,比如对字典的操作,分别表示 获取、设置、删除某个条目。 数据。可以通过这些方法来定义一个类对字典进行封装,

从而可以对字典中key的操作进行控制,尤其是删除操作。

__new__ 该方法会在__init__方法之前被执行,该方法会创建被返回一个新的实例对象,然后传递给__init__。另外需要说明的是,这不是一个成员方法,而是一个静态方法。
__call__ 源码中的注释是"Call self as a function." 意思是把自己(实例对象)作为一个函数去调用,而函数的调用方式是函数名()。也就是说,当我们执行实例对象()或者 类名()()这样的操作时会触发执行该方法。

示例:

https://www.cnblogs.com/yyds/p/7591804.html

原文地址:https://www.cnblogs.com/guyanzhi/p/10120555.html

时间: 2024-07-31 21:58:54

面向对象-继承和多态的相关文章

Java面向对象㈡ -- 继承与多态

Java的继承是通过extends和implement来实现的,Java不支持多继承,但是Java支持多层继承以及多实现(接口).Java继承有一个关键字super是用来指向父类.Java继承衍生出覆盖的概念.覆盖被用来支持多态.实际开发中Java通常继承于抽象类,实现于接口.如果不希望一个类被继承,或者一个方法被覆盖,或者一个成员变量被改变,就可以用final修饰.这里只说明两个问题:1,重载和覆盖的区别重载和覆盖的区别:重载发生在同一个类之中,重载要求函数名相同,参数不同(参数个数||参数类

Python之路-面向对象&amp;继承和多态&amp;类属性和实例属性&amp;类方法和静态方法

一.面向对象 编程方式 面向过程:根据业务逻辑从上到下写垒代码 函数式:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可 面向对象:对函数进行分类和封装,让开发"更快更好更强-" 什么是面向对象 面向对象就不像面向过程那样按照功能划分模块了,它所关注的是软件系统有哪些参与者,把这些参与者称为对象,找出这些软件系统的参与者也就是对象之后,分析这些对象有哪些特征.哪些行为,以及对象之间的关系,所以说面向对象的开发核心是对象 什么是类 面向对象编程的两个重要的概念:类和对象 类是

Python学习(七)面向对象 ——继承和多态

Python 类继承和多态 在OOP(Object Oriented Programming)程序设计中,当我们定义一个class的时候,可以从某个现有的class 继承,新的class称为子类(Subclass),而被继承的class称为基类.父类或超类(Base class.Super class). 我们先来定义一个class,名为Person,表示人,定义属性变量 name 及 sex (姓名和性别):定义一个方法:当sex是male时,print he:当sex 是female时,pr

day6面向对象--继承、多态

继承     继承:就像遗传一样,继承就是拥有父类的所有方法和属性,并且能够定义自己独特的属性和方法,对上面的类进行扩展. 可以什么都不写,直接继承父类,如下: class People(object): def __init__(self,name,age): self.name = name self.age = age def eat(self): print("%s is eating......" %self.name) def sleep(self): print(&quo

python 面向对象——继承与多态

Python是面向对象的编程语言,面向对象的基本单元是类 类的声明: 1 class class_name(): 2 pass 测试如下: In [1]: class c(): ...: pass ...: In [2]: a=c() In [3]: a Out[3]: <__main__.c instance at 0x07500A30> 类的继承: 1 In [4]: class base(): 2 ...: def f(self): 3 ...: print 'base' 4 ...:

20150429 C#面向对象 继承与多态

继承一.什么继承?1.父类的相关成员,会自动派生到子类去.public protected2.子类可以扩展父类的相关成员.3.子类可以替代父类来使用,但父类不能替代子类来使用.二.继承的语法:class 子类名:父类名{ }三.继承的规则:(一)成员变量的继承1.public protected2.如果同名就隐藏.子类与父类各自用各自的成员.(二)属性的继承1.属性一般只有public2.如果同名就隐藏.子类与父类各自用各自的成员.(三)方法的继承1.public protected2.如果同名

2、C#面向对象:封装、继承、多态、String、集合、文件(上)

面向对象封装 一.面向对象概念 面向过程:面向的是完成一件事情的过程,强调的是完成这件事情的动作. 面向对象:找个对象帮你完成这件事情. 二.面向对象封装 把方法进行封装,隐藏实现细节,外部直接调用. 打包,便于管理,为了解决大型项目的维护与管理. 三.什么是类? 将相同的属性和相同方法的对象进行封装,抽象出 “类”,用来确定对象具有的属性和方法. 类.对象关系:人是类,张三是人类的对象. 类是抽象的,对象是具体的.对象可以叫做类的实例,类是不站内存的,对象才占内存. 字段是类的状态,方法是类执

JAVA基础——面向对象三大特性:封装、继承、多态

JAVA面向对象三大特性详解 一.封装 1.概念: 将类的某些信息隐藏在类内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的操作和访问. 2.好处: 只能通过规定的方法访问数据.     隐藏类的实例细节,方便修改和实现. 3.封装的实现步骤 需要注意:对封装的属性不一定要通过get/set方法,其他方法也可以对封装的属性进行操作.当然最好使用get/set方法,比较标准. A.访问修饰符 从表格可以看出从上到下封装性越来越差. B.this关键字 1.this关键字代表当前

面向对象的三大特征——封装、继承、多态

接触过面向对象的人都知道面向对象有三大特征,分别是封装.继承和多态.这三者分别指的是什么,为什么是这哥仨,使用他们有什么好处,我们来梳理一下. 封装 原则:隐藏对象的属性和实现细节,仅对外提供公共访问方式. 好处: ①将变化隔离. ②便于使用. ③提高重用性. ④提高安全性. Demo1: 比如一个学生类:他具有姓名和年龄两个属性,但是为了提高安全性和重用性,便于使用,我们将其封装起来. public class Student { private String name; private in