Python20-Day07
面向对象之继承与派生
什么是继承?
继承是一种创建新类的方式,新建的类可以继承一个或者多个父类,父类又称为基类或者超类,新建的类称为派生类或者子类
子类会‘遗传’父类的特性,从而解决代码重用问题
python中分为单继承和多继承
class ParentClass1: #定义父类
pass class ParentClass2: #定义父类
pass class SubClass1(ParentClass1): #单继承,父类是ParentClass1,子类是SubClass
pass class SubClass2(ParentClass1,ParentClass2): #python支持多继承,用逗号分隔开多个继承的类
pass
查看继承
#print(SubClass1.__bases__)
(<class '__main__.ParentClass1'>,) #print(SubClass2.__bases__)
(<class '__main__.ParentClass1'>, <class '__main__.ParentClass2'>)
经典类与新式类
1、只有python2中才分为经典类和新式类,python3中都是新式类
2、在python2中没有标明继承object类的类,以及该类的子类,都称为经典类
3、在python2中标明继承object类的类,以及该类的子类,称为新式类
4、python3中,无论是否继承object类,默认都继承object类,即python3中都为新式类
继承与抽象
继承描述的是子类与父类之间的关系,是什么是什么的关系,要找出这种关系,必须先抽象再继承
属性查找
class Foo:
def f1(self):
print('Foo.f1') def f2(self):
print('Foo.f2')
self.f1() class Bar(Foo):
def f1(self):
print('Foo.f1') b=Bar()
b.f2() #得到的结果为:
Foo.f2
Foo.f1
派生
子类也可以添加自己新的属性或者自己重新定义属性。一旦重新定义了自己的属性且与父类重名,调用新增的属性时,就以自己的为准了。
class ParentClass:
def __init__(self,name,age,sex):
self.name = name
self.age = age
self.sex = sex
def tell_info(self):
print('%s is in old_class!' %self.name)
class SubClass(ParentClass):
def __init__(self,name,age,sex):
ParentClass.__init__(self,name,age,sex)
# def tell_info(self):
# print('%s is in subclass!' %self.name) stu1 = SubClass('zly',25,'female')
stu1.tell_info() #此时调用结果为:
zly is in old_class! #如果在SubClass子类中也定义tell_info属性,此时调用结果为:
zly is in subclass!
组合与重用性
软件重用的重要方式除了继承之外还有另外一种:组合
组合指的是:在一个类中以另外一个类的对象作为数据属性,称为类的组合
继承:
通过继承建立了派生类与基类之间的关系,是一种什么是什么的关系。
当类之间有很多相同的功能,提取这些共同的功能做成父类。用继承比较好
组合:
用组合的方式建立了类与组合的类之间的关系,是一种有的关系。
class People:
def __init__(self,name,age,sex):
self.name=name
self.age=age
self.sex=sex class Course:
def __init__(self,name,period,price):
self.name=name
self.period=period
self.price=price
def tell_info(self):
print('<%s %s %s>' %(self.name,self.period,self.price)) class Teacher(People):
def __init__(self,name,age,sex,job_title):
People.__init__(self,name,age,sex)
self.job_title=job_title
self.course=[]
self.students=[] class Student(People):
def __init__(self,name,age,sex):
People.__init__(self,name,age,sex)
self.course=[] egon=Teacher('egon',18,'male','沙河霸道金牌讲师')
s1=Student('牛榴弹',18,'female') python=Course('python','3mons',3000.0)
linux=Course('python','3mons',3000.0) #为老师egon和学生s1添加课程
egon.course.append(python)
egon.course.append(linux)
s1.course.append(python) #为老师egon添加学生s1
egon.students.append(s1) #使用
for obj in egon.course:
obj.tell_info()
抽象类
抽象类是一个特殊的类,它的特殊之处在于只能被继承,不能被实例化
从设计的角度看,如果类是从现实对象抽象而来的,那么抽象类就是基于类抽象来的。
抽象类中只有抽象方法,没有实现功能,该类不能被实例化,只能被继承,且子类必须实现抽象方法。
#_*_coding:utf-8_*_
__author__ = 'Linhaifeng'
#一切皆文件
import abc #利用abc模块实现抽象类 class All_file(metaclass=abc.ABCMeta):
all_type='file'
@abc.abstractmethod #定义抽象方法,无需实现功能
def read(self):
'子类必须定义读功能'
pass @abc.abstractmethod #定义抽象方法,无需实现功能
def write(self):
'子类必须定义写功能'
pass # class Txt(All_file):
# pass
#
# t1=Txt() #报错,子类没有定义抽象方法 class Txt(All_file): #子类继承抽象类,但是必须定义read和write方法
def read(self):
print('文本数据的读取方法') def write(self):
print('文本数据的读取方法') class Sata(All_file): #子类继承抽象类,但是必须定义read和write方法
def read(self):
print('硬盘数据的读取方法') def write(self):
print('硬盘数据的读取方法') class Process(All_file): #子类继承抽象类,但是必须定义read和write方法
def read(self):
print('进程数据的读取方法') def write(self):
print('进程数据的读取方法') wenbenwenjian=Txt() yingpanwenjian=Sata() jinchengwenjian=Process() #这样大家都是被归一化了,也就是一切皆文件的思想
wenbenwenjian.read()
yingpanwenjian.write()
jinchengwenjian.read() print(wenbenwenjian.all_type)
print(yingpanwenjian.all_type)
print(jinchengwenjian.all_type)
继承实现的原理
1、继承顺序
如果继承关系为非菱形结果,则会按照先找B这一条分支,然后再找C这一条分支,最后找D这一条分支,
如果继承关系为菱形结构,属性查找:深度优先和广度优先。
2、继承原理
定义的每一个类,python会计算出一个方法解析顺序(MRO)列表,这个MRO列表就是一个简单的所有基类的线性顺序列表。
所有父类的MRO列表遵循以下3条原则:
1、子类会先与父类被检查
2、多个父类会根据他们在列表中的顺序被检查
3、如果对下一个类存在两个合法的选择,选择第一个父类
面向对象之封装
如何隐藏?
在python中用双下划线开头的方式将属性隐藏起来(设置成私有的)
#其实这仅仅这是一种变形操作且仅仅只在类定义阶段发生变形
#类中所有双下划线开头的名称如__x都会在类定义时自动变形成:_类名__x的形式: class A:
__N=0 #类的数据属性就应该是共享的,但是语法上是可以把类的数据属性设置成私有的如__N,会变形为_A__N
def __init__(self):
self.__X=10 #变形为self._A__X
def __foo(self): #变形为_A__foo
print('from A')
def bar(self):
self.__foo() #只有在类内部才可以通过__foo的形式访问到. #A._A__N是可以访问到的,
#这种,在外部是无法通过__x这个名字访问到。
变形的过程只在类的定义时发生一次,在定义后的赋值操作,不会变形
在继承中,父类如果不想让子类覆盖自己的方法,可以将方法定义为私有。
#正常情况
>>> class A:
... def fa(self):
... print('from A')
... def test(self):
... self.fa()
...
>>> class B(A):
... def fa(self):
... print('from B')
...
>>> b=B()
>>> b.test()
from B #把fa定义成私有的,即__fa
>>> class A:
... def __fa(self): #在定义时就变形为_A__fa
... print('from A')
... def test(self):
... self.__fa() #只会与自己所在的类为准,即调用_A__fa
...
>>> class B(A):
... def __fa(self):
... print('from B')
...
>>> b=B()
>>> b.test()
from A
封装数据:
将数据隐藏起来,然后对外提供操作该数据的接口,然后可以在接口附加上对该数据操作的限制,以此完成对数据属性操作的严格限制。
class Teacher:
def __init__(self,name,age):
# self.__name=name
# self.__age=age
self.set_info(name,age) def tell_info(self):
print('姓名:%s,年龄:%s' %(self.__name,self.__age))
def set_info(self,name,age):
if not isinstance(name,str):
raise TypeError('姓名必须是字符串类型')
if not isinstance(age,int):
raise TypeError('年龄必须是整型')
self.__name=name
self.__age=age t=Teacher('egon',18)
t.tell_info() t.set_info('egon',19)
t.tell_info()
封装方法:目的是隔离复杂度
#取款是功能,而这个功能有很多功能组成:插卡、密码认证、输入金额、打印账单、取钱
#对使用者来说,只需要知道取款这个功能即可,其余功能我们都可以隐藏起来,很明显这么做
#隔离了复杂度,同时也提升了安全性 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() a=ATM()
a.withdraw()
特性(property)
什么是特性property?
property是一种特殊的属性,访问它时会执行一段功能,然后返回值。
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**2) p1=People('egon',75,1.85)
print(p1.bmi)
为什么要用property?
将一个类的函数定义成特性后,对象再去使用的时候obj.name,根本无法察觉自己的nameshi执行了一个函数后计算出来的。这种特性的使用方式遵循了统一访问的原则
面向对象之绑定方法与非绑定方法
类中定义的函数分成两大类
1、绑定方法(绑定给谁,谁来调用就自动将它本身当作第一个参数传入)
1、绑定到类的方法:用classmethod装饰器装饰的方法
为类量身定制
2、绑定到对象的方法:没有被任何装饰器装饰的方法
为对象量身定制
属于类的函数,类可以调用,但是必须按照函数的规则来,没有自动传值一说。
2、非绑定方法:用staicmethod装饰器装饰的方法
1、不与类或对象绑定,类和对象都可以调用。但是没有自动传值一说,就是一个普通工具。
绑定方法:
绑定给类的方法(classmethod)
classmethod是给类用的,即绑定到类,类在使用时会将类本身当做参数传给类方法的第一个参数,python内置了函数classmethod来吧类中的函数定义成类方法
#settings.py
HOST='127.0.0.1'
PORT=3306
DB_PATH=r'C:\Users\Administrator\PycharmProjects\test\面向对象编程\test1\db'
import settings
class MySQL:
def __init__(self,host,port):
self.host=host
self.port=port @classmethod
def from_conf(cls):
print(cls)
return cls(settings.HOST,settings.PORT) print(MySQL.from_conf) #<bound method MySQL.from_conf of <class '__main__.MySQL'>>
conn=MySQL.from_conf() conn.from_conf() #对象也可以调用,但是默认传的第一个参数仍然是类
非绑定方法
在类内部用staicmethod装饰的函数即非绑定方法,就是普通函数
staicmethod不与类或对象绑定,谁都可以调用,没有自动传值效果
import hashlib
import time
class MySQL:
def __init__(self,host,port):
self.id=self.create_id()
self.host=host
self.port=port
@staticmethod
def create_id(): #就是一个普通工具
m=hashlib.md5(str(time.time()).encode('utf-8'))
return m.hexdigest() print(MySQL.create_id) #<function MySQL.create_id at 0x0000000001E6B9D8> #查看结果为普通函数
conn=MySQL('127.0.0.1',3306)
print(conn.create_id) #<function MySQL.create_id at 0x00000000026FB9D8> #查看结果为普通函数
classmethod与staicmethod区别
import settings
class MySQL:
def __init__(self,host,port):
self.host=host
self.port=port @staticmethod
def from_conf():
return MySQL(settings.HOST,settings.PORT) # @classmethod #哪个类来调用,就将哪个类当做第一个参数传入
# def from_conf(cls):
# return cls(settings.HOST,settings.PORT) def __str__(self):
return '就不告诉你' class Mariadb(MySQL):
def __str__(self):
return '<%s:%s>' %(self.host,self.port) m=Mariadb.from_conf()
print(m) #我们的意图是想触发Mariadb.__str__,但是结果触发了MySQL.__str__的执行,打印就不告诉你:
Python20-Day07的更多相关文章
- day07 Cookie 和 Session(非常重要)
day07 Cookie 和 Session 1. 会话技术 2. cookie 的方法和 cookie 案例-显示用户上次访问网站的时间 3. cookie 的细节 - 删除 cookie 4. S ...
- python day07笔记总结
2019.4.4 S21 day07笔记总结 一.深浅拷贝 1.copy.copy() 浅拷贝 deep.copy() 深拷贝 2.一般情况 1.str/int/bool 是不可变类型 ...
- Python面向对象-day07
写在前面 上课第七天,打卡: 时间的高效利用: 前言: 今天egon老师补充了下 is 和 == 的区别,整理如下:Python中变量的属性以及判断方法 一.面向过程和面向对象 - 1.面向过程 核心 ...
- 逆袭之旅.DAY07东软实训..封装~继承~抽象~final
2018年7月3日.逆袭之旅DAY07 package day0703.exam1; /** * 狗狗类 使用权限修饰符private和public进行封装 * @author Administrat ...
- C++Primer笔记-----day07
==========================================================================day07===================== ...
- Day07 jdk5.0新特性&Junit&反射
day07总结 今日内容 MyEclipse安装与使用 JUnit使用 泛型 1.5新特性 自动装箱拆箱 增强for 静态导入 可变参数方法 枚举 反射 MyEclipse安装与使用(yes) 安装M ...
- python开发学习-day07(面向对象之多态、类的方法、反射、新式类and旧式类、socket编程)
s12-20160227-day07 *:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: ...
- 2017-2018-1 JAVA实验站 冲刺 day07
2017-2018-1 JAVA实验站 冲刺 day07 各个成员今日完成的任务 小组成员 今日工作 完成进度 张韵琪 写博客.进行工作总结 100% 齐力锋 部分按钮图片.对按钮图片进行ps 100 ...
- dup、文件锁、库函数、函数调用(day07)
一.lseek()重新定位文件的读写位置. #include <sys/types.h> #include <unistd.h> off_t lseek(int fd, off ...
- 记录我的 python 学习历程-Day07 基础数据类型进阶 / 数据类型之间的转换 / 基础数据类型总结 / 编码的进阶
基础数据类型 str(字符串) str:补充方法练习一遍就行 s.capitalize() 首字母大写,其余变小写 s = 'dyLAn' print(s.capitalize()) # Dylan ...
随机推荐
- Python自动化之clean方法前端调用clean方法的错误
obj.non_field_errors.0 源代码: NON_FIELD_ERRORS = '__all__' 如果在前端写 obj.errors.__all__.0直接就会报错 所以经过尝试得知, ...
- Linux搜索查找命令
Linux搜索查找指令 find,用于在文件树中查找文件并作相应的处理 -name:按照文件名查找文件 -perm:按照文件权限查找文件 -user:按照文件属主来查找文件 -size:按照指定的文件 ...
- Kafka设计解析(十七)Kafka 0.11客户端集群管理工具AdminClient
转载自 huxihx,原文链接 Kafka 0.11客户端集群管理工具AdminClient 很多用户都有直接使用程序API操作Kafka集群的需求.在0.11版本之前,kafka的服务器端代码(即添 ...
- 在Qtlabel中显示数字十六进制和十进制都可以
ui->label_6->setText(QString::number(table_test[0]<<8 | table_test[1]));这样子就可以把十六进制的数转换为 ...
- phpqrcode生成动态二维码简单实例
这是一个利用phpqrcode生成动态二维码简单实例,比微信官方提供的接口还要好用.二维码是动态的,不用生成图片,可自定义二维码大小,间隙,跳转地址等. 参数设置: include_once 'php ...
- 数据分析-pandas基础入门(一)
最近在学习python,所以了解了一下Pandas,Pandas是基于NumPy的一个开源Python库,它被广泛用于快速分析数据,以及数据清洗和准备等工作. 首先是安装numpy以及pandas, ...
- 使用RT3070使开发板上网
原文地址:http://www.cnblogs.com/NickQ/p/8973880.html 使开发板上网 USB驱动部分 在arch/arm/mach-s3c2440/mach-smdk2440 ...
- webdriver 获取页面response
在selenium webdriver实现自动化抓取数据过程中,发现无法从webdriver获取页面response 查来查去最终在 stackoverflow 上找到了这一篇文章 文章中说:webd ...
- 4557: [JLoi2016]侦察守卫
4557: [JLoi2016]侦察守卫 链接 分析: 因为D比较小,所设状态f[i][j]表示子树i内,从i往下第j层及第j层以下都覆盖了的最小代价,g[i][j]表示覆盖完子树内所有点,还可以往上 ...
- cogs1799 [国家集训队2012]tree(伍一鸣)
LCT裸题 注意打标记之间的影响就是了 这个膜数不会爆unsigned int #include<cstdio> #include<cstdlib> #include<a ...