day25 多继承、接口、抽象类、鸭子类型
今日内容:
如何查看对象的名称空间及对象名
继承的另一种使用
单继承与多继承
经典类与新式类
mro列表
菱形继承
接口
抽象类
鸭子类型
1、查看名称空间包含的变量:
使用类或对象名.__dict__查看
实际上在我们调用函数时就是在访问名称空间
比如Student.name实际上就是在调用 Student.__dict__["name"]
2、在使用类实例化对象时,代码的执行顺序为:
首先调用类产生一个空的对象
执行类的__init__方法,为对象添加自己独特的属性
#python为类内置的特殊属性
类名.__name__# 类的名字(字符串)
类名.__doc__# 类的文档字符串
类名.__base__# 类的第一个父类(在讲继承时会讲)
类名.__bases__# 类所有父类构成的元组(在讲继承时会讲)
类名.__dict__# 类的字典属性
类名.__module__# 类定义所在的模块
类名.__class__# 实例对应的类(仅新式类中)
class Human:
def __init__(self,name):
self.name = name def run(self):
print("%s is running..."%self.name) p1 = Human("lee")
p1.run() print(p1.__class__) # <class '__main__.Human'>
print(p1.__name__) # error:'Human' object has no attribute '__name__'
print(p1.__dict__) # {'name': 'lee'} --> 只展示对象自己的名称空间, print(Human.__dict__) # {'__module__': '__main__', '__init__': <function Human.__init__ at 0x000001E64CEC52F0>, 'run': <function Human.run at 0x000001E64CEC5378>, '__dict__': <attribute '__dict__' of 'Human' objects>, '__weakref__': <attribute '__weakref__' of 'Human' objects>, '__doc__': None}
print(Human.__class__) # <class 'type'>
print(Human.__name__) # 类的名字 p1 = Human("lee")
p2 = Human("lee")
p3 = Human("lee")
print(p1.run) # <bound method Human.run of <__main__.Human object at 0x000001A209BBE710>>
print(p2.run) # <bound method Human.run of <__main__.Human object at 0x000001A209BBE828>>
print(p3.run) # <bound method Human.run of <__main__.Human object at 0x000001A209BBEF60>>
print(p1) # <__main__.Human object at 0x000001C1B0B5D7B8>
print(p2) # <__main__.Human object at 0x000001C1B0B5D710>
print(p3) # <__main__.Human object at 0x000001C1B0B5D828>
1、继承的另一种使用:
在昨天的课程中讲了继承自己写的类,除了可以继承自己写的类,还可以继承系统已有的类
练习:
class MyList(list): def __init__(self,ele_name):
super().__init__(self)
self.ele_name = ele_name def append(self, object):
if object.__class__ == self.ele_name:
# print(object.__class__)
super().append(object)
else:
print("%s不是%s类型"%(object,self.ele_name.__name__)) li = MyList(int) li.append("")
li.append(123)
li.append(11) print(li) print(int(10).__class__)
2、单继承与多继承
单继承:子类只继承自一个父类,在进行属性查找时,首先查找自己的名称空间,在根据继承顺序依次进行查找
多继承:在python中,子类除了可以继承一个父类外,还可以继承多个父类,在进行属性查找时不能单独的依靠肉眼判断查找顺序,此时只能依靠mro列表判断查找顺序
查看继承:
在存在继承关系时,可以使用__base__()查看子类的第一个父类
可以使用__bases__()查看子类的全部父类,会产生一个元组
例子: class C:
pass class B(C):
pass class MyList(list,B): def __init__(self,ele_name):
super().__init__(self)
self.ele_name = ele_name def append(self, object):
if object.__class__ == self.ele_name:
# print(object.__class__)
super().append(object)
else:
print("%s不是%s类型"%(object,self.ele_name.__name__)) print(MyList.__base__) # <class 'list'>
print(MyList.__bases__) # (<class 'list'>, <class '__main__.B'>)
3、经典类与新式类
经典类与新式类的分别只有在py2中才会体现,在py3中所有的类都是新式类
经典类:在python2中,当一个类没有父类,又没有显性的显示继承自object类,那么这个类就是经典类(老式类)
新式类:在python2中,当一个类显性的显示它继承自object类,那么他就是新式类
在python3中,所有的类,如果没有显示他们有父类,那他们就会隐形的继承自object类,所以,在python3中,所有的类都是新式类
换句话说就是:所有没有直接或间接继承自object的类都是经典类,所有直接或间接继承自object的类就会新式类
4、super()方法与mro列表
在单继承中,我们会使用super()来继承父类的某个方法,但是在多继承中,存在继承顺序的问题,那么super()到底继承自谁就会有异议
下方的例子我们经过分析,判断可能会报错,因为C的父类是object类,但是运行时没有报错,这与我们的分析时不同的
这是因为在多继承中会使用到mro列表,在进行属性查找时会根据mro列表进行继承
查看mro列表使用的是:当前类名.mro()
# 举例: class B:
def test(self):
print("B test") class C:
def test(self):
print("C test")
super().test() class A(C,B):
# def test(self):
# print("A test")
pass a = A()
a.test()
print(A.mro()) # [<class '__main__.A'>, <class '__main__.C'>, <class '__main__.B'>, <class 'object'>]
5、菱形继承
类型继承就是当前类具有多个父类,而这些父类有具有相同的父类,那么这种继承关系就叫做菱形继承
菱形继承中属性的查找依赖于mro列表的顺序进行查找
# 例子:
class I:
def test(self):
print("I test") class K:
pass class E:
pass class F:
pass class G:
pass class H:
pass class D(H, I):
pass class C(F, H):
pass class B(E,F,G):
pass class A(B,C,D):
pass a = A()
a.test()
print(A.mro()) # I test
# [<class '__main__.A'>, <class '__main__.B'>, <class '__main__.E'>,
# <class '__main__.C'>, <class '__main__.F'>, <class '__main__.G'>,
# <class '__main__.D'>, <class '__main__.H'>, <class '__main__.I'>,
# <class 'object'>]
菱形继承
6、抽象与接口
接口:接口实际上就是一种规范制度,接口类中的方法不能拥有方法体,只是将方法罗列出来,作为模板供借鉴,这样可以更好的提高其扩展性
例如:我们平时使用电脑上的USB接口,如果我们要使用这个接口,就需要遵守这个接口的规范,如果不遵守,就不能使用这个接口
在python中,我们会使用接口类创建一个模板类,所有想要使用这个接口的类都要继承并重写模板类中的方法或者是按照接口方法的格式自己重新编写
# 我们也可以不使用模板类,这时候只要是按照模板类的格式自己定义方法也是可以使用接口的
# 举例:
# 接口类
class USB:
def read(self):
pass def write(self):
pass # 依据接口类的具体设备类
class Key(USB):
def read(self):
print("reading...") def write(self):
print("writing...") # 提供接口的类,只要依据接口的格式进行定义就能够被PC使用,不依据这个接口就不能被PC使用
class PC:
def connect_device(self,device):
device.read()
device.write()
7、抽象类
上例中,我们如果想要可以被PC类使用,就需要遵守接口,按照接口的方法进行类的创建
但是,有时为了避免遗忘接口有哪些方法,我们会将接口类定义为抽象类,这样,如果遵循其模板,就会报错
抽象类:具有抽象方法的类就是抽象类,只要一个方法中包含抽象方法,那么他就是抽象类
抽象类不能实例化,必须要有一个类继承抽象类,这个子类才可以进行实例化
抽象方法:没有函数体的方法,并且被@abc.abstractmethod 装饰器进行装饰的方法
下例中:
say_hi()方法没有函数体,且被@abc.abstractmethod 装饰器进行装饰,那么这个方法就是抽象方法
Test中包含有抽象方法,那么这个类就是抽象类 接口类与抽象类的区别:
接口类中的方法都不能具有函数体,抽象类中可以有方法具有函数体
接口类可以实例化对象,抽象类不能实例化对象
接口类可以不进行定义,只要按照接口类的模板进行类的定义即可
抽象类也可以不进行定义
# 举例:
import abc
class Test(metaclass=abc.ABCMeta):
@abc.abstractmethod
def say_hi(self):
pass
class TT(Test):
def say_hi(self):
print("i am TT obj")
t = TT()
t.say_hi()
# 鸭子类型 说如果一个对象叫声像鸭子,走路像鸭子,长得像鸭子,那它就是鸭子 是python 推荐的方式,python不喜欢强行限制你
class PC():
def conntent_device(self, usb_device):
usb_device.open()
usb_device.work()
usb_device.close()
class Mouse:
# 实现接口规定的所有功能
def open(self):
print("mouse opened")
def work(self):
print("mouse working...")
def close(self):
print("mouse closed")
mouse = Mouse()
pc = PC()
pc.conntent_device(mouse)
class KeyBoard:
def open(self):
print("KeyBoard opened")
def work(self):
print("KeyBoard working...")
def close(self):
print("KeyBoard closed")
key1 = KeyBoard()
# 如果key1的特征和行为都像USB设备 那就把它当做USB设备来使用
# 对于使用者而言可以不用关心这个对象是什么类,是如如何是实现,
pc.conntent_device(key1)
day25 多继承、接口、抽象类、鸭子类型的更多相关文章
- java 接口 继承 接口 抽象类 继承 实体类
韩梦飞沙 韩亚飞 313134555@qq.com yue31313 han_meng_fei_sha 接口 可以 继承 接口 抽象类 可以 实现 接口 抽象类 继承实体类 需要 实体类 有 ...
- 接口是否可继承接口? 抽象类是否可实现(implements)接口? 抽象类是否可继承实体类(concrete class)?
接口是否可继承接口? 抽象类是否可实现(implements)接口? 抽象类是否可继承实体类(concrete class)? 答:接口可以继承接口.抽象类可以实现(implements)接口,抽象类 ...
- day25 面向对象之多态和鸭子类型
1.封装方法 如何封装:给方法名称前面加上双下划线 # ATM 的取款功能 # 1.插入银行卡 2.输入密码 3.选择取款金额 4.取款 class ATM: def __insert_card(se ...
- python基础语法17 面向对象4 多态,抽象类,鸭子类型,绑定方法classmethod与staticmethod,isinstance与issubclass,反射
多态 1.什么是多态? 多态指的是同一种类型的事物,不同的形态. 2.多态的目的: “多态” 也称之为 “多态性”,目的是为了 在不知道对象具体类型的情况下,统一对象调用方法的规范(比如:名字). 多 ...
- 【Java面试题】60 接口是否可继承接口? 抽象类是否可实现(implements)接口? 抽象类是否可继承具体类(concrete class)? 抽象类中是否可以有静态的main方法?
接口可以继承接口.抽象类可以实现(implements)接口,抽象类可以继承具体类.抽象类中可以有静态的main方法. 问: 抽象类是否可继承实体类 (concrete class) 答: 抽象类是 ...
- kotlin 类 接口 抽象类 子类类型有限的class 。sealed class
韩梦飞沙 韩亚飞 313134555@qq.com yue31313 han_meng_fei_sha 用 private 封装,可以防止别人修改. 就好像 内有高压,危险,不让碰.
- 接口的定义——默认加public abstract默认全局常量;与继承不同,子类可以同时实现多个接口;抽象类实现接口;接口继承接口
一. 接口的定义 接口中定义的方法,全部都为抽象方法,默认加public abstract 接口中定义的变量,全部为全局常量,默认加public static final 二.与继承不同,子类可以同时 ...
- day25 面向对象继承,多态,
这两天所学的都是面向对象,后面还有几天也是它,面向对象主要有三个大的模块,封装,继承,多态,(组合),昨天主要讲了面向对象的命名空间,还有组合的用法,今天是讲的继承还有继承里面所包括的钻石继承,以及多 ...
- python与鸭子类型
部分参考来源:作者:JasonDing https://www.jianshu.com/p/650485b78d11##s1 首先介绍下面向对象(OOP)的三大特征: (1)面向对象程序设计有三大特 ...
随机推荐
- [Svelte 3] Use an onMount lifecycle method to fetch and render data in Svelte 3
Every Svelte component has a lifecycle that starts when it is created, and ends when it is destroyed ...
- HydroCMS-用ueditor无法实现word中图片转存的问题
图片的复制无非有两种方法,一种是图片直接上传到服务器,另外一种转换成二进制流的base64码目前限chrome浏览器使用首先以um-editor的二进制流保存为例:打开umeditor.js,找到UM ...
- [python]有中文字符程序异常的解决方案
一. 含有中文字符无法运行 在python3中用的是Unicode编码,Unicode号称万国码,可以向所有的编码进行兼容.不会出现这种问题. Python2中使用的是ASCII编码,会出现这种问题. ...
- POJ 1741 Tree ——(树分治)
思路参考于:http://blog.csdn.net/yang_7_46/article/details/9966455,不再赘述. 复杂度:找树的重心然后分治复杂度为logn,每次对距离数组dep排 ...
- Django1.6 + jQuery Ajax + JSON 实现页面局部实时刷新
最近微信公众帐号要扩展做一个签到系统,签到结果在一个网页上实时更新,即页面局部刷新.我想用Ajax来实现,之前公众帐号是用的Django搭的,我查找了Django的官方文档,没有封装Ajax.网上有各 ...
- Mac 下python3 [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed 解决方法
原文:http://blog.yuccn.net/archives/625.html python3.6下使用urllib 的request进行url 请求时候,如果请求的是https,请求可以会出现 ...
- 安装wget 、 wget命令
今天给服务器安装新LNMP环境时,wget 时提示 -bash:wget command not found,很明显没有安装wget软件包.一般linux最小化安装时,wget不会默认被安装. 可以通 ...
- js优先队列的定义和使用
//队列,先入先出,FIFO function Queue() { this.items = []; } Queue.prototype = { constructor: Queue, enqueue ...
- cache magic对pms模块的cache访问模式分析结果
其中43.184的命中率只有不到70%,是要分析的对象:3.189是命中率98%左右,是做参考的对象. 基本统计:可以知道43.184的update和delete操作占总操作的比例要比3.189打不少 ...
- vscode在软件内部查看html渲染效果的插件
使用方法: Usage press 'F1' and type "Show Live Server Preview" F1,然后输入Show Live Server Preview ...