day30 继承、派生与多态,类中方法和内置函数
一、多继承出现的问题(mixins机制)
继承从人的思维逻辑上看,就是什么什么(子类)是什么(父类),具体一点就是人类和狗类都属于动物类。
但是如果有特殊情况导致出现多继承,就会违反人类的思维逻辑,一类事物是多种事物
从代码层面来讲
class Vehicle:
pass
class FlyableMixin:
def fly(self):
pass
class CivilAircraft(FlyableMixin,Vehicle): # 民航飞机
pass
class Helicopter(FlyableMixin,Vehicle): # 直升飞机
pass
class Car(Vehicle): # 汽车并不会飞,但按照上述继承关系,汽车也能飞了
pass
民航飞机和直升飞机和汽车都属于交通工具,如果我们要解决民航飞机和直升飞机的代码冗余把飞行功能提取到交通工具类中。会导致汽车也能飞,这就违反了我们设置汽车类的原则。
多继承解决了我们代码冗余问题,也没有违反汽车类的原则。
但是多继承又给我们带来新的问题,程序可读性差。
这里引入一种规范,如果我们需要为多种类去总结一类功能,我们可以定义一个特殊的功能类,以Mixin为结尾,在集成时放在唯一父类的左边。
二、派生与方法重用
子类可以派生出自己新的属性,在进行属性查找的时候,子类的属性会优先父类查找。
class People:
def __init__(self,name,age):
self.name = name
self.age = age
class Teacher(People):
def __init__(self,name,age,sex):
self.name = name
self.age = age
self.sex = sex
teacher里面的init和父类的init方法有重复的地方,我们可以通过以下两种方法实现父类方法的重用
方法一:‘指名道姓’的调用某一个类的函数
class People:
def __init__(self,name,age):
self.name = name
self.age = age
class Teacher(People):
def __init__(self,name,age,sex):
People.__init__(self,name,age)
self.sex = sex
方式二:super()
super()调用父类提供给自己的方法=》严格依赖继承关系
调用super()会得到一个特殊的对象,该对象会参照发起属性查找的那个类的mro,去当前类的父类中找属性
class Teacher(People):
def __init__(self,name,age,sex):
super().__init__(name,age)
self.sex = sex
这两种方式的区别是:方式一是跟继承没有关系的,而方式二的super()是依赖于继承的,并且即使没有直接继承关系,super()仍然会按照MRO继续往后查找
class A:
def text(self):
super().text()
class B:
def text(self):
print("text B")
class C(A,B):
pass
obj = C()
obj.text()
# 此刻调用是根据类C的mro列表查找顺序查找,即便A没有继承B,根据C的继承,还是会查到B中的text
>>>text B
三、多态
1 什么是多态
定义:同一种事物的多重形态
多态和继承是一种相对立的抽象概念
class Animal:
pass
class People(Animal):
pass
class Dog(Animal):
pass
class Pig(Animal):
pass
人类,狗类,猪类,他们继承于父类动物类,说明他们都有动物类的属性。
换一种说话,动物类有三种形态,人类,猪类,狗类,这就是多态
2 为什么要有多态
多态性指的是可以在不考虑对象具体类型的情况下而直接使用对象,我们在知道了该类是哪一种类型的不同形态,我们就可以用那种类型的方法进行操作。
class Animal: # 统一所有子类的方法
def say(self):
print('动物基本的发声频率。。。',end=' ')
class People(Animal):
def say(self):
super().say()
print('嘤嘤嘤嘤嘤嘤嘤')
class Dog(Animal):
def say(self):
super().say()
print('汪汪汪')
class Pig(Animal):
def say(self):
super().say()
print('哼哼哼')
更进一步,我们可以通过定义统一的接口,接受传入的对象
def animal_say(animal):
animal.say()
#只要是动物类所属其他多态类的对象,都可使用这个方法,不需要任何条件
综上我们得知,多态性的本质在于不同的类中定义有相同的方法名,这样我们就可以不考虑类而统一用一种方式去使用对象,可以通过在父类引入抽象类的概念来硬性限制子类必须有某些方法名
import abc
# 指定metaclass属性将类设置为抽象类,抽象类本身只是用来约束子类的,不能被实例化
class Animal(metaclass=abc.ABCMeta):
@abc.abstractmethod # 该装饰器限制子类必须定义有一个名为talk的方法
def talk(self): # 抽象方法中无需实现具体的功能
pass
class Cat(Animal): # 但凡继承Animal的子类都必须遵循Animal规定的标准
def talk(self):
pass
cat=Cat() # 若子类中没有一个名为talk的方法则会抛出异常TypeError,无法实例化
3 python中多态的鸭子类型
鸭子类型:如果一个东西,他看起来像鸭子,叫起来也像鸭子,我们就可以把他看做鸭子
放在程序中,如果一个类,看起来像a,有a的特性,那我们就可以把它当做a来使用(可以去使用a中的方法,不管他是否继承于a)
#二者看起来都像文件,因而就可以当文件一样去用,然而它们并没有直接的关系
class Txt: #Txt类有两个与文件类型同名的方法,即read和write
def read(self):
pass
def write(self):
pass
class Disk: #Disk类也有两个与文件类型同名的方法:read和write
def read(self):
pass
def write(self):
pass
四、绑定方法与非绑定方法
定义
类中定义的函数有两大类:绑定方法与非绑定方法
绑定方法也分为两类:对象的绑定方法,类的绑定方法
1 绑定方法
1.1对象的绑定方法
类中的方法都是默认绑定给对象的
class Peopel:
#say就是类中对象的绑定方法
def say(self):#self是对象绑定方法规范第一个传参写法
pass
特性:
对象在使用时,作为绑定方法,会把对象作为第一个参数传入
类在调用时,作为函数,要严格按照函数的传参对应传值
1.2 类的绑定方法
为类中某个函数加上装饰器@classmethod后,该函数就绑定到了类
class Peopel:
@classmethod
#text就是类中对象的绑定方法
def text(cls):#cls是类绑定方法规范第一个传参写法
pass
特性:
对象在试用时和类在使用时,都会把类作为第一个参数传入,所以这种方法对象调用没有意义,只是用来给类使用的。
2 非绑定方法
为类中某个函数加上装饰器@staticmethod后,该函数就变成了非绑定方法,也称为静态方法。该方法不与类或对象绑定,类与对象都可以来调用它,但它就是一个普通函数而已,因而没有自动传值那么一说
import uuid
class MySQL:
def __init__(self,host,port):
self.id=self.create_id()
self.host=host
self.port=port
@staticmethod
def create_id():
return uuid.uuid1()
总结:
如果我们这个方法是给类用的,加上装饰器@classmethod,让这个方法自动绑定类
如果我们这个方法是给对象用的,不用管,python中类的方法默认都是绑定对象
如果我们这个方法谁都能用,加上装饰器@staticmethod,设置成静态方法谁调他都只是个普通的函数。
五、内置函数
1 zip
把传入的两个可迭代对象一一对应成元组放在字典里,多出的不管
v1='hello'
v2=[111,222,333,444,5555,6666]
res=zip(v1,v2)
print(list(res))
>>>[('h', 111), ('e', 222), ('l', 333), ('l', 444), ('o', 5555)]
2 divmod
传入的第一个值为被除数,第二个值为除数,返回一个元组,第一个值是商,第二个值是余数
print(divmod(10000,33))
>>>(303, 1)
3 dir
查看对象或者类有哪些方法
class Foo:
pass
obj=Foo()
obj.xxx=1111
print(dir(obj)) # obj.哪些属性
>>>['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'xxx']
4 enumerate
枚举,迭代循环一个可迭代对象,返回一个enumerate对象,内含可迭代对象的所在位置和值的一个一个元组
for v in enumerate(['a','b','c']):
print(v)
print(type(enumerate(['a','b','c'])))
>>>(0, 'a')
>>>(1, 'b')
>>>(2, 'c')
>>><class 'enumerate'>
5 eval
执行字符串中的表达式
res=eval('{"a":1}') # 执行字符串中的表达式
print(res,type(res))
>>>{'a': 1} <class 'dict'>
6 isinstance
判断类型和type区别使用,type是用来返回类型的
class Foo:
pass
obj=Foo()
print(isinstance(obj,Foo))
print(isinstance([],list)) # 类型判断推荐使用isinstance
print(type([]) is list) # 不推荐使用
>>>True
>>>True
>>>True
day30 继承、派生与多态,类中方法和内置函数的更多相关文章
- 洗礼灵魂,修炼python(36)--面向对象编程(6)—类的相关内置函数issubclass,hasattr等
啥?我靠,类也有内置函数?哈哈,确实有的.有哪些呢?请往下看 issubclass(cls, class_or_tuple, /) 1.基本属性: 方法全是特殊方法 2.使用方法:判断一个类是否由另一 ...
- python 类(object)的内置函数
python 类(object)的内置函数 # python 类(object)的内置函数 ### 首先 #### 以__双下划线开头的内置函数 __ #### __往往会在某些时候被自动调用,例如之 ...
- Day07:常用模块,面向对象编程(对象&类)及内置函数
今日内容:1.常用模块2.面向对象编程(*****) 介绍面向对象编程 类 对象3.内置函数------------------------------1.面向过程编程 核心“ ...
- python类中的内置函数
__init__():__init__方法在类的一个对象被建立时,马上运行.这个方法可以用来对你的对象做一些你希望的初始化.注意,这个名称的开始和结尾都是双下划线.代码例子: #!/usr/bin/p ...
- day29 类中的内置函数方法 __str__ __repr__ __call__ isinstance() issubclass()
__str__()__repr__()__len__() str() 转字符串repr() 让字符原形毕露的方法len() 计算长度 内置的方法很多,但是并不是全部都在object中,比如len(), ...
- Day 21 python :面向对象 类的相关内置函数 /单例模式 /描述符
1.isinstance(obj,cls) 检查obj是否是类cls的对象: 备注:用isinstance 的时候,产生实例后,会显示实例既是父类的实例,也是子类的实例 class Mom: gend ...
- python 类中__call__内置函数的使用
class F: def __call__(self, *args, **kwargs): print('执行__call__') s = F()s() 先给类创建一个对象,直接通过对象来执行,就会自 ...
- python基础(14)-反射&类的内置函数
反射 几个反射相关的函数可参考python基础(10)-匿名函数&内置函数中2.2.4反射相关 类的一些内置函数 __str__()&__repr__() 重写__str__()函数类 ...
- python面向对象的多态-类相关内置函数-类内置魔法函数-迭代器协议-上下文管理-04
多态 一种事物具备不同的形态 例如:水 --> 固态.液态.气态 多态:# 多个不同对象可以相应同一个对象,产生不同的结果 首先强调,多态不是一种特殊的语法,而是一种状态,特性(多个不同对象可以 ...
随机推荐
- Vue中解决新脚手架3创建项目的移动端双击屏幕放大,双手拉动放大的方法
替换新版vue-cli创建项目的public>index.html <!DOCTYPE html> <html lang="en"> <head ...
- JDK8在泛型类型推导上的变化
概述 JDK8升级,大部分问题可能在编译期就碰到了,但是有些时候比较蛋疼,编译期没有出现问题,但是在运行期就出了问题,比如今天要说的这个话题,所以大家再升级的时候还是要多测测再上线,当然JDK8给我们 ...
- Thread和Runnable
继承Thread类不能实现资源共享.(程序启动了三个线程,但是3个线程却分别卖了各自的5张票,并没有达到资源共享的目的) 实现Runnable接口可以资源共享.(程序启动了三个线程,但是3个线程一共才 ...
- centos7.2挂载硬盘攻略
远程SSH登录上CentOS服务器后,进行如下操作: 提醒:挂载操作会清空数据,请确认挂载盘无数据或者未使用 第一步:列出所有磁盘 命令: ll /dev/disk/by-path ll /dev/d ...
- DedeCms 首页、列表页调用文章body内容的方法
[第一种方法] arclist标签使用如下: {dede:arclist row='1' typeid='1' addfields='body' idlist='1' channelid='1'} [ ...
- kali系统安装后乱码的解决
1.先添加kaili的源地址*(这里推荐了几个源,选一个就可以.打开/etc/apt/sources.list 删除里面自带的所有内容,把你复制的内容添加进去保存就ok了) #中科大 deb http ...
- RESTORE FILELISTONLY FROM DISK ='D:\DataSQL\BakFile\pubs.bak' _ 数据库安装工具_连载_4
在查询分析器中执行: RESTORE FILELISTONLY FROM DISK = 'D:\DataSQL\BakFile\pubs.bak'根据查询类型判断Type(D.L),再取得对应的Lo ...
- 02.DRF-认识RESTful
认识RESTful 在前后端分离的应用模式里,后端API接口如何定义? 例如对于后端数据库中保存了商品的信息,前端可能需要对商品数据进行增删改查,那相应的每个操作后端都需要提供一个API接口: POS ...
- 《Java并发编程的艺术》 第9章 Java中的线程池
第9章 Java中的线程池 在开发过程中,合理地使用线程池能带来3个好处: 降低资源消耗.通过重复利用已创建的线程 降低线程创建和销毁造成的消耗. 提高响应速度.当任务到达时,任务可以不需要等到线程创 ...
- 08.利用Easymock测试简单的servlet
1.首先导入需要使用的servlet的jar包 接下来我们编写一个登陆的servlet package com.fjnu.service; import java.net.HttpRetryExcep ...