欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Python面向对象编程Day 28部分知识点

程序员文章站 2022-03-20 20:02:04
__enter__和__exit__ with obj as f: '代码块' 1.with obj >触发obj.__enter__(),拿到返回值 2.as f > f=返回值 3.with obj as f 等同于 f=obj.__enter__() 4.执行代码块 两种情况: 没有异常的情况 ......

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