Python基础-描述器和装饰器

一、__new__方法

当所有实例中间封装的数据都相同的情况下 我们去实例化 就可以用__new__方法
__init__方法如果两次实例化 是会有两个不同的地址

__new__ : 单例模式
class A:
    def __new__(cls, *args, **kwargs):
        if not hasattr(cls, "instance"):             # 判断是不是已经有实例存在
            cls.instance = super().__new__(cls)      # 新建一个实例
        return cls.instance                          # 有了的话直接调用

    def __init__(self):
        self.name = "王福鑫"


one = A()
print(one, id(one))  
two = A() 
print(two, id(two))       #相同的内存地址

二、对象属性的增删改查

1、增

无则增,有则改

class Rectangle:
    def __init__(self, length, width):
        self.length = length
        self.width = width

    def area(self):
        areas = self.length * self.width
        return "面积是:{}".format(areas)


a = Rectangle(66, 88)
a.num = 6                  #第一种增加方法
setattr(a, "num", 6)        #第二种增加方法
a.__setattr__("num", 6)     #第三种增加方法
print(a.num)
a.num = 8
setattr(a, "num", 10)
a.__setattr__("num", 12)
print(a.num)                #无则增,有则改

2、查

print(hasattr(a, 'num'))        # bool值
print(getattr(a, 'num'))        # 获取属性值 
print(a.__getattribute__('num'))   # 获取属性值 

3、删

del a.num
delattr(a, "num")
a.__delattr__("num")

#当属性不存在时,调用魔术方法,实现不报错
    def __getattr__(self, item):
        print("no attribute")

魔术方法,给了我们一个自定义的接口,函数执行的底层其实就是去调用了魔术方法,只需要修改一下对应的魔术方法,就实现自定义

class A:
    def __get__(self, instance, owner):
        print("__get__")

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

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


class B:
    a = A()   # 把A的实例对象拿来做了B的类属性,描述器

    def __init__(self):
        self.name = "句号"


b = B()   # 类的实例化
print(b.name)   # 获取对象属性
b.a     # 获取B的类属性(A的实例),会去执行__get__
b.a = 88   # 重新赋值,会去执行__set__
del b.a    # 删除 ,会去执行__delete__

三、装饰器

1、一个装饰器

本质还是一个闭包

def outer(func):
    def inner():
        print("前增功能")
        func()
        print("后增功能")
    return inner

@outer     # 1.执行outer函数,并将下方的函数名作为参数赋值给了outre函数 2.将outer函数的返回值重新赋值给了下方函数
def f1():
    print("原功能")


f1()

有参数为了方便接收不同的参数个数的每个函数,*args, **kwargs

def outer(func):
    def innt(*args, **kwargs):
        print("前增")
        func(*args, **kwargs)
        print("后增")
    return innt
@outer
def f1():
    print("没有参数")
f1()
@outer
def f2(a):
    print(a)
f2(6)
@outer
def f3(a, b):
    print(a + b)
f3(5, 6)
@outer
def f4(a, b, c):
    print(a + b + c)
f4(5, 6, c=7)

2、多个装饰器

def outer_0(func):
    def innt(*args, **kwargs):
        print("start")
        func(*args, **kwargs)
        print("ebd")
    return innt


def outer(func):
    def innt(*args, **kwargs):
        print("前增")
        func(*args, **kwargs)
        print("后增")
    return innt


@outer_0
@outer
def f1():
    print("原功能")


f1()

3、内置装饰器

class Cat:
    name = "猫"

    def __init__(self, color, eat):
        self.color = color
        self.eat = eat

    def print_cat(self):
        print("{},{}".format(self.color, self.eat))

    @classmethod
    def funcl(cls):
        print("OK")


kitty = Cat('white', 'food')
kitty.print_cat()
kitty.funcl()
Cat.funcl()
@property   # (方法变属性)

class Cat:
    name = "猫"

    def __init__(self, color, eat):
        self.color = color
        self.eat = eat

    @property   # (方法变属性)
    def print_cat(self):
        print("{},{}".format(self.color, self.eat))

    @classmethod
    def funcl(cls):
        print("OK")


kitty = Cat('white', 'food')
kitty.print_cat     #可以直接这样调用不用()
@staticmethod   #静态方法(解绑)

class Cat:
    name = "猫"

    def __init__(self, color, eat):
        self.color = color
        self.eat = eat

    @property   # (方法变属性)
    def print_cat(self):
        print("{},{}".format(self.color, self.eat))

    @classmethod
    def funcl(cls):
        print("OK")

    @staticmethod
    def func():
        print("不需要self参数也能运行")
        print("不需要实例也能运行")


kitty = Cat('white', 'food')

kitty.func()
Cat.func()

4、类做装饰器

class TestClass:
    """这是一个用来做装饰器的类"""
    def __init__(self, func):
        self.func = func

    def __call__(self, *args, **kwargs):
        print("__call__")
        print("前增")
        self.func()
        print("后增")
        

@TestClass           # 类的实例不能直接被调用 想要调用 必须要定义一个__call__方法
def f():
    print("原功能")


f()

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值