反射
通过字符串的形式操作对象相关的属性
四个可以实现自省的函数:hasattr、getattr、setattr、delattr
class People:
country = 'China'
def __init__(self,Name):
self.name = Name
hasattr
p = People('spring')
print(p.__dict__)
print(hasattr(p,'country'))
print(hasattr(p,'__doc__'))
print(hasattr(p,'name'))
print(hasattr(p,'__init__'))
print(hasattr(People,'country'))
getattr
res = getattr(p,'country')
print(res)
res = getattr(p, 'age', '没有设定age')
print(res)
res = getattr(People, 'country')
print(res)
setattr
p.age = 18
print(p.age)
print(p.__dict__)
setattr(p, 'age', 28)
print(getattr(p, 'age'))
setattr(People,'country','USA')
print(getattr(People,'country'))
delattr
print(hasattr(p, 'age'))
delattr(p, 'age') #res = getattr(p, 'age', '没有设定age') # 找不到可以设个返回值,不设定找不到会报错。
print(hasattr(p, 'age'))
使用反射的好处:
1.通过字符串来导入模块,动态导入模块
#不推荐这个
m = __import__('time')
print(m.time())
#推荐方法
import importlib
m = importlib.import_module('time')
print(m.time())
2.可插拔机制,实现可插拔机制
#module
class FtpClient:
def __init__(self, addr):
print('正在连接服务器[%s]'%addr)
self.addr = addr
# def get(self):
# print('get')
from module import FtpClient
f1 = FtpClient('192.168.1.1')
if hasattr(f1, 'get'):
func_get = getattr(f1, 'get')
func_get()
else:
print('---->不存在此方法')
反射当前模块属性(成员)
import sys
x = 22
class Foo:
pass
def s1():
print('s1')
def s2():
print('s2')
this_module = sys.modules[__name__]
print(this_module)
print(hasattr(this_module,'s1'))
print(this_module.s1)
__setattr__, __delattr__, __getattr__
#__setattr__, __delattr__, __getattr__
class Foo:
def __init__(self,Name):
self.name = Name
def __setattr__(self, key, value):
print('---setattr-----key: %s value: %s'%(key, value))
self.__dict__[key] = value
def __delattr__(self, item):
print('------delattr-----item: %s'%item)
# self.__dict__.pop(item)
del self.__dict__[item]
def __getattr__(self, item):
print('----getattr----item: %s'%item)
#setattr
cc = Foo('spring')
print(cc.__dict__)
print(cc.name)
cc.__dict__['age'] = 166
print(cc.age)
#delattr
print(cc.__dict__)
del cc.age
print(cc.__dict__)
#getattr 属性不存在才会运行 和getattr() 结合使用
print('!'*100)
print(cc.zz)
定制自己的数据类型
1 基于继承标准的数据类型来定制数据类型
class List(list):
def append(self, object: int):
if not isinstance(object,int):
raise TypeError('must be int')
super().append(object)
#list.append(self,object)
def insert(self, index: int, object: int):
if not isinstance(object, int):
raise TypeError('must be int')
super().insert(index, object)
cc = List([1,2,3])
print(cc)
#cc.append('3')
cc.append(33)
print(cc)
cc.insert(0,22)
print(cc)
2 授权的方式定制数据类型
import time
class Open:
def __init__(self, file_path, m='r', encode='utf-8'):
self.x = open(file_path, mode=m, encoding=encode)
self.file_path = file_path
self.encoding = encode
def write(self, line):
print('写入: ', line)
t = time.strftime('%Y-%m-%d %X')
self.x.write('%s %s'%(t, line))
def __getattr__(self, item):
return getattr(self.x, item)
f = Open('a.txt', m='a+')
f.x.write('sss\n')
f.write('zzz\n')
f.seek(0)
print(f.read())
class List:
def __str__(self):
return str(self.cont)
def __init__(self,cont):
self.cont = cont
def append(self,value):
if not isinstance(value, str):
raise TypeError('must be str')
self.cont.append(value)
@property
def mid(self):
if len(self.cont) == 1 or len(self.cont) == 0: #如果list为口活着只有一个元素返回list本身
return self.cont
a, b = divmod(len(self.cont), 2)
if b != 0:
return self.cont[a+1] #如果奇数返回中间数
else:
return self.cont[a:a+2] #如果是偶数返回中间的2个数
def __getattr__(self, item): #其余方法都使用list自带
return getattr(self.cont,item)
cc = List(['b','a','c','d'])
print(cc.mid)
cc.append('z')
cc.sort()
print(cc)