python基础之类的内置__setattr__,__delattr__,__getattr__和 二次加工标准类型(包装)

一、内置attr:__setattr__,__delattr__,__getattr__

  1. __setattr__ #添加/修改属性会触发它的执行
  2. __delattr__ #删除属性的时候会触发
  3. __getattr__ #只有在调用属性且属性不存在的时候才会触发
class Foo:
    def __init__(self,x):
        self.name=x

    def __setattr__(self, key, value):
        # if not isinstance(value,str):
        #     raise TypeError('must be str')
        # print('----setattr---key:%s,value:%s' %(key,value))
        # print(type(key))
        # print(type(value))
        # self.key=value
        # setattr(self,key_str,value) #self.key_attribute=value #这是无限递归
        self.__dict__[key]=value #因为你重写了__setattr__,凡是赋值操作都会触发它的运行,你啥都没写,就是根本没赋值,除非你直接操作属性字典,否则永远无法赋值

    def __delattr__(self, item):
        print('delattr:%s' %item)
        print(type(item))
        # delattr(self,item) #这是无限递归
        # del self.item
        self.__dict__.pop(item) #我们可以直接修改属性字典,来完成添加/修改属性的操作


f1=Foo('egon') #f1.name='egon'

f1.age=18

print(f1.__dict__)
print(f1.name)
print(f1.age)

print(f1.__dict__)
del f1.age
print(f1.__dict__)
print(f1.age)


#---------------------getattr------------------------

class Foo:
    def __init__(self,x):
        self.name=x

    #属性不存在的情况下才会触发
    def __getattr__(self, item):
        print('getattr-->%s %s' %(item,type(item)))


f=Foo('egon')
# print(f.name)

print(f.xxxxxxx)
三板斧绝技

 二、二次加工标准类型(包装)

包装:python默认提供了标准数据类型,以及丰富的内置方法,有时候需要基于标准数据类型来定制我们自己的数据类型,新增或改写方法,这就用到了继承和派生知识(标准类型均可以通过以下方式进行二次加工)

授权:授权是包装的一个特性, 包装一个类型通常是对已存在的类型的一些定制,这种做法可以新建,修改或删除原有产品的功能。其它的则保持原样。授权的过程,即是所有更新的功能都是由新类的某部分来处理,但已存在的功能就授权给对象的默认属性。

实现授权的关键点就是覆盖__getattr__方法

定制自己的数据类型:

  1. 继承的方式
  2. 授权的方式
l=list([1,2,3])

l.append(4)
l.append('5')
print(l)

class List(list):
    pass

l1=List([1,2,3])
print(l1)
l1.append(4)
print(l1)
l1.append('5')
print(l1)
小例子
#基于继承的原理,来定制自己的数据类型(继承标准类型)
class List(list):
    def append(self, p_object):
        # print('--->',p_object)
        if not isinstance(p_object,int):
            raise TypeError('must be int')
        # self.append(p_object)
        super().append(p_object)
    def insert(self, index, p_object):
        if not isinstance(p_object,int):
            raise TypeError('must be int')
        # self.append(p_object)
        super().insert(index,p_object)
#
l=List([1,2,3])
# print(l)
# l.append(4)
# print(l)

# l.append('5')
print(l)
# l.insert(0,-1)
l.insert(0,'-1123123213')
print(l)


# def test(x:int,y:int)->int:
#     return x+y
# print(test.__annotations__)
#
# print(test(1,2))
# print(test(1,'3'))
#
# def test(x,y):
#     return x+y
基于继承的原理,来定制自己的数据类型(继承标准类型)
#不能用继承,来实现open函数的功能
# f=open('a.txt','w')
# print(f)
# f.write('1111111')

#授权的方式实现定制自己的数据类型
import time


class Open:
    def __init__(self,filepath,m='r',encode='utf-8'):
        self.x=open(filepath,mode=m,encoding=encode)

        self.filepath=filepath
        self.mode=m
        self.encoding=encode

    def write(self,line):
        print('f自己的write',line)
        t=time.strftime('%Y-%m-%d %X')
        self.x.write('%s %s' %(t,line))

    def __getattr__(self, item):
        # print('=------>',item,type(item))
        return getattr(self.x,item)
#
# f=Open('b.txt','w')
# # print(f)
# f.write('111111
')
# f.write('111111
')
# f.write('111111
')


f=Open('b.txt','r+')
# print(f.write)
print(f.read)


res=f.read() #self.x.read()
print(res)

print('=-=====>',f.read())
f.seek(0)
print(f.read())
# f.flush()
# f.close()
授权的方式实现定制自己的数据类型


原文地址:https://www.cnblogs.com/luchuangao/p/6758185.html