zoukankan      html  css  js  c++  java
  • Python面向对象编程Day 28部分知识点

    __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'}

  • 相关阅读:
    A1066 Root of AVL Tree (25 分)
    A1099 Build A Binary Search Tree (30 分)
    A1043 Is It a Binary Search Tree (25 分) ——PA, 24/25, 先记录思路
    A1079; A1090; A1004:一般树遍历
    A1053 Path of Equal Weight (30 分)
    A1086 Tree Traversals Again (25 分)
    A1020 Tree Traversals (25 分)
    A1091 Acute Stroke (30 分)
    A1103 Integer Factorization (30 分)
    A1032 Sharing (25 分)
  • 原文地址:https://www.cnblogs.com/chenyuan-1995/p/9711408.html
Copyright © 2011-2022 走看看