上下文管理协议和元类

上下文管理协议和元类

返回首页

item系列:

把对象操作属性模拟成字典的格式。

 #把对象操作属性模拟成字典的格式
class Foo:
    def __init__(self,name):
        self.name=name
    def __setattr__(self, key, value):
        print('setattr===>')
    def __getitem__(self, item):
        # print('getitem',item)
        return self.__dict__[item]
    def __setitem__(self, key, value):
        print('setitem-----<')
        self.__dict__[key]=value
    def __delitem__(self, key):
        self.__dict__.pop(key)
        # self.__dict__.pop(key)
    # def __delattr__(self, item):
    #     print('del obj.key时,我执行')
    #     self.__dict__.pop(item)

f=Foo('George')
f.name='Wang'
f['name']='George'
# print(f.name)
# f.name='George'
# f['age']=18
# print(f.__dict__)
#
# del f['age'] #del f.age
# print(f.__dict__)
# print(f['name'])

__slots__方法:对象不会去建立新的名称空间,这样可以节省内存。但是它会限制使用属性,所以它的使用场景是一个类要产出多个固定的属性的时候,这时就可以用__slots__来统一管理了。 

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

    def run(self):
        pass

print(People.__dict__)  #查看People的属性
p=People('alex')
print(p.__dict__)


class People:
    __slots__=['x','y','z']

p=People()
print(People.__dict__)

p.x=1
p.y=2
p.z=3
print(p.x,p.y,p.z)
# print(p.__dict__)

p1=People()
p1.x=10
p1.y=20
p1.z=30
print(p1.x,p1.y,p1.z)
print(p1.__dict__)

实现迭代器协议

from collections import Iterable,Iterator
class Foo:
    def __init__(self,start):
        self.start=start

    def __iter__(self):
        return self

    def __next__(self):
        return 'aSB'

f=Foo(0)
# f.__iter__()  #有__iter__就是可迭代的
# f.__next__()  #有__next__就是迭代器

print(isinstance(f,Iterable))
print(isinstance(f,Iterator))
print(next(f)) #f.__next__()
print(next(f)) #f.__next__()
print(next(f)) #f.__next__()

for i in f: #先执行__iter__方法,变成迭代器,然后就可以__next__, res=f.__iter__() #__iter__得到的就是自己self #next(res)
    print(i)

例如:

######有一个初始值,每次自加一
from collections import Iterable,Iterator
class Foo:
    def __init__(self,start):
        self.start=start

    def __iter__(self):
        return self

    def __next__(self):
        if self.start > 10:
            raise StopIteration
        n=self.start
        self.start+=1
        return n

f=Foo(0)
# print(next(f))
# print(next(f))
# print(next(f))
# print(next(f))
# print(next(f))
# print(next(f))
# print(next(f))
# print(next(f))
# print(next(f))
# print(next(f))
# print(next(f))
# print(next(f))
for i in f:
    print('====>',i)

模拟range:

class Range:
    '123'
    def __init__(self,start,end):
        self.start=start
        self.end=end

    def __iter__(self):
        return self

    def __next__(self):
        if self.start == self.end:
            raise StopIteration
        n=self.start
        self.start+=1
        return n

for i in Range(0,3):
    print(i)

print(Range.__doc__)

析构函数: __del__,在__del__中定义一些清理操作。比如关闭。

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

    def write(self):
        pass

    def __getattr__(self, item):
        return getattr(self.f,item)

    def __del__(self):
        print('----->del')
        self.f.close()

f=Open('a.txt','w')
f1=f  #f1=f时,先执行print("=====>")的操作,在去执行def f
del f
print('=========>')

上下文管理协议

# with open('a.txt','r') as f:
#     print('--=---->')
#     print(f.read())

# with open('a.txt', 'r'):
#     print('--=---->')

class Foo:
    def __enter__(self):
        print('=======================》enter')
        return 111111111111111

    def __exit__(self, exc_type, exc_val, exc_tb):
        print('exit')
        print('exc_type',exc_type)
        print('exc_val',exc_val)
        print('exc_tb',exc_tb)
        return True

# with Foo(): #res=Foo().__enter__()
#     pass

with Foo() as obj: #res=Foo().__enter__() #obj=res  #with Foo() as obj是将with Foo()的结果给obj。
    print('with foo的自代码块',obj)
    raise NameError('名字没有定义')
    print('************************************')

print('1111111111111111111111111111111111111111')

实现上下文管理协议

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

    def write(self,line):
        print('write')
        self.f.write(line)

    def __getattr__(self, item):
        return getattr(self.f,item)

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.f.close()
        return True

with Open('aaaaa.txt','w') as write_file: #write_file=Open('aaaaa.txt','w')
    write_file.write('123123123123123
')
    write_file.write('123123123123123
')
    #print(sssssssssssssss)
    write_file.write('123123123444123123
')

call方法:

对象后面加括号,触发执行。

注:构造方法的执行是由创建对象触发的,即:对象=类名();而对于__call__方法的执行是由对象后加括号触发的,即:对象() 或者 类()()

class People:
    def __init__(self,name):
        self.name=name

    def __call__(self, *args, **kwargs):
        print('call')

p=People('George')
print(callable(People))
print(callable(p))
p() #加call方法会直接触发call方法的运行,打印call

元类:元类是类的类,是类的模板。

元类是用来控制如何创建类的,正如类是创建对象的模板一样。

# class People:
#     def __init__(self,name):
#         self.name=name
#
# p=People('egon')
# print(type(p))
# print(type(People))
#####typer产生类,类产生对象。

# class Foo:
#     x=1
#     def run(self):
#         pass
# print(type(Foo))

#####type成为元类,是所有类的类,利用type模拟class关键字的创建类的过程
def run(self):
    print('%s is runing' %self.name)

class_name='Bar'  #类的名字
bases=(object,)   #类的继承关系
class_dic={       #类的属性字典
    'x':1,
    'run':run
}
print(class_dic)
Bar=type(class_name,bases,class_dic)
print("Bar",Bar)
print(type(Bar))

自定制元类:

class Mymeta(type):  #Mymeta继承type这个元类
    def __init__(self,class_name,class_bases,class_dic):
        # print(self)
        # print(class_name)
        # print(class_bases)
        # print(class_dic)
        for key in class_dic:
            if not callable(class_dic[key]):continue
            if not class_dic[key].__doc__:
                raise TypeError('小子,你没写注释,赶紧去写')
        # type.__init__(self,class_name,class_bases,class_dic)

class Foo(metaclass=Mymeta):  #metaclass=Mymeta是指定元类
    x=1
    def run(self):
        'run function'
        print('running')

# Foo=Mymeta('Foo',(object,),{'x':1,'run':run})  #实例化
print(Foo.__dict__)


class Mymeta(type):
     def __init__(self,class_name,class_bases,class_dic):
            pass
     def __call__(self, *args, **kwargs):
        print(self)
        obj=self.__new__(self)
        self.__init__(obj,*args,**kwargs) #obj.name='egon'
        return obj
class Foo(metaclass=Mymeta):
    x=1
    def __init__(self,name):
        self.name=name #obj.name='egon'
    def run(self):
        'run function'
        print('running')
        
print(Foo.__dict__)
f=Foo('egon')
print(f)
print(f.name)

------- END -------

原文地址:https://www.cnblogs.com/george92/p/14662869.html