Python面向对象编程Day 26部分知识点
五大数据类型:整型、字符串、列表、元组、字典
多态
多态概念指出了对象如何通过他们共同的属性和动作来操作和访问,而不需考虑他们具体的类、多态表明了动态(又名:运行时)绑定的存在,允许重载及运行时类型确定和验证。多态是继承的改变和扩展的实现机制,即调用不同的类实例化得对象下的相同方法,实现的过程不一样。
(python中的标准类型就是多态概念的一个良好示范)
封装
本质是要明确的区分内外。python约定(并不是实际的限制)单下划线开头的变量为隐藏变量。python会给双下划线开头的变量重命名(前加上'_classname')
第一个层面的封装:类就是麻袋,这本身就是一种封装
第二个层面的封装:类中定义私有的,只在类的内部使用,外部无法访问(停留在约定层面)
第三个层面的封装(真正的封装):明确区分内外(内部可以直接使用,外部则不能),内部的实现逻辑,外部无法知晓,并且为封装到内部的逻辑提供一个访问接口(访问函数 )给外部使用
通过继承+多态在语言层面支持了归一化设计。不用面向对象的语言即class一样可以做归一化(比如泛文件概念),一样可以封装,只是使用面向对象语言可以直接用语言元素显示声明而已。
反射/自省
主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(也叫自省)。
四个可以实现自省的函数(适用于类和对象):
hasattr(object,name,default=none)判断object中有没有一个name字符串对应的方法或属性,没有打印false
getattr(object,name,default=none)没有则报错,如果default=none位置处写一个错误提示字符串,就不会报错了,而是输出这个字符串
setattr(object,key(字符串形式),value )添加或修改
delattr(object,key(字符串形式))相当于 del object.key
动态导入模块
底层是基于反射去做的。
import dic
m=__import__('dic') #字符串形式导入模块,只能导入最*模块
print(m) #module 'm1'
module_t=__import__('m1.t') #实际引入的是m1
module_t.t #是在调用m1文件夹中的t文件
from m1.t import * #标红是因为没在环境变量中 导入不了函数名以下划线开头的函数
import importlib
m=importlib.import_module('m1.t') #这回直接定位到t
print(m) #module 'm1.t'
m.test1()调用t文件下的test1函数
双下划线开头(内置方法)的attr方法
属性不存在时触发__getattr__函数(最重要,用的比较多)
删除一个对象的属性时会触发__delattr__函数
__setattr__(self,key,value)设置时触发 函数内self.key=value这样会触发无限递归 应该这样设置self.__dict__[key]=value操作底层字典(del 什么.什么也会导致无限递归) 最后执行设属性操作可通过 f=函数名(参数) f.key=value这样设定
print(函数名.__dict__)和print(dir(函数名))都是用来打印属性方法的,但是后者更全面
1 class foo: 2 def __init__(self,name): 3 self.name=name 4 def __getattr__(self, item): 5 print('你找的属性【%s】不存在' %item) 6 def __setattr__(self, k,v): 7 print('执行setattr',k,v) 8 if type(v) is str: 9 print('开始设置') 10 # self.k=v #触发__setattr__ 11 self.__dict__[k]=v.upper() 12 else: 13 print('必须是字符串类型') 14 def __delattr__(self, item): 15 print('不允许删除属性【%s】' %item) 16 # print('执行delattr',item) 17 # del self.item 18 # self.__dict__.pop(item) 19 20 f1=foo('alex')#触发__setattr__ 21 # f1.age=18 #触发__setattr__ 22 # print(f1.__dict__) 23 # print(f1.name) 24 # print(f1.age) 25 # print(f1.gender) 26 # print(f1.slary) 27 print(f1.__dict__) 28 del f1.name 29 print(f1.__dict__)
输出
执行setattr name alex
开始设置
{'name': 'alex'}
不允许删除属性【name】
{'name': 'alex'}
二次加工标准类型(包装)
授权是包装的一个特性,包装一个类型通常是对已存在的类型的一些定制,修改或删除原有产品功能,其它的保持原样。授权的过程即所有更新的功能都是由新类的某部分处理,但已存在的功能就授权给对象的默认属性。
包装通过继承加派生实现。
实现授权的关键点就是覆盖__getattr__方法。
str()工厂函数 str一个类
包装标准类型
1 class list(list): 2 def append(self, p_object): 3 if type(p_object) is str: 4 # self.append(p_object) 5 super().append(p_object) 6 else: 7 print('只能添加字符串类型') 8 9 def show_midlle(self): 10 mid_index=int(len(self)/2) 11 return self[mid_index] 12 13 14 # l2=list('hell oworld') 15 # print(l2,type(l2)) 16 17 l1=list('helloworld') 18 # print(l1,type(l1)) 19 # print(l1.show_midlle()) 20 l1.append(1111111111111111111111) 21 l1.append('sb') 22 print(l1)
输出
只能添加字符串类型
['h', 'e', 'l', 'l', 'o', 'w', 'o', 'r', 'l', 'd', 'sb']
组合的方式完成授权
1 import time 2 class filehandle: 3 def __init__(self,filename,mode='r',encoding='utf-8'): 4 # self.filename=filename 5 self.file=open(filename,mode,encoding=encoding) 6 self.mode=mode 7 self.encoding=encoding 8 def write(self,line): 9 print('------------>',line) 10 t=time.strftime('%y-%m-%d %x') 11 self.file.write('%s %s' %(t,line)) 12 13 def __getattr__(self, item): 14 # print(item,type(item)) 15 # self.file.read 16 return getattr(self.file,item) 17 18 f1=filehandle('a.txt','w+') 19 # print(f1.file) 20 # print(f1.__dict__) 21 # print('==>',f1.read) #触发__getattr__ 22 # print(f1.write) 23 f1.write('1111111111111111\n') 24 f1.write('cpu负载过高\n') 25 f1.write('内存剩余不足\n') 26 f1.write('硬盘剩余不足\n') 27 # f1.seek(0) 28 # print('--->',f1.read())