Python面向对象编程Day 28部分

发布时间:2019-03-13 23:15:58编辑:auto阅读(2031)

    __enter__和__exit__

     with obj as f:

      '代码块'

    1.with obj --->触发obj.__enter__(),拿到返回值

    2.as f ---> f=返回值

    3.with obj as f 等同于 f=obj.__enter__()

    4.执行代码块

    两种情况:

      没有异常的情况下,整个代码块运行完毕后去触发__exit__,它的三个参数都为None

      有异常的情况下,会从异常出现的位置直接触发__exit__,此时分两种情况:

          如果__exit__的返回值为True,代表吞掉了异常

          如果__exit__的返回值不为True,代表吐出了异常

          (exit的运行完毕就代表了整个with语句的执行完毕,异常后代码块内的语句不会执行)

     

    用途:使用with语句的目的是省去手动清理的过程,另外在需要管理一些资源比如文件,网络连接和锁的编程环境中,可以在__exit__中定制自动释放资源的机制。

     

    异常构成简单了解

    异常类,异常值,追踪信息 分别对应exc_type/exc_val/exc_tb

     

    描述符应用

     1 class Typed:
     2     def __init__(self,key,expected_type):
     3         self.key=key
     4         self.expected_type=expected_type
     5     def __get__(self, instance, owner): #instance是p1实例
     6         print('get方法')
     7         return instance.__dict__[self.key]
     8     def __set__(self, instance, value):
     9         print('set方法')
    10         if not isinstance(value,self.expected_type):
    11             raise TypeError('%s 传入的类型不是%s' %(self.key,self.expected_type))
    12         instance.__dict__[self.key]=value
    13     def __delete__(self, instance):
    14         print('delete方法')
    15         instance.__dict__.pop(self.key)
    16 
    17 class People:
    18     name=Typed('name',str) #t1.__set__()  self.__set__()
    19     age=Typed('age',int) #t1.__set__()  self.__set__()
    20     def __init__(self,name,age,salary):
    21         self.name=name
    22         self.age=age
    23         self.salary=salary
    24 
    25 p1=People(213,13,13.3)

    输出

    Traceback (most recent call last):
    File "G:/BaiduNetdiskDownload/第04阶段-Python3面向对象编程(24-28)/python全栈s3 day028/day28课上代码/描述符的应用.py", line 41, in <module>
    p1=People(213,13,13.3)
    File "G:/BaiduNetdiskDownload/第04阶段-Python3面向对象编程(24-28)/python全栈s3 day028/day28课上代码/描述符的应用.py", line 36, in __init__
    self.name=name
    File "G:/BaiduNetdiskDownload/第04阶段-Python3面向对象编程(24-28)/python全栈s3 day028/day28课上代码/描述符的应用.py", line 25, in __set__
    raise TypeError('%s 传入的类型不是%s' %(self.key,self.expected_type))
    TypeError: name 传入的类型不是<class 'str'>

     

    类的装饰器

     

     1 def deco(obj):
     2     print('==========',obj)
     3     obj.x=1
     4     obj.y=2
     5     obj.z=3
     6     return obj
     7 
     8 @deco #Foo=deco(Foo)
     9 class Foo:
    10     pass
    11 
    12 print(Foo.__dict__)

    输出

    ========== <class '__main__.Foo'>
    {'__module__': '__main__', '__dict__': <attribute '__dict__' of 'Foo' objects>, '__weakref__': <attribute '__weakref__' of 'Foo' objects>, '__doc__': None, 'x': 1, 'y': 2, 'z': 3}

     

     

    自定制property实现延迟计算功能

     1 class Lazyproperty:
     2     def __init__(self,func):
     3         # print('==========>',func)
     4         self.func=func
     5     def __get__(self, instance, owner):
     6         print('get')
     7         if instance is None:
     8             return self
     9         res=self.func(instance) #函数运行的时候要把实例本身传进去,而不是类
    10         setattr(instance,self.func.__name__,res)
    11         return res
    12     # def __set__(self, instance, value):  
    13     #     pass
    14 
    15 class Room:
    16     def __init__(self,name,width,length):
    17         self.name=name
    18         self.width=width
    19         self.length=length
    20     @Lazyproperty  # area=Lazypropery(area)
    21     def area(self):
    22         return self.width * self.length
    23     @property  # area1=property(area1)
    24     def area1(self):
    25         return  self.width * self.length
    26 
    27 r1=Room('厕所',1,1)
    28 print(r1.__dict__)
    29 
    30 # 实例调用
    31 print(r1.area)
    32 print(r1.__dict__)
    33 print(Room.__dict__)
    34 
    35 # 类调用    被描述符代理的属性 instance传的是None owner不变
    36 print(Room.area)
    37 
    38 # 不再调用get方法,因为此时有实例属性,
    39 # 其优先级高于非数据描述符 若此时加上set属性就无法实现了
    40 print(r1.area)
    41 print(r1.area)

     输出

    {'name': '厕所', 'width': 1, 'length': 1}
    get
    1
    {'name': '厕所', 'width': 1, 'length': 1, 'area': 1}
    {'__module__': '__main__', '__init__': <function Room.__init__ at 0x000001EFB23EA620>, 'area': <__main__.Lazyproperty object at 0x000001EFB07D8908>, 'area1': <property object at 0x000001EFB0799688>, '__dict__': <attribute '__dict__' of 'Room' objects>, '__weakref__': <attribute '__weakref__' of 'Room' objects>, '__doc__': None}
    get
    <__main__.Lazyproperty object at 0x000001EFB07D8908>
    1
    1

     

     property补充

     1 class Foo:
     2     @property
     3     def AAA(self):
     4         print('get的时候运行我啊')
     5 
     6     # 下面两个函数依附于静态属性存在
     7     @AAA.setter
     8     def AAA(self,val):
     9         print('set的时候运行我啊',val)
    10     @AAA.deleter
    11     def AAA(self):
    12         print('del的时候运行我啊')
    13 #只有在属性AAA定义property后才能定义AAA.setter,AAA.deleter
    14 f1=Foo()
    15 f1.AAA
    16 f1.AAA='aaa'
    17 del f1.AAA

    #另一种写法,效果一样
    class Foo:

    def get_AAA(self):
    print('get的时候运行我啊')
    def set_AAA(self,val):
    print('set的时候运行我啊',val)
    def del_AAA(self):
    print('del的时候运行我啊')

    AAA=property(get_AAA,set_AAA,del_AAA)  #顺序不要变
    f1=Foo()
    f1.AAA
    f1.AAA='aaa'
    del f1.AAA
     

    输出

    get的时候运行我啊
    set的时候运行我啊 aaa
    del的时候运行我啊

     

    元类

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

    1 def say_hi(name):
    2     return('hello,%s'%name)
    3 FFo=type('FFo',(object,),{'gender':'female','say_hi':say_hi})
    4 print(FFo)
    5 print(FFo.__dict__)
    6 print(FFo.say_hi('chenyuan'))
    7 print('Your gender is %s'%FFo.gender)

    输出

    <class '__main__.FFo'>
    {'gender': 'female', 'say_hi': <function say_hi at 0x000001CF9911C1E0>, '__module__': '__main__', '__dict__': <attribute '__dict__' of 'FFo' objects>, '__weakref__': <attribute '__weakref__' of 'FFo' objects>, '__doc__': None}
    hello,chenyuan
    Your gender is female

    实例调用函数,会自动把实例本身传进去当参数,而类调用函数时如果需要得写self

     

    自定制元类

     1 class MyType(type):
     2     def __init__(self,a,b,c):
     3         print('元类的构造函数执行')
     4         # print(a)
     5         # print(b)
     6         # print(c)
     7     def __call__(self, *args, **kwargs):
     8         # print('=-======>')
     9         # print(self)
    10         # print(args,kwargs)
    11         obj=object.__new__(self) #object.__new__(Foo)-->f1
    12         self.__init__(obj,*args,**kwargs)  #Foo.__init__(f1,*arg,**kwargs)
    13         return obj
    14 class Foo(metaclass=MyType): #Foo=MyType(Foo,'Foo',(),{})---》__init__
    15     def __init__(self,name):
    16         self.name=name #f1.name=name
    17 # print(Foo)
    18 # f1=Foo('alex')
    19 # print(f1)
    20 
    21 f1=Foo('alex')
    22 print(f1)
    23 print(f1.__dict__)

    输出

    元类的构造函数执行
    <__main__.Foo object at 0x0000025A13005048>
    {'name': 'alex'}

关键字

上一篇: Windows+Python 3.6环境

下一篇: 循环结构for