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)面向对象程序设计有三大特 ...
随机推荐
- CodeForces 835C - Star sky | Codeforces Round #427 (Div. 2)
s <= c是最骚的,数组在那一维开了10,第八组样例直接爆了- - /* CodeForces 835C - Star sky [ 前缀和,容斥 ] | Codeforces Round #4 ...
- Luogu P1450 [HAOI2008]硬币购物 背包+容斥原理
考虑如果没有个数的限制,那么就是一个完全背包,所以先跑一个完全背包,求出没有个数限制的方案数即可. 因为有个数的限制,所以容斥一下:没有1个超过限制的方案=至少0个超过限制-至少1个超过限制+至少2个 ...
- 洛谷P4317 花神的数论题
洛谷题目链接 数位$dp$ 我们对$n$进行二进制拆分,于是就阔以像十进制一样数位$dp$了,基本就是套模板.. 接下来是美滋滋的代码时间~~~ #include<iostream> #i ...
- Java源码分析-UUID
原文链接:Little Apple's Blog 本文分析的JDK版本为1.8.0_131. UUID? UUID是Universally Unique Identifier的缩写:Java UUID ...
- java 面试心得总结-BAT、网易
http://blog.csdn.net/sinat_26812289/article/details/50898693
- 如何让spark sql写mysql的时候支持update操作
如何让sparkSQL在对接mysql的时候,除了支持:Append.Overwrite.ErrorIfExists.Ignore:还要在支持update操作 1.首先了解背景 spark提供了一个枚 ...
- 在linux写一个shell脚本用maven git自动更新代码并且打包部署
服务器上必须安装了git maven jdk 并且配置好环境变量 实际服务器中可能运行着多个Java进程,所以重新部署的时候需要先停止原来的java进程,写一个按照名称杀死进程的脚本 kill.sh ...
- 如何知道,当前redis实例是处于阻塞状态?
随便get一个key,然后卡着不动就行,简单粗暴.优雅一点是看latency的延迟,blocked_clients的数量,rejected_connections的数量等 或者 方法一:登录 Redi ...
- python获取最大值
python2 中获取int最大值 import sys print sys.maxint 但是在python3中,报错: AttributeError: module 'sys' has no at ...
- pytorch-LeNet网络
LeNet网络的结构 输入的32x32x1的单通道图片, 第一层网络: 3x3x1x6的卷积层,步长为1, padding = 1, 经过2x2的池化操作 第二层网络: 5x5x6x16的卷积层, 步 ...