day6--面向对象初识
一面向过程与面向对象
面向过程:
流水线式的思维,顺着流程进行下去,类似于代码的堆叠,重视步骤
优点:不需要考虑太多东西,想到一个功能就写一个功能,堆叠代码
缺点:过程往往是先后执行的,要想变换功能或者增加功能,就要考虑重新堆叠大部分或者所有代码了,牵一发而动全身
面向对象:
将事务分解成各个对象,可以给这个对象附加相应的功能,后面的东西一旦调用,这些功能或者方法也就自然的拥有了
优点:对象可扩展,并可以单独修改,调用的地方会立刻显现,我是一块砖哪里需要哪里搬
缺点:无法预测出现问题的具体地方,对象和对象之间融合到一块了,找出问题需要很长时间
面向对象在实际运用中还是很普遍的,将事务拆分成各个对象,大家可以分头去做,往往进度比较快
面向对象的实现需要类和对象
二 类和对象
类:相当于一个模板,里面有这个模板的函数,变量,属性,方式方法等
对象:根据模板来创建,这样自然而然对象就拥有了类里面的东西
2.1 定义一个类
一个类的定义有其独特的方式,类名首字母大写,里面定义的函数,其参数必须有self
例如:
class Person: #定义一个人类
role = 'person' #人的角色属性都是人
def walk(self): #人都可以走路,也就是有一个走路方法
print("person is walking...")
print(Person.role) #查看人的role属性
print(Person.walk) #引用人的走路方法,注意,这里不是在调用
2.2实例化
类名加括号就是实例化,会自动触发__init__函数的运行,可以用它来为每个实例定制自己的特征
例如:
class Person: #定义一个人类
role = 'person' #人的角色属性都是人
def __init__(self,name):
self.name = name # 每一个角色都有自己的昵称; def walk(self): #人都可以走路,也就是有一个走路方法
print("person is walking...") print(Person.role) #查看人的role属性
print(Person.walk) #引用人的走路方法,注意,这里不是在调用
实例化的过程就是类——>对象的过程
2.3类的属性
dir(类名):查出的是一个名字列表
类名.__dict__:查出的是一个字典,key为属性名,value为属性值 二:特殊的类属性
类名.__name__# 类的名字(字符串)
类名.__doc__# 类的文档字符串
类名.__base__# 类的第一个父类(在讲继承时会讲)
类名.__bases__# 类所有父类构成的元组(在讲继承时会讲)
类名.__dict__# 类的字典属性
类名.__module__# 类定义所在的模块
类名.__class__# 实例对应的类(仅新式类中)
2.4类的查看
类的两种变量:静态变量和动态变量
例如:
class Person: # class 关键字,定义了一个类
'''
类里面的所有内容
'''
animal = '高级动物' # 静态变量
soup = '有思想' # 静态变量 def __init__(self,name,sex,eye,high,weight,): # 构造方法 self.eye = eye # 属性
self.name = name
self.sex = sex
self.high = high
self.weight = weight
print(666) def work(self): # 动态变量,动态方法,方法
print(self)
# self.job = 'IT'
print('人会工作....')
1,类名.__dict__方法 只能查看,不能增删改。
# print(Person.__dict__)
# print(Person.__dict__['animal'])
#查询动态变量
print(Person.__dict__['work'](11))
2 类名.变量名 可增删改查
# print(Person.animal)
# print(Person.soup)
# Person.kind = '有性格'
# Person.animal = '低等动物'
# del Person.kind
查询动态变量
#Person.work(11)
2.5对象的查看
实例化一个对象内部进行了三步
# 内部进行三步:
# 1,实例化一个对象,在内存中产生一个对象空间。
# 2,自动执行init方法,并将这个空间对象。 <__main__.Person object at 0x0000000001F5ABE0> 传给self
# 3,通过构造方法里的代码给空间对象添加一些属性,并返回给对象。
对象的查看与类的查看类似,只是将类名换成了对象名
类的静态属性是共享给对象的,类的动态属性是绑定给对象的
三面向对象的三大特性
3.1继承
继承是一种创建新类的方式,在python中,新建的类可以继承一个或多个父类,父类又可称为基类或超类,新建的类称为派生类或子类
继承简单的来说就是子继承父
继承分为:单继承和多继承
一些对象具体相同的功能时,可以在它们的父类中实现,这样的话可以减少很多代码
注:除了子类和父类的称谓,你可能看到过 派生类 和 基类 ,他们与子类和父类只是叫法不同而已。
查看继承
类名.__bases__ #__base__只查看从左到右继承的第一个子类,__bases__则是查看所有继承的父类
如果没有指定基类,python会默认继承object类,object是所有python类的基类
例如:leiming.__bases__
#结果为 (<class 'object'>,)
有很多情况是一个子类往往有很多父类,这个是多继承,它又是如何继承的
1、Python的类可以继承多个类,Java和C#中则只能继承一个类
2、Python的类如果继承了多个类,那么其寻找方法的方式有两种,分别是:深度优先和广度优先
- 当类是经典类时,多继承情况下,会按照深度优先方式查找
- 当类是新式类时,多继承情况下,会按照广度优先方式查找
经典类和新式类,从字面上可以看出一个老一个新,新的必然包含了跟多的功能,也是之后推荐的写法,从写法上区分的话,如果 当前类或者父类继承了object类,那么该类便是新式类,否则便是经典类。
class D: def bar(self):
print 'D.bar' class C(D): def bar(self):
print 'C.bar' class B(D): def bar(self):
print 'B.bar' class A(B, C): def bar(self):
print 'A.bar' a = A()
# 执行bar方法时
# 首先去A类中查找,如果A类中没有,则继续去B类中找,如果B类中么有,则继续去D类中找,如果D类中么有,则继续去C类中找,如果还是未找到,则报错
# 所以,查找顺序:A --> B --> D --> C
# 在上述查找bar方法的过程中,一旦找到,则寻找过程立即中断,便不会再继续找了
a.bar()
经典类多继承
class D(object): def bar(self):
print 'D.bar' class C(D): def bar(self):
print 'C.bar' class B(D): def bar(self):
print 'B.bar' class A(B, C): def bar(self):
print 'A.bar' a = A()
# 执行bar方法时
# 首先去A类中查找,如果A类中没有,则继续去B类中找,如果B类中么有,则继续去C类中找,如果C类中么有,则继续去D类中找,如果还是未找到,则报错
# 所以,查找顺序:A --> B --> C --> D
# 在上述查找bar方法的过程中,一旦找到,则寻找过程立即中断,便不会再继续找了
a.bar()
新式类多继承
抽象类与接口类
继承有两种用途:
一:继承基类的方法,并且做出自己的改变或者扩展(代码重用)
二:声明某个子类兼容于基类,定义一个接口类interface,接口类中定义了一些接口名(即函数)且并未实现
接口的功能,子类继承接口类,并且实现接口中的功能
这第二种就是接口继承
接口继承实质上是要求“做出一个良好的抽象,这个抽象规定了一个兼容接口,使得外部调用者无需关心具体细节,
可一视同仁的处理实现了特定接口的所有对象”——这在程序设计上,叫做归一化。
归一化使得高层的外部使用者可以不加区分的处理所有接口兼容的对象集合——就好象linux的泛文件概念一样,
所有东西都可以当文件处理,不必关心它是内存、磁盘、网络还是屏幕(当然,对底层设计者,
当然也可以区分出“字符设备”和“块设备”,然后做出针对性的设计:细致到什么程度,视需求而定)。
为什么用接口?
接口提取了一群类共同的函数,可以把接口当做一个函数的集合。 然后让子类去实现接口中的函数。 这么做的意义在于归一化,什么叫归一化,就是只要是基于同一个接口实现的类,那么所有的这些类产生的对象在使用时,从用法上来说都一样。 归一化,让使用者无需关心对象的类是什么,只需要的知道这些对象都具备某些功能就可以了,这极大地降低了使用者的使用难度。 比如:我们定义一个动物接口,接口里定义了有跑、吃、呼吸等接口函数,这样老鼠的类去实现了该接口,松鼠的类也去实现了该接口,由二者分别产生一只老鼠和一只松鼠送到你面前,即便是你分别不到底哪只是什么鼠你肯定知道他俩都会跑,都会吃,都能呼吸。 再比如:我们有一个汽车接口,里面定义了汽车所有的功能,然后由本田汽车的类,奥迪汽车的类,大众汽车的类,他们都实现了汽车接口,这样就好办了,大家只需要学会了怎么开汽车,那么无论是本田,还是奥迪,还是大众我们都会开了,开的时候根本无需关心我开的是哪一类车,操作手法(函数调用)都一样 为什么用接口
在python中根本就没有一个叫做interface的关键字,上面的代码只是看起来像接口,其实并没有起到接口的作用,子类完全可以不用去实现接口 ,如果非要去模仿接口的概念,可以借助第三方模块:
http://pypi.python.org/pypi/zope.interface
twisted的twisted\internet\interface.py里使用zope.interface
文档https://zopeinterface.readthedocs.io/en/latest/
设计模式:https://github.com/faif/python-patterns
抽象类
抽象类是一个特殊的类,它的特殊之处在于只能被继承,不能被实例化
为什么要有抽象类?
抽象类就是从一堆类中抽取相同的内容而来的,内容包括数据属性和函数属性
例如下面的例子
from abc import ABCMeta,abstractmethod
class Payment(metaclass=ABCMeta): # 抽象类 接口类 规范和约束 metaclass指定的是一个元类
@abstractmethod
def pay(self):pass # 抽象方法,python从语法上支持的规范类 class Alipay(Payment):
def pay(self,money):
print('使用支付宝支付了%s元'%money) class QQpay(Payment):
def pay(self,money):
print('使用qq支付了%s元'%money) class Wechatpay(Payment): # 继承了Payment类,就必须去实现被abstractmethod装饰的方法
def fuqian(self,money):
print('使用微信支付了%s元' % money) w = Wechatpay() # 实例化
Payment不需要pay的代码,只需要子类实现即可
Payment没有任何代码实现,必须要求子类有同名的方法名
总之:抽象类和接口类做的事情:建立规范
依赖倒置原则:
高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该依赖细节,细节应该依赖抽象。换言之,
要依赖接口编程,而不是针对实现编程
如上例:Payment是高层模块,Wechatpay是底层模块。Wechatpay只能依赖Payment,Payment不能依赖Wechatpay
Payment是抽象类,它定义了pay方法,具体实现的逻辑,它不需要写,有子类完成。
接口类
接口类:在 java 里面有interface的概念,它是一组功能的集合,接口的功能用于交互,所有的功能都是pubiic,即别的对象可操作
接口只定义函数,但不涉及函数实现,并且它的这些功能都是相关的。
但是在python中没有接口这样的关键字,但是可以实现类似的功能,它可以定义一个父类或者是基类,让它的子类强制使用相同函数名的方法
接口类:定义一个接口对继承类进行约束,接口里面有什么方法,继承类就必须有什么方法,接口中不能有任何功能代码
例如
from abc import ABCMeta,abstractmethod
class FlyAnimal(metaclass=ABCMeta): # 飞行
@abstractmethod
def fly(self):pass
@abstractmethod
def cal_flying_speed(self):pass
@abstractmethod
def cal_flying_height(self):pass
class WalkAnimal(metaclass=ABCMeta): # 走路
@abstractmethod
def walk(self):pass
class SwimAnimal(metaclass=ABCMeta): # 游泳
@abstractmethod
def swim(self):pass
class Tiger(WalkAnimal,SwimAnimal): # 老虎,继承走路和游泳
def walk(self):pass # 走路
def swim(self):pass # 游泳
class Monkey(WalkAnimal): # 猴子
def walk(self):pass
def climb(self):pass # 爬树
class Swan(FlyAnimal,WalkAnimal,SwimAnimal): # 天鹅,继承飞行,走路,游泳
def walk(self): pass
def swim(self): pass
def fly(self):pass # 飞行
def cal_flying_speed(self):pass # 计算飞行速度
def cal_flying_height(self):pass # 计算飞行高度
class Parrot(FlyAnimal): # 鹦鹉,继承飞行
def fly(self):pass
def cal_flying_speed(self): pass
def cal_flying_height(self): pass #实例化
Tiger()
Monkey()
Swan()
Parrot()
对于上面的例子,飞行的动物,陆地上面的东西,水中的动物都有各自的特点,不能使用一个抽象类限制其行为
接口隔离原则:使用多个专门的接口,而不使用单一的总接口。
那么接口类和抽象类该怎么说呢?
抽象类 是python中定义类的一种规范,用来约束子类中的方法的。被abstractmethod装饰的方法,子类必须实现,否则实例化时报错。
接口类 满足接口隔离原则,并且完成多继承的约束。如果不按照规范,在调用方法时,报错。
例如上面的例子,如果注释掉
# def cal_flying_height(self): pass
实例化:
k=Parrot()
调用方法:k.fly就会报错:TypeError: Can't instantiate abstract class Parrot with abstract methods cal_flying_height
3.2多态
多态是指一类事物有多种形态
class Payment:
def pay(self):pass class QQpay(Payment):
def pay(self, money):
print('使用qq支付了%s元'%money) class Wechatpay(Payment):
def pay(self, money):
print('使用微信支付了%s元'%money) def pay(pay_obj,money): # 统一支付方法
'''
:param pay_obj: 实例化对象
:param money: 金钱
:return: 使用xx支付了xx元
'''
pay_obj.pay(money) # 执行实例化对象的类方法pay qq = QQpay()
we = Wechatpay() pay(qq, 100)
pay(we, 200)
通过执行pay函数,传入不同的参数返回不同的结果,这就是多态
上面的例子可以进一步实现好的效果,将函数放到父类里面
class Payment:
@staticmethod
def pay(pay_obj,money): # 静态方法.需要通过类名+方法名来调用这个方法
'''
统一支付方法
:param pay_obj: 实例化对象
:param money: 金钱
:return: 使用xx支付了xx元
'''
pay_obj.pay(money) class QQpay(Payment):
def pay(self, money):
print('使用qq支付了%s元'%money) class Wechatpay(Payment):
def pay(self, money):
print('使用微信支付了%s元'%money) qq = QQpay()
we = Wechatpay() Payment.pay(qq, 100)
Payment.pay(we, 200)
python中自带多态效果
对于object类,python2中是封闭的,但是在python3中是开放的,也就是可以被继承
鸭子类型
Python崇尚鸭子类型,即‘如果看起来像、叫声像而且走起路来像鸭子,那么它就是鸭子’
在Linux系统中,一切皆文件的概念就是一个典型的例子,任何东西都可以看作有读和写两种属性
鸭子类型:不是通过具体的继承关系来约束某些类中的必须有那些方法名
是通过一种约定俗成的概念,来保证在多个类中,相似的功能叫相同的名字
3.3封装
封装,顾名思义就是将内容封装到某个地方,以便于被其他对象调用
class Foo:
def __init__(self,name,age): #创建对象的时候会自动执行init函数
self.name=name
self.age=age
obj1=Foo('xingchen',18) #将xingchen和18分别封装到obj1/self 的name和age属性中
self是一个形式参数,当执行obj1=Foo('xingchen',18)时,self等于obj1,内容被封装到了对象obj1中
调用时,可以通过对象直接调用被封装的内容,或者通过self间接调用被封装的内容
class Foo:
def __init__(self,name,age):
self.name=name
self.age=age
def detail(self):
print(self.name) #间接调用
print(self.age) obj1=Foo('xingchen',18)
obj1.detail() #直接调用
其他:扩展性
封装之后,内部的方法可以随时改变,并且可以保证你调用时使用的时同样的方法
day6--面向对象初识的更多相关文章
- day22.面向对象初识
1.面向对象引入 先来创建一个小游戏:人狗大战 # 定义一个狗 def Gog(name,blood,aggr,kind): dog = { 'name':name, 'blood':blood, ' ...
- python之面向对象初识
一.面向对象初识 1.结构上 面向对象分成两部分:属性.方法 class A: name = 'xiaoming' # 静态属性.静态变量.静态字段. def func1(self): # 函数.动态 ...
- python基础(17)继承类和面向对象初识
1.继承类 class Lm: money = 1000000 house = 5 def driver(self): print('会开车') class Mcb(Lm): def about_me ...
- day06_雷神_面向对象初识
day_06 递归函数 自己用自己.一般递归100多次,都没有解决的问题,放弃递归. count = 0 def func1(): global count count += 1 print(coun ...
- 《Python》 面向对象初识
一.面向对象初识: 1.结构上理解:类由两部分组成 class A: # class是类的关键字,类名首字母默认大写 name = 'alex' # 静态属性,静态变量,静态字段 def func ...
- python递归 及 面向对象初识及编程思想
递归 及 面向对象初识及编程思想 一.递归 1.定义: 在函数内部,可以调用其他函数.如果一个函数在内部调用自身本身,这个函数就是递归函数. (1)递归就是在过程或函数里调用自身: (2)在使用递 ...
- python基础学习笔记——面向对象初识
面向对象初识 python中一切皆对象. 类有两种: 新式类:在py3中所有类都是新式类 经典类:在py2中只有类本身继承了object类才叫做新式类,默认是经典类 class Person: cou ...
- Python中面向对象初识到进阶
面向对象初识到进阶 # 面向对象结构: # class 类名: # def __init__(self,参数1,参数2): # self.对象的属性1 = 参数1 # self.对象的属性2 = 参数 ...
- (转)Python之路,Day6 - 面向对象学习
本节内容: 面向对象编程介绍 为什么要用面向对象进行开发? 面向对象的特性:封装.继承.多态 类.方法. 引子 你现在是一家游戏公司的开发人员,现在需要你开发一款叫做<人狗大战> ...
- Python面向对象01 /面向对象初识、面向对象结构、类、self、实例化对象
Python面向对象01 /面向对象初识.面向对象结构.类.self.实例化对象 目录 Python面向对象01 /面向对象初识.面向对象结构.类.self.实例化对象 1. 面向对象初识 2. 面向 ...
随机推荐
- MapReduce案例:统计共同好友+订单表多表合并+求每个订单中最贵的商品
案例三: 统计共同好友 任务需求: 如下的文本, A:B,C,D,F,E,OB:A,C,E,KC:F,A,D,ID:A,E,F,LE:B,C,D,M,LF:A,B,C,D,E,O,MG:A,C,D,E ...
- Video to SDI Tx Bridge模块video_data(SD-SDI)处理过程
Video to SDI Tx Bridge模块video_data(SD-SDI)处理过程 1.Top Level Block Diagram of Video to SDI TX Bridge V ...
- C# .NET 4.5 将多个文件添加到压缩包中
string zipFilePath = @"d:\test.zip"; string file1 = @"D:\门头照处理\门店照片2018-3-19 wuxl\门店照 ...
- UML类图快速入门篇
1.关联 1.1双向关联: C1-C2:指双方都知道对方的存在,都可以调用对方的公共属性和方法. 在GOF的设计模式书上是这样描述的:虽然在分析阶段这种关系是适用的,但我们觉得它对于描述设计模式内的类 ...
- VS2010与Qt5.1.0集成(非源码方式)
早就听说qt可以集成到VS中,就是一直没尝试过.一直在使用qt creator,也没觉得它有什么不好.可最近VS用多了,我发现一个qt creator中很不好的毛病,就是代码自动完成时,creator ...
- Azure SQL 数据库仓库Data Warehouse (2) 架构
<Windows Azure Platform 系列文章目录> 在上一篇文章中,笔者介绍了MPP架构的基本内容 在本章中,笔者给大家介绍一下Azure SQL Data Warehouse ...
- 数据仓库专题(5)-如何构建主题域模型原则之站在巨人的肩上(二)NCR FS-LDM主题域模型划分
一.前言 分布式数据仓库模型的架构设计,受分布式技术的影响,很多有自己特色的地方,但是在概念模型和逻辑模型设计方面,还是有很多可以从传统数据仓库模型进行借鉴的地方.NCR FS-LDM数据模型是金融行 ...
- 【IIS错误】IIS各种错误
IIS简介 当用户试图通过HTTP或文件传输协议(FTP)访问一台正在运行Internet信息服务 (IIS)的服务器上的内容时,IIS返回一个表示该请求的状态的数字代码.该状态代码 记录在IIS日志 ...
- P1601高精度加法
传送门 虽然本题一本通上有,但是一本通不是万能的,这道题就漏掉了进位(所以这告诉我们加法进位很重要) 直接上修改后的题解 #include<iostream> #include<cs ...
- java设计模式-责任链
背景:要把<script>等<>html标签替换掉:把敏感词屏蔽或者替换等: 1.刚开始可能这么写: public class Main { public static voi ...