Python基础(十一)-面向对象
三种编程范式:
1、函数式编程:函数指数学意义上的函数
由于命令式编程语言也可以通过类似函数指针的方式来实现高阶函数,函数式的最主要的好处主要是不可变性带来的。没有可变的状态,函数就是引用透明(Referential transparency)的和没有副作用(No Side Effect)。 一个好处是,函数即不依赖外部的状态也不修改外部的状态,函数调用的结果不依赖调用的时间和位置,这样写的代码容易进行推理,不容易出错。这使得单元测试和调试都更容易。 不变性带来的另一个好处是:由于(多个线程之间)不共享状态,不会造成资源争用(Race condition),也就不需要用锁来保护可变状态,也就不会出现死锁,这样可以更好地并发起来,尤其是在对称多处理器(SMP)架构下能够更好地利用多个处理器(核)提供的并行处理能力
2、面向过程编程:
3、面向对象编程:
面向对象编程--类与对象
类与对象初识
类:具有相同属性的事物的集合,只是一个抽象概念(Python中将具有相同数据属性和函数属性(方法)的对象集合的抽象定义为一个类)
对象:就是一个具体存在的事物(Python中由类实例化得到的就叫做一个对象(实例))
实例化:由类生成一个对象(实例)的过程就叫实例化
class China:#类名
"this is China" #类的文档字符串 capital=Beijing #类的数据属性
def __init__(self,a,b): #类的初始化函数(定义对象的数据属性)
self.a=a
self.b=b
def func(self): #类的函数属性(默认返回None,也可以加return)
pass obj=China(a,b) #实例化 #从结构上类似函数的定义 实例化的过程实质就是执行类的初始化函数,得到一个数据属性字典 查看所有属性:dir(obj) 返回列表,只有属性名
查看类的属性字典:print(China.__dirt__) obj.func() # 对象调用类方法 Python默认会将obj传到第一个位置参数,而类调用方法则没有
China.func(obj) # 类调用方法,如果有参数就必须传参
# 对象可以调用类的所有属性,但类则无法调用对象里的属性(类似函数的作用域) ## 类和对象调用方法都是类名(对象名).函数名,没有点的调用,直接写个变量名,那就是类外的变量
分类:
Python2中有经典类与新式类之分,而Python3中则统一按照新式类处理(之后类的优先顺序会具体看到)
class a: #经典类
pass class a(父类):#新式类 二者区别就在有无继承父类
pass
以上是Python2中类,Python3中都是新式类,默认继承object类,继承顺序是根据c3算法,可以通过__mro__方法查看
类与对象的属性操作(增、删、改、查)
#类属性又称为静态变量,或者是静态数据。这些数据是与它们所属的类对象绑定的,不依赖于任何类实例。
#如果你是一位Java或C++程序员,这种类型的数据相当于在一个变量声明前加上static关键字。
class Chinese:
country='China'
def __init__(self,name):
self.name=name def play_ball(self,ball):
print('%s 正在打 %s' %(self.name)) def say_word(self,word):
print('%s 说 %s' %(self.name,word)) #查看类属性
print(Chinese.country) #修改类属性
Chinese.country='CHINA'
print(Chinese.country) #删除类属性
del Chinese.country #增加类属性
Chinese.Country='China'
Chinese.location='Asia'
print(Chinese.__dict__) #类的数据属性增删改查与函数属性是一样的
Chinese.say_word=say_word
print(Chinese.__dict__)
alex_obj=Chinese('alex')
Chinese.say_word(alex_obj,'我是一只来自北方的狼狗')
类属性操作
class Chinese:
country='China'
def __init__(self,name):
self.name=name def play_ball(self,ball):
print('%s 正在打 %s' %(self.name,ball)) p1=Chinese('alex')
print(p1.__dict__) #查看对象属性 (如果对象没有则会调用类,类也没有就报错)
print(p1.country) #修改、增加
p1.country='A' 这是赋值,如果有这个属性就是修改,没有就是增加
print(p1.__dict__) #此时就是增加
p1.country='B' #此时就是修改 #删除
del p1.country #没有该属性会报错
对象属性操作
对象与类的动态添加方法
class Student(object):
pass def set_age(self,age): #定义一个函数作为实例方法
self.age=age from types import MethodType
s=Student()
s.set_age=MethodType(set_age,s) #给实例绑定一个方法==> 类具有该方法吗?或者说其他实例能调用该方法吗?
s.set_age()
print(s.age) # 直接绑在实例s上 s1=Student()
s1.set_age()
print('实例s1--',s1.age) #显然其他实例没有该方法 ############### File "E:/PyCharm/Personal_practice/suanfa/paixu.py", line , in <module>
s1.set_age()
AttributeError: 'Student' object has no attribute 'set_age'
给实例
注意:
1.类实例化得到对象,实质就是执行了类的__init__函数,得到一个数据属性字典,所有说对象没有函数属性,但可以调用类的函数属性
2.类和对象调用属性使用 类名(对象).属性名,直接写个属性名就是调用类外的变量,切记 !
age=10000000000
class Chinese:
country='China'
age=10
l=[] def __init__(self,name):
self.name=name def play_ball(self,ball):
print('%s 正在打 %s' %(self.name,ball)) p1=Chinese('wupeiqi') #实例化
p2=Chinese('alex') p1.age=100 #给对象的age数据属性赋值,没有该属性的话就是增加
p2.age=101 print(p1.age,p2.age)
print(age) #这就是类外的变量调用
print(Chinese.age) p1.l.append('p1') #对p1.l列表进行追加,没有就是对类列表追加
p2.l.append('p2') #同上,操作对象是列表
print(Chinese.l)
print(p1.l)
print(p2.l)
3.对象调用函数属性,Python会自动在第一个位置参数加上对象本身,类则没有,切记 !
静态属性、类方法、静态方法
初衷都是为了实现类直接能调用方法(本来必须传个对象)
静态属性没什么卵用,返回个property object
类方法可以接收返回值,方法内无法调用对象的数据属性self.a,可以调用类的数据属性cls.b
静态方法也可以接收返回值,方法内既不可以调用类的数据属性也不可以调用对象数据属性,而且它不像以上两种方法必须有个位置参数(self,cls)
三者比较结果:类方法相对灵活些
class Room:
x=1
y='hei'
def __init__(self,name,owner,length,wide,high):
self.name=name
self.owner=owner
self.length=length
self.wide=wide
self.high=high
@property #静态属性 给类调用方法,对象也可以调用该方法
def cal_area(self):
# print('%s 住的 %s 面积是 %s'%(self.owner,self.name,self.length*self.wide))
return self.length*self.wide r1 = Room('cesuo', 'alex', 10, 10, 10)
print(r1)
print(Room.cal_area) #感觉没什么卵用 得到一个proprety object so能干嘛?
r1.cal_area=10
print(r1.cal_area) #对象照样用
print(r1.__dict__) def cal_volume(self):
print('%s住的%s体积是%s'%(self.owner,self.name,self.length*self.wide*self.high)) @classmethod #类方法:专门给类直接调类的函数属性使用(这是存在的初衷),(因为之前调用必须传入实例)与实例无关,
def fuck(cls,a):
cls.a=a
return a
return cls.y #可以调用类的数据属性
return self.length*self.wide #类方法内无法调用初始化函数中对象数据属性 r1 = Room('cesuo', 'alex', 10, 10, 10)
print(r1.fuck())
l=Room.fuck(1) #类调用之后能得到返回值 这个就有些用了
print(l) @staticmethod
def yoyo(a,b,c): #可以没有位置参数,不像以上两种方法,必须传个位置参数self,cls
# print(a,b,c)
# return self.name #方法内无法调用对象数据属性
# return x #无法调用类的数据属性
return a
print(Room.yoyo(1,2,3))
一个例子全部搞定
继承
继承有两种用途:
一:继承基类的方法,并且做出自己的改变或者扩展(代码重用)
二:声明某个子类兼容于某基类,定义一个接口类Interface,接口类中定义了一些接口名(就是函数名)且并未实现接口的功能,子类继承接口类,并且实现接口中的功能
组合
类跟类之间没有共同点,但之间有关联或包含关系,比如老师属于某个学校,学生属于某个学校,课程属于某个老师
比如手、脚、头、躯干,都属于身体(或者说组成身体)
用途:
1、做关联
2、小的类组成大的类
class Hands:
pass
class Feet:
pass
class Head:
pass
class Trunk:
pass
class Body:
'this is body'
def __init__(self,name,hand,feet,head,trunk):
self.name=name
self.hand=Hands
self.foot=feet
self.head=Head
self.trunk=Trunk
事例1
class School:
def __init__(self,name,addr):
self.name=name
self.addr=addr
def tell_info(self):
print('School(%s,%s)' %(self.name,self.addr)) class Course:
def __init__(self,name,price,period,school):
self.name=name
self.price=price
self.period=period
self.school=School #此处就是组合的体现(与上面的School相关联) #其实关联的实际意义就体现在数据的重复利用,比如已经创建了两个School实例,再建Course实例的时候就不需要再手动传输school,只需在已经创建的两个School实例中选择即刻
事例2
接口与归一化设计
class Interface:#定义接口Interface类来模仿接口的概念,python中压根就没有interface关键字来定义一个接口。
def read(self): #定接口函数read
pass def write(self): #定义接口函数write
pass class Txt(Interface): #文本,具体实现read和write
def read(self):
print('文本数据的读取方法') def write(self):
print('文本数据的读取方法') class Sata(Interface): #磁盘,具体实现read和write
def read(self):
print('硬盘数据的读取方法') def write(self):
print('硬盘数据的读取方法') class Process(Interface):
def read(self):
print('进程数据的读取方法') def write(self):
print('进程数据的读取方法')
接口
实践中,继承的第一种含义意义并不很大,甚至常常是有害的。因为它使得子类与基类出现强耦合。
继承的第二种含义非常重要。它又叫“接口继承”。
接口继承实质上是要求“做出一个良好的抽象,这个抽象规定了一个兼容接口,使得外部调用者无需关心具体细节,可一视同仁的处理实现了特定接口的所有对象”——这在程序设计上,叫做归一化。
抽象类
跟接口类类似,不同的地方是抽象类只能继承,不能实例化
#_*_coding:utf-8_*_ #一切皆文件
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)
Python中实现抽象类
子类调用父类方法super
class A:
def a(self):
print('A.a') def d(self):
print('A.d') class B:
def b(self):
print('B.b') class C(A,B):
def a(self):
super().a()
print('C.a') def c(self):
print('C.c') def d(self):
print('C.d') class D(C):
def c(self):
print('D.c') print(D().a())
super
注意:使用super调用的所有属性,都是从MRO列表当前的位置往后找,千万不要通过看代码去找继承关系,一定要看MRO列表
当然也可以使用 父类名.父类方法() 的方式直接写在子类代码中,耦合性太强
Python基础(十一)-面向对象的更多相关文章
- Python 基础 四 面向对象杂谈
Python 基础 四 面向对象杂谈 一.isinstance(obj,cls) 与issubcalss(sub,super) isinstance(obj,cls)检查是否obj是否是类 cls ...
- (转)Python成长之路【第九篇】:Python基础之面向对象
一.三大编程范式 正本清源一:有人说,函数式编程就是用函数编程-->错误1 编程范式即编程的方法论,标识一种编程风格 大家学习了基本的Python语法后,大家就可以写Python代码了,然后每个 ...
- 自学Python之路-Python基础+模块+面向对象+函数
自学Python之路-Python基础+模块+面向对象+函数 自学Python之路[第一回]:初识Python 1.1 自学Python1.1-简介 1.2 自学Python1.2-环境的 ...
- 二十. Python基础(20)--面向对象的基础
二十. Python基础(20)--面向对象的基础 1 ● 类/对象/实例化 类:具有相同属性.和方法的一类人/事/物 对象(实例): 具体的某一个人/事/物 实例化: 用类创建对象的过程→类名(参数 ...
- python基础,函数,面向对象,模块练习
---恢复内容开始--- python基础,函数,面向对象,模块练习 1,简述python中基本数据类型中表示False的数据有哪些? # [] {} () None 0 2,位和字节的关系? # ...
- Day7 - Python基础7 面向对象编程进阶
Python之路,Day7 - 面向对象编程进阶 本节内容: 面向对象高级语法部分 经典类vs新式类 静态方法.类方法.属性方法 类的特殊方法 反射 异常处理 Socket开发基础 作业:开发一个 ...
- Python基础7 面向对象编程进阶
本节内容: 面向对象高级语法部分 经典类vs新式类 静态方法.类方法.属性方法 类的特殊方法 反射 异常处理 Socket开发基础 作业:开发一个支持多用户在线的FTP程序 面向对象高级语法部分 经典 ...
- Python高手之路【十一】python基础之面向对象
创建类和对象 面向对象编程是一种编程方式,此编程方式的落地需要使用 “类” 和 “对象” 来实现,所以,面向对象编程其实就是对 “类” 和 “对象” 的使用. 类就是一个模板,模板里可以包含多个函数, ...
- Python之路【第六篇】python基础 之面向对象进阶
一 isinstance(obj,cls)和issubclass(sub,super) isinstance(obj,cls)检查是否obj是否是类 cls 的对象 和 issubclass(su ...
- Python之路【第六篇】python基础 之面向对象(一)
一.三大编程范式 1.面向过程编程 2.函数式编程 3.面向对象编程 二.编程进化论 1.编程最开始就是无组织无结构,从简单控制流中按步写指令 2.从上述的指令中提取重复的代码块或逻辑,组织到一起(比 ...
随机推荐
- IO多路复用之select
IO多路复用之select总结 1.基本概念 IO多路复用是指内核一旦发现进程指定的一个或者多个IO条件准备读取,它就通知该进程.IO多路复用适用如下场合: (1)当客户处理多个描述字时(一般是交 ...
- cocos2d-x 3.0 cocos run Couldn't find the gcc toolchain.
出现这个错误是NDK_ROOT环境变量没有设置好,要么设置错了,要么没有重启终端(也就是环境变量还没有生效).我就是因为没有重启终端坑了一个晚上,我只能帮你到这了,玩cocos2d-x 3.0的朋友, ...
- 项目检出JRE问题(Unbound classpath container: 'JRE System Library [JavaSE-1.7]' in project 'idweb')
分类: java 技术2014-07-31 16:51 9864人阅读 评论(13) 收藏 举报 项目从SVN检出到工作空间后报了很多错误,其中很明显就是一些jar的问题,没有相关的jar或版本问题, ...
- 开发一个微信小程序教程
一.注册小程序账号 1.进入微信公众平台(https://mp.weixin.qq.com/),注册小程序账号,根据提示填写对应的信息即可. 2.注册成功后进入首页,在 小程序发布流程->小程序 ...
- Js 获取当前月的天数
function getDays() { //构造当前日期对象 var date = new Date(); //获取年份 var year = date.getFullYear(); //获取当前月 ...
- SAP CRM 高效调试方法
调试,是程序开发中的基本技巧.快速定位错误消息在源代码中的位置,对发现和解决程序中的问题有着重要的意义.在SAP CRM中,错误消息通常在前台的Web Client页面中展示,应该怎样定位相关代码的位 ...
- Docker集群实验环境布署--swarm【1 架构说明】
在读完<Docker技术入门与实践>这本书后,基本上已对Docker了有一些入门的理解,以及我们为什么要使用Docker 答:我们发现在实际工作中,通过openstack一旦把一个VM创建 ...
- Centos 7 意外断电如何处理
拔U盘的时候,不小心碰到了主机上的开机键-- 还好默认的响应动作是睡眠-- 还不知道 CentOS 怎么样应对意外断电呢?!
- SublimeText快捷键
在我做了一次包含一些现场编码的演示后,一些观众问我是如何操作这么快.当然这里没有唯一的答案,答案是一堆简单的快捷键和大量的实践的组合.为了回应那些询问,我觉得有必要看看我每天想都不用想且使用的快捷键. ...
- GTK+2.0学习——code::block使用
在之后使用中会慢慢去完善~~ 一.编码设置 1.设置文件编码:setting->editor->如图 2.设置编译时的编码(记住二者要统一):setting->compiler-&g ...