#面向对象的三大特性

1 继承(上一章的内容)

2 多态

python本身就是多态的

3 封装

# 多态

#不同类的实例化对象,调用同一个方法(执行的逻辑不同),而不用考虑他们具体的类,例如:

字符对象s和列表对象l都调用了同一个__len__的方法(都继承于他们的父类即str和list),却不需要考虑他们属于不同类

s = str(111)          #相当于str这个类将数字1传入,实例化出来一个字符串对象
l = list('abc')       #相当于list这个类将'abc'传入,实例化出来一个列表对象
len(s)                #相当于字符对象s调用了字符类下的一个__len__的方法,即s.__len__()
print(s.__len__())
len(l)                #同理
print(l.__len__())

print(dir(str))     #里面有__len__print(dir(list))    #里面有__len__

#其实len函数相当于

def len(obj) :obj.__len__()

#多态反应的是一个执行时候的状态

#再举一个例子加深理解

class H20 :def __init__(self,temperature):self.temperature = temperaturedef trans(self):if self.temperature < 0 :print('freezing')if self.temperature > 0 and self.temperature < 100 :print('flowing')if self.temperature > 100 :print('boiling')
class liquid(H20):pass
class solid(H20) :pass
s1 = liquid(110)
s2 = liquid(20)
s1.trans()                          #都调用了同一种方法,却属于不同类
s2.trans()
def trans(obj) :             #其实这里定义了这个函数,才叫真正的多态。当你不调用时,没差别;而当你调用这个函数时,不管是什么类实例化出来的对象,都能执行同一套方法。obj.trans()
trans(s1)
trans(s2)

到此,我们也就明白到底什么是多态了:不同子类继承了父类的共同的函数属性,并且不同子类实例化出来的不同对象都调用父类的函数属性,这种动态的过程,就叫做多态。其实多态的基础就是就是继承,就是一种继承的体现方式。

换句话说,继承解决的是代码重用的问题,而把这个优势体现出来的方式就叫做多态,即父类定义的函数,要考虑到多个子类的继承问题(需要是有意义的)

#封装

#封装是一种思想(本质就是要区别内外,内部就是类里面,外部就是调用者;外部调用者无需知道内部逻辑),装就是把东西都放到一个袋子里,封就是把袋子封口,将东西隐藏起来,也就是定义一个类,往里面定义数据属性和函数属性,这就叫装(装到了__dict__里)

#那么什么是封呢?

(类中定义私有的,只想让其在类内部被访问,外部不需访问,但需要给外部定义一个接口函数,用于外部访问内部)

1 在一个py文件里定义的类,由其他py文件调用,其实就已经有隐藏的含义了,调用者并不知道其内部逻辑,只需要用就行

2 通过python约定俗成的命名方法来命名,达到隐藏的效果:

3 为封装到内部的逻辑提供一个外部访问的接口

# _开头的变量如 _abc 代表这个属性不该被外部调用者调用

class A :_b = '你不该在外部调用这个数据属性'def __init__(self):pass
a = A()
print(a._b)                             #还是能调用到这个_b,因为这只是文字上的约束,python并没有内部逻辑帮你阻止调用#但你看到_开头的就要明白,这个属性是不该被你调用的

#__开头的变量如__abc (__abc__这样末尾有__的不算),python会给你自动重命名为_类名__abc

class A :__b = '你调用不到我,会报错'def __init__(self):print('但我可以在这里调',self.__b)def C(self):                  #接口函数(访问函数)print(self.__b,'内部就能调用')
a = A()
# print(a.__b)                             #调用不到__b,会报错 ,因为以及被python自动重命名为_A__b了,可以在__dict__中找到
print(A.__dict__)
print(a._A__b)
a.C()                          #外部调用者通过调用接口函数,访问到了在内部被封装的属性

#注意事项:

要把什么变量做成私有的需要深思熟虑(不然后期只能通过不断的添加接口函数来弥补,在一个项目里把私有的变量名再改回去是不现实的)

 #来几个真正封装的例子

class cal_area :def __init__(self,name,width,length):self.name = nameself.__width = widthself.__length = lengthdef result(self):print('%s的面积为%s平方米' %(self.name,self.__length*self.__width))def port(self):return self.__width,self.__length
s = cal_area('home',100,100)
s.result()
print(s.port())                             #没法直接调用内部私有的__width和__length,只能通过新写的接口函数(也叫访问函数)来调用

#反射(又称自省)

 #主要是指程序可以访问、检测和修改它本身状态或行为的一种能力。

四个可以实现反射的函数(适用于类和对象):

hasattr(object,name):判断对象中有没有一个叫做name的方法或属性(数据属性或函数属性),

或者换句话说,能不能调用到name的方法或属性,返回bool值.                    注意name是个字符串!

a = 'abc'
print(hasattr(a,'__len__'))                #可以传入实例化对象
print(hasattr(str,'__len__'))              #也可以传入一个类
class A:def __init__(self,name):self.__name = namedef __test(self):pass
print(hasattr(A,'__test'))                 #hasattr检测的是能被调用的方法或属性,这里做了封装所以没找到

getattr(object,name,default=None):获取对象或者类中能被调用的方法或者属性

a = 'abc'
b = getattr(a,'__len__')                                #在实例化对象a中,获取到叫做'__len__'的属性,并且可以调用.(没有则会报错)
d = getattr(a,'adflkj','如果找不到,得到这里的值')      #这样写找不到也不会报错
e = getattr(a,'adsf',default=None)
print(b())
print(d)
c = getattr(str,'__len__')
print(c(a))
#其实getattr(object,name)就等于object.name

setattr(object,key,value):给对象或类设置方法或属性

class A:def __init__(self,name):self.name = namedef test(self):pass
a = A('abc')
setattr(a,'name0','ssy')
print(a.__dict__)
#相当于直接
a.name = 'alex'
print(a.__dict__)
#也可传入函数属性
def test(self) :print(self.name)
setattr(A,'test',test)
a.test()

delattr(object,key):删除对象或类的属性或方法,相当于 del A.key

class A:def __init__(self,name):self.name = namedef test(self):pass
a = A('abc')
delattr(a,'name')
#相当于直接
del a.name
print(a.__dict__)

 #反射的好处:

当多人开发一个项目时候,你需要调用别人负责实现的的类,但是对方没实现,甚至都没定义这时候怎么办?

难道要等到他实现了通知你,你才开始写代码么?这时候就可以用hasattr来进行一个判断

from XXX import A
a = A('abc')       #调用别人的类来实例化
if hasattr(a,'你要调用的方法') :b = getattr(a,'你要调用的方法')b()            #运行调用的方法
#如果不存在,就接着下面的逻辑

这样,当你调用的类不存在时,就跳过;存在的时候即调用;你这段调用的代码其实就已经写好了,不论这个类有没有被实现。

换句话说就是你不用等别人实现这个类,再回过头来写这个调用逻辑了。

#动态导入

#以一个字符串的名字的形式导入模块

#动态导入,可以导入字符串名字的模块。但是无论你调用多少层,总是获取最顶层
a = __import__('module_test.bin')       #导入相当于执行了一遍文件.
print(a)                                #获取的不是你导入的最低层bin,而是顶层module_test
a.bin.test()                            #所以得这么才能调用到,但是为了能调用到,__import__里还是得写到最低层,即'module_test.bin'
#导入的过程相当于执行了一次文件,下面拿以前的导入方式来距离
from module_test import bin
bin.test()                              #bin下定义的函数得通过bin这个类调用,不能直接test()
#或者直接把模块里的所有东西导入到当前,那就可以直接test()调用了
from module_test.bin import *           # * 跟linux里的通配符一个意思
test()
#但是这种用*的方法没法导入_开头的函数
_test()                                 #没找到这个函数
#不过python没有在真正逻辑层面上限制你调用,你可以这么调_test
from module_test.bin import test,_test
_test()
#或者用__import__调用也可以
a.bin._test()#另一种更好的方法动态导入
import importlib
a = importlib.import_module('module_test.bin')
a.test()
a._test()

 #为什么这里要讲动态导入呢?因为动态导入就是基于反射做的。而模块其实就是一个类

比如 importlib.import_module('module_test.bin'),相当于从importlib这个类里找到一个import_module方法;

这个方法能从当前类(文件夹就是一个类)下找到module_test这个类,再从中找到bin这个类

这也就解释了为什么pycharm创建文件夹的时候,会生成一个__init__的文件,并且自动执行,其实它就是用来实例化出对象(文件夹里的文件)的

# __getattr__ 、 __setattr__ 、 __delattr__

(注意:形如  __XXX__ 都是类的内置方法,当不自己设置__XXX__的时候用内置的,设置跟他名字一样的__XXX__则用你设置的)

(常用)#__getattr__ : 当对象或类调用不存在的方法时,会自动运行类下的__getattr__方法 (如果不像下面自己设置__getattr__则调用内置的结果是输出报错信息到屏幕)

(不常用)#__delattr__: 类或对象在删除属性时,会自动运行__delattr__

(不常用)#__setattr__: 类或对象在设置属性时,会自动运行__setattr__

class Foo :name = 'abc'def __init__(self,x):self.x = xdef __getattr__(self, item):print('__getattr__被执行')def __delattr__(self, item):print("__delattr__被执行")def __setattr__(self, key, value):print("__setattr__被执行")# self.key = value              #不能这么设置属性,因为这里一设置又会触发__setattr__的执行,然后再设置,无限循环self.__dict__[key] = value      #这样设置才对
a = Foo(1)
a.adfdaf                                #类或对象调用不存在的属性时,会自动运行__getattr__
del a.name                              #类或对象在删除属性时,会自动运行__delattr__
a.name1 = 'cba'                         #触发__setattr__

转载于:https://www.cnblogs.com/Matrixssy/p/10911952.html

Python基础 ( 十 ) —— 面向对象(多态、封装、反射、动态导入)相关推荐

  1. python基础(面向对象(封装、私有化封装))

    封装 封装(encapsulation)指的是向外部隐藏不必要的细节.这听起来有点像多态(无需知道对象的内部细节就可使用它).这两个概念很像,因为它们都是抽象的原则.它们都像函数一样,可帮助你处理程序 ...

  2. Python基础十五:面向对象编程四:高级特性

    Python基础十五:面向对象编程四:高级特性 Python基础系列内容为学习廖雪峰老师Python3教程的记录,廖雪峰老师官网地址:廖雪峰Python3教程 Author:yooongchun Em ...

  3. 【Python基础】面向对象封装 案例(二)

    目录 案例二 1.首先开发 枪类 2.接着开发 士兵类 3.开发 开火类. 案例一在这里: [Python基础]面向对象封装 案例(一) 案例二 仍然是一步一步开发.同时,下面的第3小步是完整代码,亦 ...

  4. Python成长之路【第九篇】:Python基础之面向对象

    一.三大编程范式 正本清源一:有人说,函数式编程就是用函数编程–>错误1 编程范式即编程的方法论,标识一种编程风格 大家学习了基本的Python语法后,大家就可以写Python代码了,然后每个人 ...

  5. (转)Python成长之路【第九篇】:Python基础之面向对象

    一.三大编程范式 正本清源一:有人说,函数式编程就是用函数编程-->错误1 编程范式即编程的方法论,标识一种编程风格 大家学习了基本的Python语法后,大家就可以写Python代码了,然后每个 ...

  6. 5.Python基础之面向对象

    文章目录 Python基础之面向对象 面向对象的三大特性 类和对象的关系 类的组成 类的书写规则 实例化对象 检测类和对象的成员 类和对象成员的操作 类成员操作 对象成员操作 关于self 封装特性 ...

  7. python基础之面向对象编程

    python基础之面向对象编程 面向对象编程思想 面向对象是一门编程思想,编程思想仅仅是一门思想,与任何技术无关 核心是对象两字,对象可以理解为特征与技能的结合体 基于该编程思想编写程序,就好比创造世 ...

  8. Python基础_07_面向对象1

    python基础7_面向对象1 文章目录 python基础7_面向对象1 一.面向对象:类和对象.魔法方法 1. 面向对象编程概述 1.1[了解]面向过程和面向对象的区别 1.2[知道]类和对象介绍 ...

  9. Python基础十九:多进程

    Python基础十九:多进程 Python基础系列内容为学习廖雪峰老师Python3教程的记录,廖雪峰老师官网地址:廖雪峰Python3教程 Author:yooongchun Email:yooon ...

最新文章

  1. 基于 Android NDK 的学习之旅-----资源释放
  2. JS中IE与W3C不同的地方
  3. java 根据类名示例化类_如何使用示例从Java中的类路径加载资源
  4. 数组copyWithin()方法以及JavaScript中的示例
  5. 视频过大怎么压缩变小
  6. 微信小程序开发入门与实践
  7. iSpiik产品说:谈谈小程序直播-数据背后几个思考
  8. 头条白板面试_让我们谈谈白板面试和可能的替代方法
  9. Client can't access Jboss server, the port is not accessable.
  10. 行为识别阅读笔记(paper + parted code):Beyond Frame-level CNN Saliency-Aware 3-D CNN with LSTM for Video Acti
  11. 3、微信小程序-通信
  12. 在Windows上挂载磁盘为非445端口的SAMBA服务(原创)
  13. 优盘复制进来为空_为什么复制后文件夹u磁盘为空
  14. 数学知识整理:二重积分
  15. 【历史上的今天】10 月 6 日:互联网先驱诞生日;莲花公司宣布上市
  16. 贪心之最大相容子集合问题
  17. docker ——安装tomcat
  18. 关于大一新生的一些话
  19. 我认为这种计算机卖的很好英语翻译,英语翻译
  20. C#读写调整UVC摄像头画面-饱和度

热门文章

  1. Elasticseach 从零开始学习记录(一) - 单实例环境搭建
  2. 为制造业构建Teams Power App 3:创建制造商UI
  3. (四)训练用于口罩检测的YOLOv5模型
  4. 微软推出新编程语言 Bosque,超越结构化程序设计
  5. 在IIS中调试ASP.NET Core应用程序
  6. ajax jinja,在向Flask发出jQuery AJAX请求后渲染Jinja
  7. 前端悬浮窗效果_web前端入门到实战:css过渡和动画解析文
  8. 如何访问云端的tcpserver_Swoole: TcpServer+SocketServer+EMQTT组合,实现基础设备控制
  9. bootstrap表单拖拽生成器插件_web前端常用插件、工具类库汇总,新手必收藏!!!...
  10. python函数的内涵_python内涵段子文章爬取