装饰器和描述器

描述器

一.__new_的用法(这个也是默认调用的)

这个也叫单例模式,因为一直就是一个实例

class Earth:
    def __new__(cls, *args, **kwargs):
        if not hasattr(cls, 'instance'):
            cls.instance = super().__new__(cls)
        return cls.instance

    def __init__(self):
        Earth.name = 'earth'

e = Earth()
print(e)
a = Earth()
print(a)

[外链图片转存失败(img-OCtRJuuE-1564988398906)(../../AppData/Roaming/Typora/typora-user-images/1562760154515.png)]

首先说一下,这个__new__调用是在__init__前的,因为__new__先创建一个实例,__init__才继续赋值什么的,而这个演示的__new__是改写了默认的new,用来判断一下是否存在,这样可以知道是否已经实例化过了,可以大大的节省内存。

二.对象属性的增删改查
2.1 增
class Person:
    def __init__(self, name):
        self.name = name


one = Person("zxc")
Person.num = 1  # 第一种,通过句点法来增加
print(one.num)
setattr(one, "nu", "lalal")  # 第二种,通过内置函数setattr来实现,这种一定要有实例对象
print(one.nu)
one.__setattr__('n',444)  # 第三种,通过魔术方法
print(one.n)

[外链图片转存失败(img-gJ6A1Y4a-1564988398907)(../../AppData/Roaming/Typora/typora-user-images/1562763741294.png)]

其实内置函数都是所对应的魔术方法来实现的,这也解释为什么一定得有实例对象而不能凭空出现

2.2 删
class Person:
    def __init__(self, name):
        self.name = name


one = Person("zxc")
delattr(one, "name")
print(one.name)
one.__delattr__(one)

[外链图片转存失败(img-PHDDxYjW-1564988398908)(../../AppData/Roaming/Typora/typora-user-images/1562805773133.png)]

2.3 改
class Person:
    def __init__(self, name):
        self.name = name


one = Person("zxc")
one.name = "llla"
print(one.name)
setattr(one, "name", "feifei")
print(one.name)
one.__setattr__("name", 666)
print(one.name)

[外链图片转存失败(img-4miXI8KC-1564988398908)(../../AppData/Roaming/Typora/typora-user-images/1562805627974.png)]

2.4 查
class Person:
    def __init__(self, name):
        self.name = name


one = Person("zxc")
print(one.name)
print(hasattr(one, "name"))  #第一种查找方式,通过hasattr来实现查找,这个函数再__new__方法中调用过
print(getattr(one, "name"))  #这是相应得配套得方法,先通过hasattr来了解是否有,然后通过getattr来直接读取
print(one.__getattribute__("name")) #这是对应的第二种得魔术方法

[外链图片转存失败(img-pDvxm086-1564988398908)(../../AppData/Roaming/Typora/typora-user-images/1562804148556.png)]

三.描述符
class Cat:
    def __get__(self, instance, owner):
        return 6666

    def __set__(self, instance, value):
        print(777)

    def __delete__(self, instance):
        print(8888)

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

    test = Cat()


c = Person("ZXC")
print(c.test)
c.test = 'true'
print(c.test)
del c.test

这个相当于在一个类中去使用另一个实例对象,而实例对象得每个方法对应为默认调用,每个都有自己得方式

[外链图片转存失败(img-2J49x2vq-1564988398909)(../../AppData/Roaming/Typora/typora-user-images/1562810931432.png)]

在类里面访问另一个实例

装饰器

本质就是闭包

一.单层装饰器
def test1(func):
    def test2():
        print("调用之前")
        func()
        print("调用之后")
    return test2

def f1():
    print("功能模块")

f1 = test1(f1)
f1()

[外链图片转存失败(img-nPXPkkT8-1564988398909)(../../AppData/Roaming/Typora/typora-user-images/1562816954244.png)]

这个第二种

def test1(func):
    def test2():
        print("调用之前")
        func()
        print("调用之后")
    return test2

@test1
def f1():
    print("功能模块")

# f1 = test1(f1)
f1()

[外链图片转存失败(img-pfwsXq0l-1564988398909)(../../AppData/Roaming/Typora/typora-user-images/1562817790640.png)]

可以看出是一样得效果的,当然这都是没有参数的,哪有参数的怎么做呢

def test1(func):
    def test2(*args, **kwargs):
        print("调用之前")
        func(*args, **kwargs)
        print("调用之后")
    return test2

@test1
def f1(a):
    print("功能模块")
    print(a)

# f1 = test1(f1)
f1(5)

@test1
def f2(a):
    print("功能模块1")
    print(a)

f2(4)

[外链图片转存失败(img-q0hr8i5N-1564988398910)(../../AppData/Roaming/Typora/typora-user-images/1562818024811.png)]

这里的关键就是动态参数,适应性强

二.多层装饰器
def test1(func):
    def test2(*args, **kwargs):
        print("调用之前")
        func(*args, **kwargs)
        print("调用之后")
    return test2

def test0(func):
    def test2(*args, **kwargs):
        print("start")
        func(*args, **kwargs)
        print("end")
    return test2

@test0
@test1
def f1(a):
    print("功能模块")
    print(a)

# f1 = test1(f1)
f1(5)

[外链图片转存中...(img-SYaeLy7O-1564988398911)]

多层装饰器和单层装饰器原理差不多

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值