Python OOP:继承、单继承、多继承、__mro__、子类重写父类同名属性和方法、子类调用父类同名属性和方法、多层继承、super()、私有(实例)属性和方法、获取修改私有属性值、私有类属性
一、继承
Python⾯向对象的继承指的是多个类之间的所属关系,即⼦类默认继承⽗类的所有属性和⽅法。
继承作用:继承可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。
在Python中,所有类默认继承object类,object类是顶级类或基类;其他⼦类叫做派⽣类。
class Being: # 定义一个类Beingdef __init__(self): #初始化实例属性self.num = 1 #在类里面添加实例属性self.属性名=值def info_print(self): # 定义一个实例方法print(self.num) # 在类里面访问实例属性self.属性名class People(Being): # 定义一个类People,继承Being类passp1 = People() # 创建People类的一个对象p1
p1.info_print() # 对象调用父类实例方法
p1.num # 对象访问父类实例属性输出:1
class Being(object):def __init__(self):self.num = 1def info_print(self):print(self.num)class People(Being):passp1 = People()
p1.info_print()输出:1
二、单继承
单继承:一个子类继承一个父类
class Master:def __init__(self):self.kongfu = "古法配方"def make_cake(self):print("{}制作煎饼果子".format(self.kongfu))class prentice(Master):passdaqiu = prentice()
print(daqiu.kongfu)
daqiu.make_cake()输出:
古法配方
古法配方制作煎饼果子
二、多继承
多继承:一个子类同时继承多个⽗类
当⼀个类有多个父类的时候,默认使用第⼀个父类的同名属性和方法。
class Master:def __init__(self):self.kongfu = "古法配方"self.age = 100def make_cake(self):print("{}制作煎饼果子".format(self.kongfu))class School:def __init__(self):self.kongfu = "学校技术"self.name = "新东方"def make_cake(self):print("{}制作煎饼果子".format(self.kongfu))class prentice(Master, School):passdaqiu = prentice()
print(daqiu.kongfu) # 同名属性,访问第一个父类的同名属性
daqiu.make_cake() # 同名方法,访问第一个父类的同名方法print(daqiu.age) # 不同名属性,第一个父类正常
print(daqiu.name) # 不同名属性,非第一个父类报错
输出:
三、子类重写父类同名方法和属性
⼦类和父类具有同名属性和方法,默认使用子类的同名属性和方法。
class Master:def __init__(self):self.kongfu = "古法配方"self.age = 100def make_cake(self):print("{}制作煎饼果子".format(self.kongfu))class School:def __init__(self):self.kongfu = "学校技术"self.name = "新东方"def make_cake(self):print("{}制作煎饼果子".format(self.kongfu))class prentice(Master, School):def __init__(self):self.kongfu = "独创配方"def make_cake(self):print("{}制作煎饼果子".format(self.kongfu))daqiu = prentice()
print(daqiu.kongfu) # 同名属性,重写父类
daqiu.make_cake() # 同名方法,重写父类
#如果子类和父类有同名属性和方法,子类创建对象调用属性和方法,调用的是子类里面的同名属性和方法# print(daqiu.age) # 不同名属性,报错
print(daqiu.name) # 不同名属性,报错
输出:
四、___mro___
Python的MRO即Method Resolution Order(方法解析顺序),即在调用方法时,会对当前类以及所有的基类进行一个搜索,以确定该方法之所在,而这个搜索的顺序就是MRO。
类名.__mro__,返回一个元组。
可以清晰地看到类的层级关系。
class Master:def __init__(self):self.kongfu = "古法配方"self.age = 100def make_cake(self):print("{}制作煎饼果子".format(self.kongfu))class School(Master):def __init__(self):self.kongfu = "学校技术"self.name = "新东方"def make_cake(self):print("{}制作煎饼果子".format(self.kongfu))class prentice(School):def __init__(self):self.kongfu = "独创配方"def make_cake(self):print("{}制作煎饼果子".format(self.kongfu))print(prentice.__mro__)
print(type(prentice.__mro__))
print(list(prentice.__mro__))输出:
(<class '__main__.prentice'>, <class '__main__.School'>, <class '__main__.Master'>, <class 'object'>)
<class 'tuple'>
[<class '__main__.prentice'>, <class '__main__.School'>, <class '__main__.Master'>, <class 'object'>]
五、子类调用父类的同名属性和方法
子类里如果有与父类同名的属性方法,调用这个属性方法,调用的是子类里面的,调用不到父类里面的属性方法。
如何实现同名属性方法,既能调用子类里面的,也能调用父类里面的呢?
- 1.在子类里定义一个函数
- 2.再次初始化父类属性(参数self)
- 3.调用父类方法(参数self)
class Master:def __init__(self):self.kongfu = "古法配方"self.age = 100def make_cake(self):print("{}制作煎饼果子".format(self.kongfu))class School:def __init__(self):self.kongfu = "学校技术"self.name = "新东方"def make_cake(self):print("{}制作煎饼果子".format(self.kongfu))class prentice(Master, School):def __init__(self):self.kongfu = "独创配方"def make_cake(self):print("{}制作煎饼果子".format(self.kongfu))def make_master_cake(self): # 调用父类方法,为保证调用到的也是父类的属性,必须在调用方法前调用父类的初始化,类名.__init__(self)Master.__init__(self)Master.make_cake(self)def make_school_cake(self):School.__init__(self)School.make_cake(self)daqiu = prentice()
print(daqiu.kongfu)
daqiu.make_cake()
daqiu.make_master_cake()
daqiu.make_school_cake()print(prentice.__mro__)输出:
独创配方 # 返回的是子类属性
独创配方制作煎饼果子 # 调用的是子类方法
古法配方制作煎饼果子 # 调用到了父类Master的方法
学校技术制作煎饼果子 # 调用到了父类School的方法
(<class '__main__.prentice'>, <class '__main__.Master'>, <class '__main__.School'>, <class 'object'>)
class Master:def __init__(self):self.kongfu = "古法配方"self.age = 100def make_cake(self):print("{}制作煎饼果子".format(self.kongfu))class School:def __init__(self):self.kongfu = "学校技术"self.name = "新东方"def make_cake(self):print("{}制作煎饼果子".format(self.kongfu))class prentice(Master, School):def __init__(self):self.kongfu = "独创配方"def make_cake(self):print("{}制作煎饼果子".format(self.kongfu))def make_master_cake(self): # 调用父类方法,为保证调用到的也是父类的属性,必须在调用方法前调用父类的初始化,类名.__init__(self)Master.__init__(self)Master.make_cake(self)def make_school_cake(self):School.__init__(self)School.make_cake(self)daqiu = prentice()
daqiu.make_master_cake()
daqiu.make_school_cake()
print(daqiu.kongfu)
daqiu.make_cake()
print(prentice.__mro__)输出:
古法配方制作煎饼果子
学校技术制作煎饼果子
学校技术 # 如果先调用了父类的属性和方法,父类属性会覆盖子类属性
学校技术制作煎饼果子 # 如果先调用了父类的属性和方法,父类属性会覆盖子类属性
(<class '__main__.prentice'>, <class '__main__.Master'>, <class '__main__.School'>, <class 'object'>)
代码修正,
class Master:def __init__(self):self.kongfu = "古法配方"self.age = 100def make_cake(self):print("{}制作煎饼果子".format(self.kongfu))class School:def __init__(self):self.kongfu = "学校技术"self.name = "新东方"def make_cake(self):print("{}制作煎饼果子".format(self.kongfu))class prentice(Master, School):def __init__(self):self.kongfu = "独创配方"def make_cake(self):self.__init__() # 如果先调用了父类的属性和方法,父类属性会覆盖子类属性,故在调用子类方法前,先调用子类自己的初始化print("{}制作煎饼果子".format(self.kongfu))def make_master_cake(self): # 调用父类同名属性方法,为保证调用到的也是父类的属性,必须在调用方法前调用父类的初始化,类名.__init__(self)Master.__init__(self) # 父类类名.__init__(self),父类初始化调用一次,注意不要漏写selfMaster.make_cake(self) # 父类类名.函数(self), 父类方法调用一次,注意不要漏写selfdef make_school_cake(self):School.__init__(self)School.make_cake(self)daqiu = prentice()
daqiu.make_master_cake()
daqiu.make_school_cake()
print(daqiu.kongfu)
daqiu.make_cake()输出:
古法配方制作煎饼果子
学校技术制作煎饼果子
学校技术 # 因为先调用父类,这里子类同名属性仍然被父类属性覆盖
独创配方制作煎饼果子
六、多层继承
多层继承:大于两层的继承
class Master:def __init__(self):self.kongfu = "古法配方"self.age = 100def make_cake(self):print("{}制作煎饼果子".format(self.kongfu))class School:def __init__(self):self.kongfu = "学校技术"self.name = "新东方"def make_cake(self):print("{}制作煎饼果子".format(self.kongfu))class prentice(Master, School):def __init__(self):self.kongfu = "独创配方"def make_cake(self):self.__init__() # 如果先调用了父类的属性和方法,父类属性会覆盖子类属性,故在调用子类方法前,先调用子类自己的初始化print("{}制作煎饼果子".format(self.kongfu))def make_master_cake(self): # 调用父类同名属性方法,为保证调用到的也是父类的属性,必须在调用方法前调用父类的初始化,类名.__init__(self)Master.__init__(self) # 父类初始化调用一次,注意不要漏写selfMaster.make_cake(self) # 父类方法调用一次,注意不要漏写selfdef make_school_cake(self):School.__init__(self)School.make_cake(self)class TuShun(prentice):passxiaoqiu = TuShun() # 说明子类可以继承父类所有属性和方法
xiaoqiu.make_cake() # 调用父类prentice方法
xiaoqiu.make_master_cake() # 调用父类prentice的父类方法
xiaoqiu.make_school_cake() # 调用父类prentice的父类方法
print(xiaoqiu.make_cake) # 前一步调用父类prentice的父类school类,school类初始化后,属性是school类的属性输出:
独创配方制作煎饼果子
古法配方制作煎饼果子
学校技术制作煎饼果子
print(TuShun.__mro__)输出:
(<class '__main__.TuShun'>, <class '__main__.prentice'>, <class '__main__.Master'>, <class '__main__.School'>, <class 'object'>)
七、super()调用父类方法
方法一:在子类里定义一个函数,在里面初始化父类属性、调用父类方法
⽅法⼀特点:代码冗余;⽗类类名如果变化,这⾥代码需要频繁修改。如果有多个父类,代码量重复增加。
class Master:def __init__(self):self.kongfu = "古法配方"self.age = 100def make_cake(self):print("{}制作煎饼果子".format(self.kongfu))class School(Master):def __init__(self):self.kongfu = "学校技术"self.name = "新东方"def make_cake(self):print("{}制作煎饼果子".format(self.kongfu))class prentice(School):def __init__(self):self.kongfu = "独创配方"def make_cake(self):self.__init__() # 如果先调用了父类的属性和方法,父类属性会覆盖子类属性,故在调用子类方法前,先调用子类自己的初始化print("{}制作煎饼果子".format(self.kongfu))# def make_master_cake(self): # 调用父类同名属性方法,为保证调用到的也是父类的属性,必须在调用方法前调用父类的初始化,类名.__init__(self)# Master.__init__(self) # 父类初始化调用一次,注意不要漏写self# Master.make_cake(self) # 父类方法调用一次,注意不要漏写self## def make_school_cake(self):# School.__init__(self)# School.make_cake(self)# ⽅法⼀:代码冗余;⽗类类名如果变化,这⾥代码需要频繁修改def make_old_cake(self):Master.__init__(self)Master.make_cake(self)School.__init__(self)School.make_cake(self)daqiu = prentice()
daqiu.make_old_cake() # 从输出可以看到,两个父类的同名方法都调用到了
daqiu.make_cake()
print(prentice.__mro__)输出:
古法配方制作煎饼果子
学校技术制作煎饼果子
独创配方制作煎饼果子
(<class '__main__.prentice'>, <class '__main__.School'>, <class '__main__.Master'>, <class 'object'>)
方法二:super()方法,带参数写法, super(当前类名, self).函数()
方法二特点:super里的类名是当前类名,自己可以控制,防止改了类名而未改super里的类名。缺点是仍然需要注意上下保持一致,而且如果有多个父类,需要在多个父类里加入super代码。
class Master:def __init__(self):self.kongfu = "古法配方"self.age = 100def make_cake(self):print("{}制作煎饼果子".format(self.kongfu))class School(Master):def __init__(self):self.kongfu = "学校技术"self.name = "新东方"def make_cake(self):print("{}制作煎饼果子".format(self.kongfu))# 方法二(一):super(当前类名,self).函数()super(School, self).__init__()super(School, self).make_cake()class prentice(School):def __init__(self):self.kongfu = "独创配方"def make_cake(self):self.__init__() # 如果先调用了父类的属性和方法,父类属性会覆盖子类属性,故在调用子类方法前,先调用子类自己的初始化print("{}制作煎饼果子".format(self.kongfu))# def make_master_cake(self): # 调用父类同名属性方法,为保证调用到的也是父类的属性,必须在调用方法前调用父类的初始化,类名.__init__(self)# Master.__init__(self) # 父类初始化调用一次,注意不要漏写self# Master.make_cake(self) # 父类方法调用一次,注意不要漏写self## def make_school_cake(self):# School.__init__(self)# School.make_cake(self)# ⽅法⼀:代码冗余;⽗类类名如果变化,这⾥代码需要频繁修改# def make_old_cake(self):# Master.__init__(self)# Master.make_cake(self)# School.__init__(self)# School.make_cake(self)# 方法二(一):super(当前类名,self).函数()def make_old_cake(self): # 需要同时在当前类prentice的父类School里也加super()super(prentice, self).__init__()super(prentice, self).make_cake()daqiu = prentice()
daqiu.make_old_cake()
daqiu.make_cake()
print(prentice.__mro__)输出:
学校技术制作煎饼果子
古法配方制作煎饼果子
独创配方制作煎饼果子
(<class '__main__.prentice'>, <class '__main__.School'>, <class '__main__.Master'>, <class 'object'>)
<推荐使用以下方法>
方法三:super()方法,无参数写法, super().函数()
方法三特点:super()无参数写法,自动查找直接父类
使⽤super() 可以⾃动查找⽗类。调⽤顺序遵循 mro 类属性的顺序。⽐较适合单继承使⽤。
.
class Master:def __init__(self):self.kongfu = "古法配方"self.age = 100def make_cake(self):print("{}制作煎饼果子".format(self.kongfu))class School(Master):def __init__(self):self.kongfu = "学校技术"self.name = "新东方"def make_cake(self):print("{}制作煎饼果子".format(self.kongfu))# 方法二(一):super(当前类名,self).函数()# super(School, self).__init__()# super(School, self).make_cake()# 方法二(二):super(当前类名,self).函数()super().__init__()super().make_cake()class prentice(School):def __init__(self):self.kongfu = "独创配方"def make_cake(self):self.__init__() # 如果先调用了父类的属性和方法,父类属性会覆盖子类属性,故在调用子类方法前,先调用子类自己的初始化print("{}制作煎饼果子".format(self.kongfu))# def make_master_cake(self): # 调用父类同名属性方法,为保证调用到的也是父类的属性,必须在调用方法前调用父类的初始化,类名.__init__(self)# Master.__init__(self) # 父类初始化调用一次,注意不要漏写self# Master.make_cake(self) # 父类方法调用一次,注意不要漏写self## def make_school_cake(self):# School.__init__(self)# School.make_cake(self)# ⽅法⼀:代码冗余;⽗类类名如果变化,这⾥代码需要频繁修改# def make_old_cake(self):# Master.__init__(self)# Master.make_cake(self)# School.__init__(self)# School.make_cake(self)# 方法二(一):super(当前类名,self).函数()# def make_old_cake(self): # 需要同时在当前类prentice的父类School里也加super()# super(prentice, self).__init__()# super(prentice, self).make_cake()# 方法二(二):super(当前类名,self).函数()def make_old_cake(self):super().__init__()super().make_cake()daqiu = prentice()
daqiu.make_old_cake()
daqiu.make_cake()
print(prentice.__mro__)输出:
学校技术制作煎饼果子
古法配方制作煎饼果子
独创配方制作煎饼果子
(<class '__main__.prentice'>, <class '__main__.School'>, <class '__main__.Master'>, <class 'object'>)
八、定义私有(实例)属性和方法
默认情况下,只要继承关系建立,子类默认继承父类所有的属性和方法,这些能够继承给子类的属性方法叫共有权限。
如果有些属性和方法不想继承给子类了,私有权限,可以添加私有属性方法来实现。
注意:私有属性和私有方法只能在类里面访问和修改。,对某些属性方法起到保护作用。
.
class Master:def __init__(self):self.kongfu = "古法配方"self.age = 100def make_cake(self):print("{}制作煎饼果子".format(self.kongfu))class School:def __init__(self):self.kongfu = "学校技术"self.name = "新东方"def make_cake(self):print("{}制作煎饼果子".format(self.kongfu))class prentice(School, Master):def __init__(self):self.kongfu = "独创配方"self.__money = "一个亿" # 定义私有属性def __printinfo(self): # 定义私有⽅法print(self.kongfu)print(self.__money)def make_cake(self):self.__init__() # 如果先调用了父类的属性和方法,父类属性会覆盖子类属性,故在调用子类方法前,先调用子类自己的初始化print("{}制作煎饼果子".format(self.kongfu))class TuShun(prentice):passxiaoqiu = TuShun()
print(xiaoqiu.kongfu) # 独创配方
print(xiaoqiu.money) # AttributeError: 'TuShun' object has no attribute 'money'
print(xiaoqiu.__money) # AttributeError: 'TuShun' object has no attribute '__money'
xiaoqiu.printinfo # AttributeError: 'TuShun' object has no attribute 'printinfo'
xiaoqiu.__printinfo # AttributeError: 'TuShun' object has no attribute '__printinfo'
# ⼦类⽆法继承⽗类的私有属性和私有⽅法
九、获取和修改私有属性值
在Python中,在类里面,定义函数 get_属性名 ⽤来获取私有属性,定义 set_属性名 ⽤来修改私有属性值。
class Master:def __init__(self):self.kongfu = "古法配方"self.age = 100def make_cake(self):print("{}制作煎饼果子".format(self.kongfu))class School:def __init__(self):self.kongfu = "学校技术"self.name = "新东方"def make_cake(self):print("{}制作煎饼果子".format(self.kongfu))class prentice(School, Master):def __init__(self):self.kongfu = "独创配方"self.__money = "私有:一个亿"def get_money(self):print(self.__money) # 或者这里用 return self.__money,调用时用printdef set_money(self):self.__money = "私有更新:十个亿"def __printinfo(self):print(self.kongfu)print(self.__money)def make_cake(self):self.__init__() # 如果先调用了父类的属性和方法,父类属性会覆盖子类属性,故在调用子类方法前,先调用子类自己的初始化print("{}制作煎饼果子".format(self.kongfu))class TuShun(prentice):passxiaoqiu = TuShun()
xiaoqiu.get_money()
xiaoqiu.set_money()
xiaoqiu.get_money()print(prentice.__mro__)输出:
私有:一个亿
私有更新:十个亿
(<class '__main__.prentice'>, <class '__main__.School'>, <class '__main__.Master'>, <class 'object'>)
十、私有类属性
class Dog:__age = 3@classmethoddef get_age(cls):return cls.__agewangcai = Dog()
result = wangcai.get_age()
print(result) # 3
十一、继承知识小结
PS: source,itheima
Python OOP:继承、单继承、多继承、__mro__、子类重写父类同名属性和方法、子类调用父类同名属性和方法、多层继承、super()、私有(实例)属性和方法、获取修改私有属性值、私有类属性相关推荐
- layUI数据表格可编辑表格单元格值修改之后获取修改前的值
table.on('edit(data_table)', function(obj){ //注:edit是固定事件名,test是table原始容器的属性 lay-filter="对应的值&q ...
- JavaScript 技术篇-简单的两行js代码获取password不可见密码实例演示,js获取密码输入框里的值
如下图,chrome 控制台. 先获取到密码框的dom节点,再通过value就能获取到不可见的值. 密码框如下,其id是password. 右键检查元素可以定位到该元素的 dom 节点,里面直接会显示 ...
- 【轻松学】Python面向对象编程——类的设计、基础语法、继承、多态、类属性和类方法、单例设计
文章目录 1. 类的设计 大驼峰命名法 1.1 类名的确定 1.2 属性和方法的确定 练习 1.1 练习 1.2 2. 面相对象基础语法 2.1 定义简单的类(只包含方法) 2.1.1 定义只包含方法 ...
- 27、Python 面向对象(创建类、创建实例对象、访问属性、内置类属性、对象销毁、类的继承、方法重写、基础重载方法、运算符重载、类属性与方法、下划线双下划线)
27Python面向对象(Python2) Python从设计之初就已经是一门面向对象的语言,正因为如此,在Python中创建一个类和对象是很容易的.本章节我们将详细介绍Python的面向对象编程. ...
- Python 类属性和类方法、单例、异常
文章目录 一.类的结构 1.术语 -- 实例 2.类是一个特殊的对象 二.类属性和实例属性 1. 概念和使用 2.属性的获取机制(科普) 三.类方法和静态方法 1. 类方法 2. 静态方法 四. 方法 ...
- Python类与对象技巧(1):字符串格式化、封装属性名、可管理的属性、调用父类方法
1. 自定义字符串的格式化 _formats = {'ymd' : '{d.year}-{d.month}-{d.day}','mdy' : '{d.month}/{d.day}/{d.year}', ...
- Python 面向对象编程:类的创建与初始化、实例属性与方法、类属性与方法
1. 类的创建并实例化 类的定义:在Python中,类通过 class 关键字定义.按照 Python 的编程习惯,类名以大写字母开头,紧接着是(object),表示该类是从哪个类继承下来的.下面是一 ...
- python实例属性与类属性_Python 面向对象编程:类的创建与初始化、实例属性与方法、类属性与方法...
1. 类的创建并实例化 类的定义:在Python中,类通过class 关键字定义.按照 Python 的编程习惯,类名以大写字母开头,紧接着是(object),表示该类是从哪个类继承下来的.下面是一个 ...
- 【python】类属性以及实例属性、实例方法的介绍
1. 类的组成 class Demo():var = 'demo' # 类属性,公有__num = 100 # 类属性,私有def __init__(self,name='muzi',age=18): ...
最新文章
- Linux基础(二)--基础的命令ls和date的详细用法
- C# 判断字符串是否符合十六进制,八进制,二进制和十进制整数格式的正则表达式...
- 杭电ACM刷题(1):1002,A + B Problem II
- Jfinal 对象列表返回前台json数据
- cctype 定义的函数 (记忆)
- JavaScript 数据类型检测终极解决方案
- Hosts文件与域名解析
- linux课程--实验三 vi 基本操作
- 将数字金额转换成大写金额
- TI深度学习(TIDL)--1
- js遍历(js遍历json对象)
- 操作系统笔记 第一章
- 学计算机没有女朋友绕口令,十句以上绕口令
- 可见首发《模式识别与智能计算:MATLAB技术实现(第2版)》 百度网盘 下载 分享
- 文件管理服务器win7,Win7如何取得文件管理所有权
- 什么是等级保护?为什么要开展等级保护?
- java + Selenium实现12306自动购票
- iCheck插件的全选、反选、获取值操作
- 微软学术搜索项目10个版本的历程 - 分析流程
- HTML+CSS实现渐变色标签,鼠标经过效果
热门文章
- NMEA码详解【转】
- 工具--常见eclipse配置导入web工程(tomcat容器)步骤
- mac下java环境变量配置
- 使用mysql++写入BLOB数据
- 计算机naf类型是什么,计算机系统结构课后习题答案
- php 上传100m文件,PHP向MySQL中insert100M以上的文件
- mysql like in 数组_Web前端学习教程之常用的MySQL优化技巧
- python中用turtle绘制正方形_在Python-Turtle图形中创建正方形和旋转正方形的简单方法...
- 中关村企业 大数据_中关村大数据产业联盟秘书长赵国栋:数字经济区别于传统经济 是企业转型升级的顶层战略...
- mac 无法识别android,mac 无法识别android真机