Python–10、new方法、定制属性访问、描述符和装饰器
__ new __方法
1、__ new __ 方法相当于开辟内存,之后要传回父类。固定写法return,相当于宣告已经写好了。
2、实例是通过类里面的 __ new __方法创建出来的。
3、先调用 __ new __ 方法创建出实例,再使用__ init __ 方法初始化实例。
4、__ new __ 方法,后面括号里面的 c l s 代表的是类本身。
5、__ new __ 方法是在类 创建实例的时候自动调用的。
6、作用:当继承一些不可变的class时(例如int,str,tuple),提供一个自定义化这些类实例化过程的途径。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BXNOPPwz-1578213414426)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20200104170654739.png)]
#将输入的字母变为大写
class Caps(str):
def __new__(cls, string):
string = string.upper()
return super().__new__(cls, string) # 返回给父类的 __init__方法
'''
def __init__(self,string):
super().__init__()
string = string.upper()
#这里由于str类型不可变,所以修改不会成功
'''
b = Caps('i love china')
'''
写入的时候:'i love china'
str的new方法:'i love china'
重写的new方法:I LOVE CHINA
赋值: b = ' I LOVE CHINA '
'''
print(b)
#使输入的数字一直是正数
class A(int):
def __new__(cls, value):
return super().__new__(cls,abs(value))
i =A (-5)
print(i)
6、单线模式:
可以使用 __ new __ 方法控制只能创建一个实例。
class Earth: #游戏、论坛、聊天、APP等
def __new__(cls, *args, **kwargs):
if not hasattr(cls,'instance'): #instance 是指是否有实例
#hasattr(类名,属性名)查看某个类中是否存在指定的属性,有则返回True
#没有实例化对象的话就可以进行一次实例化创建
cls.instance = super().__new__(cls)
return cls.instance
def __init__(self):
self.name = '任太帅'
a = Earth() #a 进行第一次实例化
print(a.name) #第一次实例化成功
b = Earth()
print(b.name) #第二次实例化失败
定制属性访问
1、
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cOft3LnS-1578213414426)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20200104183613193.png)]
2、查:
hasattr(re,‘length’) #返回布尔值,查看指定类(实例)中有没有指定属性,有则返回True,没有则返回False。
getattr(re,‘length’) #返回属性值,查看指定类中属性的值
re. __ getattribute __ (‘length’) #返回属性值
改:
setattr(re,‘length’,6) #(修改的类名,属性名,新属性值)
re.__ setattr __(‘length’,5)
增:
re.aaa = 1
setattr(re,‘bbb’,2) #有bbb属性就该,没有就增
re.__ setattr __(‘ccc’,3) #同上
删:
delattr(re,‘ccc’)
re.__ delattr __(‘bbb’)
del re
class Test:
def __init__(self):
self.name = '任太帅'
self.age = '20'
self.sex = '男'
test1 = Test()
print(test1)
# <__main__.Test object at 0x7fb80b2c4f60>
#定制属性的访问 增删改查
#查找
print(hasattr(test1,'sex')) #查看指定类中有没有指定属性
print(getattr(test1,'name')) #查看指定类中属性的值
#+()print
# print(test1.__getattribute__('name')) #找到指定属性的值,没有则会报错
#修改
setattr(test1,'name','烟雨平生') #(修改的类名,属性名,新属性值)
test1.__setattr__('name','vn')
#增加 place
test1.place = '唐朝'
setattr(test1,'qq','654665456')
#删除
delattr(test1,'namme')
test1. __delattr__('qq')
del test1 #删除实例对象
3、可以对其中的方法进行重写,例如,你不希望getattr再没找到属性时报错,因为一旦报错,程序就会停止。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0gHNT3Uv-1578213414427)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20200104190549893.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eIg0b7dv-1578213414427)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20200104190834028.png)]
描述符
描述符协议:Python 描述符是一个“绑定行为”的对象属性,在描述符协议中,,它可以通过方法重写属性的访问,这些方法有__ get __ (), __ set __ (), __ delte __().如果这些方法中的任何一个呗定义在一个对象中,这个对象就是一个描述符。
class M:
def __get__(self, instance, owner):
return"恭喜你升级啦!"
def __set__(self, instance, value):
print("你当前的攻击力为%s"%value)
def __delete__(self, instance):
print("你已阵亡")
class con():
attr = M()
a = con()
print(a.attr) #获取属性
a.attr = 100 #自己定义,set加包装
del a.attr #删除时自动调用 delete
装饰器
闭包实现装饰器
1、直接更改函数,参数值可能会受到影响。于是在不改变原有函数的情况下,在函数外面加一个壳子,此为装饰器。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9WLIDbGi-1578213414427)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20200104205558574.png)]
2、在函数前面加 @函数名 ,就相当于直接加了装饰器。
@ … 相当于给下面的函数加了一个装饰器。
关键在于外部函数要返回内部函数的函数体,而且函数要传入函数。
def outer(c):
def inner():
# print(c) #func 接收到函数体
c() #调用传入的函数体
return inner #返回inner的函数体
@outer #在outer函数前加了@,就相当于直接给func函数加了装饰器
def func():
print("hello,world")
# x = outer(func)
# x() #执行返回来的inner函数
func()
案例:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TK0E9Bkj-1578213414428)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20200104222629476.png)]
类实现装饰器
类的内部装饰器–特殊的作用
1、priperty 使访问方法的形式等同于访问属性(把方法当属性使用)。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tUIwdjPM-1578213414428)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20200104211454386.png)]
2、staticmethod 静态方法。
和class(当前类)断绝关系 没有self传递,相当于函数,实现了独立,和当前类没有关系了。类方法里面也不能使用类属性。
3、classmethod 类方法。
可以使用类属性。原则上,类方法是将类本身作为对象进行操作的方法。假设有个方法,且这个方法在逻辑上采用类本身作为对象来调用更合理,那么这个方法就可以定义为类方法。另外,如果需要继承,也可以定义为类方法。
类方法和静态方法的区别为类方法可以使用类属性,静态方法不可以使用类方法。
4、类中的一个方法去使用另外的方法需要用 self.方法名;
也可使用静态方法,直接当函数使用就行
class Rec:
name = '这是类'
def __init__(self,length,width):
self.length = length
self.width = width
def area(self):
func() #静态方法
self.test() #类里面调用其他方法,要使用 self.方法名
return self.length * self.width
def test(self):
pass
@property #访问方法的形式同等于访问属性
def areal(self):
print("相当于属性")
return self.length * self.width
# 静态方法
@staticmethod #和class(当前类)断绝关系 没有self传递,相当于函数
def func(a,b):
print("静态方法",a*b)
#类方法
@classmethod
def show(cls,a,b): # cla 是类本身 传递的是当前的类
print("这是静态方法",a*b)
n1 = Rec(40,50)
Rec.func(30,50) #静态方法 类名.方法名
Rec.show(60,50) #类方法 类名.方法名
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qJo5LZKX-1578213414429)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20200104220924978.png)]
5、类做装饰器
#类做装饰器:
#必须使用 __call__
class Test:
def __init__(self,func):
self.func = func
def __call__(self, *args, **kwargs):
print('---正在验证---')
return self.func() #验证完成之后调用了func 函数
@Test
def fun_test():
print('--正在登陆---')
fun_test()
器
#类做装饰器:
#必须使用 __call__
class Test:
def __init__(self,func):
self.func = func
def __call__(self, *args, **kwargs):
print('---正在验证---')
return self.func() #验证完成之后调用了func 函数
@Test
def fun_test():
print('--正在登陆---')
fun_test()