继承
什么是继承?
继承是一种新建类的方式,新建的类称为子类或派生类
父类又称为基类、超类
子类可以“遗传”父类的属性,从而可以减少代码冗余
如何寻找继承关系?
先抽象,再继承,继承描述的就是
一种父子关系 / 从属关系
继承的语法
class Foo1:
pass
class Foo2:
pass
class Bar(Foo1, Foo2):
pass
class Bar: # 在python3中没有继承任何类的类,默认继承object
pass
新式类与经典类
新式类与经典类:
新式类:继承object类的子类,以及该子类的子类。。。
在python3中全都是新式类
经典类:没有继承object的子类,以及该子类的子类。。。
只有在python2中才有经典类,在python2中没有继承任何类的子类不会
默认继承object类
class Foo(object):
pass
经典类与新式类的区别:在菱形继承上
经典类:深度优先查找
新式类:广度优先查找
Foo.mro()
在子类定义的方法中重用父类的功能:
方式一:与继承无关
指定道姓地调用某一个类的函数:
类名.函数名(对象,参数1,参数2,...)
方式二:严格依赖继承
super(自己的类名,self).绑定方法(参数1,参数2,。。。)
继承顺序
class A(object):
def test(self):
print('from A')
class B(A):
def test(self):
print('from B')
class C(A):
def test(self):
print('from C')
class D(B):
def test(self):
print('from D')
class E(C):
def test(self):
print('from E')
class F(D,E):
# def test(self):
# print('from F')
pass
f1=F()
f1.test()
print(F.__mro__) #只有新式才有这个属性可以查看线性列表,经典类没有这个属性
#新式类继承顺序:F->D->B->E->C->A
#经典类继承顺序:F->D->B->A->E->C
#python3中统一都是新式类
#pyhon2中才分新式类与经典类
如何查找继承关系
先抽象
抽象对象之间相似之处得到了类
再总结类与类之间的相似得到父类
再继承
子类继承父类,子类可以遗传父类的属性
属性查找
obj.x
1、先从obj.__dict__
2、对象的类.__dict__
3、父类.__dict__
..........
派生
子类定义的名字会覆盖父类的同名属性
class Parent:
x = 1
def f1(self):
print('from parent')
class Sub(Parent):
z = 3
def f1(self):
# Parent.f1(self)
super(Sub, self).f1() # super会检索Sub.mro()
print('from sub')
组合
作用:
组合与继承的作用一样,都是用来减少类与类之间的重复代码
定义:
A类的对象具备某一个属性,该属性的值是B类的对象
基于这种方式就把A类与B类组合到一起
对象既能使用A类中的数据与功能,也能使用B类中的数据与功能
封装
什么是封装?
封装(从字面意思理解)就是隐藏,隐藏指的是在类内部将一个属性藏起来
让类外部的使用者无法直接用到。在py中就是用__开头将一个属性藏起来.
补充说明:封装绝对不是单纯意义的隐藏
需知定义属性的目的就是为了让使用者去用,使用者要想使用类内部隐藏的属性
需要类的设计者在类内部开一个接口(定义一个方法),在该方法内访问隐藏的属性
,使用者以后就通过该方法来“间接地”访问内部隐藏的属性
作为类的设计者可以在接口之上附加任意逻辑从而严格控制类的使用者对属性的操作
class People:
def __init__(self, name):
self.__name = name
def tell_name(self):
# 添加逻辑
return self.__name
obj = People('egon')
# obj.__name
obj.tell_name()
封装函数属性: 隔离复杂度
class ATM:
def __card(self):
print('插卡')
def __auth(self):
print('用户认证')
def __input(self):
print('输入取款金额')
def __print_bill(self):
print('打印账单')
def __take_money(self):
print('取款')
def withdraw(self):
self.__card()
self.__auth()
self.__input()
self.__print_bill()
self.__take_money()
封装之property
用来将类内的函数伪装成一个数据属性
class Foo:
@property
def name(self):
pass
@name.setter
def name(self,value):
pass
@name.deleter
def name(self):
pass
obj=Foo()
obj.name
'''
BMI指数(bmi是计算而来的,但很明显它听起来像是一个属性而非方法,如果我们将其做成一个属性,更便于理解)
成人的BMI数值:
过轻:低于18.5
正常:18.5-23.9
过重:24-27
肥胖:28-32
非常肥胖, 高于32
体质指数(BMI)=体重(kg)÷身高^2(m)
EX:70kg÷(1.75×1.75)=22.86
'''
class People:
def __init__(self, name, weight, height):
self.name = name
self.weight = weight
self.height = height
@property
def bmi(self):
return self.weight / (self.height * self.height)
carter = People('carter', 60, 1.75)
# print(carter.bmi())
print(carter.bmi)
# 属性修改
class People:
def __init__(self, name):
self.__name = name
@property
def name(self):
print('您现在访问的是用户名...')
return self.__name
@name.setter # 修改
def name(self, x):
print('已修改')
self.__name =x
@name.deleter # 删除
def name(self):
print('已删除')
del self.__name
obj = People('carter')
obj.name = 'QX'
print(obj.name)
# del obj.name
# print(obj.name)
classmethod与staticmethod区别
classmethod:
将类中的一个函数绑定给类
staticmethod:
将类中的一个函数解除绑定
'''
1 绑定方法:
在类内部定义的函数,默认就是给对象来用,而且是绑定给对象用的,称为对象的绑定方法
绑定对象的方法特殊之处:
应该由对象来调用,对象来调用,会自动将对象当作第一个参数传入
绑定到类的方法特殊之处:
应该由类来调用,类来调用,会自动将类当作第一个参数传入
'''
import settings
class People:
def __init__(self, name, age, sex):
self.name = name
self.age = age
self.sex = sex
def tell(self):
print('姓名: %s\n年龄: %s\n性别: %s' % (self.name, self.age,self.sex))
@classmethod
def from_conf(cls):
return cls(settings.NAME, settings.AGE, settings.SEX)
p1 = People('carter', 20, 'male')
p1.tell()
p2 = People(settings.NAME, settings.AGE, settings.SEX)
p2.tell()
p3 = People.from_conf()
p3.tell()
'''
2. staticmethod:非绑定方法,就是一个普通函数
特性:既不跟类绑定,也不跟对象绑定,这意味着谁都能用
谁来用都是一个普通函数,也就是说没有自动传值的特性了
'''
import settings
import hashlib
import time
class People:
def __init__(self, name, age, sex):
self.uid = self.create_id()
self.name = name
self.age = age
self.sex = sex
def tell(self):
print('ID: %s\n姓名: %s\n年龄: %s\n性别: %s' % (self.uid, self.name, self.age,self.sex))
@classmethod
def from_conf(cls):
return cls(settings.NAME, settings.AGE, settings.SEX)
@staticmethod
def create_id():
m = hashlib.md5()
m.update(str(time.perf_counter()).encode('UTF-8'))
return m.hexdigest()
obj = People('carter', 18, 'male')
# print(obj.uid, obj.name, obj.age, obj.sex)
obj.tell()
print(obj.create_id())
print(People.create_id())
多态与多态性
多态:
同一种事物有多种形态
在程序中用继承可以表现出多态
多态性:
可以在不考虑对象具体的类的情况下直接参考基类的标准使用对象
鸭子类型:
class Disk:
def read(self):
print('disk read')
def write(self):
print('disk write')
class Txt:
def read(self):
print('txt read')
def write(self):
print('txt write')
class Process:
def read(self):
print('process read')
def write(self):
print('process write')
obj1=Disk()
obj2=Txt()
obj3=Process()
obj1.read()
obj2.read()
obj3.read()