三 __setattr__,__delattr__,__getattr__
class Foo:
x=1
def __init__(self,y):
self.y=y
def __getattr__(self, item):
print('----> from getattr:你找的属性不存在')
def __setattr__(self, key, value):
print('----> from setattr')
# self.key=value #这就无限递归了,你好好想想
self.__dict__[key]=value #应该使用它
def __delattr__(self, item):
print('----> from delattr')
# del self.item #无限递归了
self.__dict__.pop(item)
#__setattr__添加/修改属性会触发它的执行
f1=Foo(10)
print(f1.__dict__) # 因为你重写了__setattr__,凡是赋值操作都会触发它的运行,你啥都没写,就是根本没赋值,除非你直接操作属性字典,否则永远无法赋值
f1.z=3
print(f1.__dict__)
#__delattr__删除属性的时候会触发
f1.__dict__['a']=3#我们可以直接修改属性字典,来完成添加/修改属性的操作
del f1.a
print(f1.__dict__)
#__getattr__只有在使用点调用属性且属性不存在的时候才会触发
f1.xxxxxx
lower的示例:
class Foo:
def __init__(self,name):
self.name = name
def __getattr__(self, item):
print('【%s】这个属性不存在!'%item)
def __setattr__(self, key, value):
# 设置值为str
if type(value) is str:
print('设置成功![%s,%s]'%(key,value))
self.__dict__[key] = value
else:
print('[%s]不是是字符串'%value)
def __delattr__(self, item):
print('%s 不允许删除'%item)
# print('执行了delattr',item)
# self.__dict__.pop(item)
f1 = Foo('long')
# f1.age # 【age】这个属性不存在!
# f1.age = 11
# print(f1.__dict__)
print(f1.__dict__)
del f1.name
print(f1.__dict__)
四 二次加工标准类型(包装)
包装:python为大家提供了标准数据类型,以及丰富的内置方法,其实在很多场景下我们都需要基于标准数据类型来定制我们自己的数据类型,新增/改写方法,这就用到了我们刚学的继承/派生知识(其他的标准类型均可以通过下面的方式进行二次加工)
class List(list): #继承list所有的属性,也可以派生出自己新的,比如append和mid
def append(self, p_object):
' 派生自己的append:加上类型检查'
if not isinstance(p_object,int):
raise TypeError('must be int')
super().append(p_object)
@property
def mid(self):
'新增自己的属性'
index=len(self)//2
return self[index]
l=List([1,2,3,4])
print(l)
l.append(5)
print(l)
# l.append('1111111') #报错,必须为int类型
print(l.mid)
#其余的方法都继承list的
l.insert(0,-123)
print(l)
l.clear()
print(l)
二次加工标准类型(基于继承实现)
授权:授权是包装的一个特性, 包装一个类型通常是对已存在的类型的一些定制,这种做法可以新建,修改或删除原有产品的功能。其它的则保持原样。授权的过程,即是所有更新的功能都是由新类的某部分来处理,但已存在的功能就授权给对象的默认属性。
实现授权的关键点就是覆盖__getattr__方法
import time
class Open:
def __init__(self,filename,mode='r',encoding='utf-8'):
self.file = open(filename,mode,encoding=encoding)
self.mode = mode
self.encoding = encoding
def __getattr__(self, item):
return getattr(self.file,item) # 从系统的方法中找对应的方法
def write(self,line):
'''写入时,加入时间'''
t = time.strftime('%Y-%m-%d %X')
self.file.write('%s %s'%(t,line))
f = Open('a.txt','w+','utf-8')
print(f.write)
# f.write('a') # 先从自己类中查找,没有调用__getattr__,通过getattr()在系统提供的类中查找
# data = f.read()
# print(data)
f.write('cup好热\n')
f.write('aaaaaaaaa\n')