Python装饰器

目录

1.装饰器的本质

2.装饰器的引出

(1)正常函数:

(2)闭包函数:

(3)装饰器

3.传一个参数

4.传多个参数   *args   **kwargs

5.输出注释:__doc__

6.添加两个装饰器

7.内置装饰器:   @property

(1)作用:

(2)注意:

(3)类中的某些属性被封装之后,想在类外改变属性的值,做法如下:

在你想要操作的方法前面写:  @property

@属性.setter   后面写你想对私有变量进行的操作

通过:对象名.属性=值,修改私有属性的值


1.装饰器的本质

闭包函数         @闭包函数名


https://blog.csdn.net/g_optimistic/article/details/86486937


2.装饰器的引出

练习:计算程序花费的时间

(1)正常函数:

import time


def func():
    start = time.time()
    for i in range(1000000):
        pass
    end = time.time()
    print(end - start)  # 0.031199932098388672


func()

(2)闭包函数:

(3)装饰器

@闭包函数名

import time


def otter(fun):
    def inner():
        start = time.time()
        ret = fun()
        end = time.time()
        print(end - start)
        return ret

    return inner


@otter  # 等价于:inner=otter(func)
def func():
    for i in range(1000000):
        pass
    return 'ok'


ret = func()
print(ret)
# 0.015599966049194336
# ok


3.传一个参数

import time


def otter(fun):
    print('xxx')

    def inner(s):
        start = time.time()
        ret = fun(s)
        end = time.time()
        print(end - start)
        return ret

    return inner


@otter  # 等价于:inner=otter(func)
def func(s):
    for i in range(1000000):
        pass
    return s


ret = func('hello')
print(ret)
# xxx
# 0.015599966049194336
# hello


4.传多个参数   *args   **kwargs

如果用一个变量来接收,输出来是元组

如果用两个变量来接收,输出来的也是元祖

      用元组接收 *args 返回的值

      用字典接收 **kwargs 返回的值

import time


def otter(fun):
    print('xxx')

    def inner(*args, **kwargs):
        start = time.time()
        ret = fun(*args, **kwargs)
        end = time.time()
        return ret

    return inner


@otter
def func(*args, **kwargs):
    for i in range(1000000):
        pass
    return args, kwargs


ret = func('hello', name='zs', age=10)
print(ret)
# xxx
# (('hello',), {'name': 'zs', 'age': 10})
ret, ret1 = func('hello', name='zs', age=10)
print(ret, ret1)  # ('hello',) {'name': 'zs', 'age': 10}
# 如果用一个变量来接收,输出来是元组
# 如果用多个变量来接受,用元组来接收*args的值,用字典来接收**kwargs的值


5.输出注释:__doc__

@wraps()要写在闭包函数里面,并且与内嵌函数中间不能有任何代码

import time
from functools import wraps


def otter(fun):
    print('xxx')

    @wraps(fun)  # @wraps()与内嵌函数之间不能有其他代码
    # print('xxx')  # 会报错

    def inner(*args, **kwargs):
        start = time.time()
        ret = fun(*args, **kwargs)
        end = time.time()
        print(end - start)
        return ret

    return inner


@otter
def func(*args, **kwargs):
    '''
    这是一个很牛的方法
    :param args: 接收多个位置参数
    :param kwargs: 接收多个关键字参数
    :return: 返回内容
    '''
    for i in range(1000000):
        pass
    return args, kwargs


ret = func('hello', name='zs', age=23)
print(ret)
print(func.__doc__)
# xxx
# 0.015600204467773438
# (('hello',), {'name': 'zs', 'age': 23})
# 
# 这是一个很牛的方法
# :param
# args: 接收多个位置参数
# :param
# kwargs: 接收多个关键字参数
# :return: 返回内容


6.添加两个装饰器

多个装饰器的执行顺序:从下往上(从内往外)

from functools import wraps
import time


def wrapper1(func):
    def inner1():
        print('wrapper1...start')
        func()
        print('wrapper1...end')

    return inner1


def wrapper2(func):
    def inner2():
        print('wrapper2...start')
        func()
        print('wrapper2...end')

    return inner2


@wrapper1  # 等价于:inner1=wrapper1(inner2)
@wrapper2  # 等价于:inner2=wrapper2(func)
# 执行顺序:
# 1.inner2=wrapper2(func)
# 2.inner1=wrapper1(inner2)

def func():
    print('func...')


func()
# wrapper1...start
# wrapper2...start
# func...
# wrapper2...end
# wrapper1...end


7.内置装饰器:   @property

(1)作用:

    把类的方法当属性用,更加模糊了函数与变量的调用

(2)注意:

使用@property,方法中不能有参数

# 正常代码:
from math import pi


class Circle:
    def __init__(self, r):
        self.r = r

    def zhouchang(self):
        return 2 * pi * self.r

    def area(self):
        return pi * self.r * self.r


c1 = Circle(2)
print(c1.zhouchang())
print(c1.area())
# 使用 @property
# 把方法当属性用
from math import pi


class Circle:
    def __init__(self, r):
        self.r = r

    @property
    def zhouchang(self):
        return 2 * pi * self.r

    @property
    def area(self):
        return pi * self.r * self.r


c1 = Circle(3)
print(c1.zhouchang)  # 18.84955592153876
print(c1.area)  # 28.274333882308138

(3)类中的某些属性被封装之后,想在类外改变属性的值,做法如下:

  • 在你想要操作的方法前面写:  @property

  • @属性.setter   后面写你想对私有变量进行的操作

  • 通过:对象名.属性=值,修改私有属性的值

 

# 在类外改变私有属性的值
# @property
# @属性.setter
class Person:
    def __init__(self, name, age):
        self.__name = name
        self.__age = age

    @property
    def name(self):
        return self.__name

    @property
    def age(self):
        return self.__age

    @age.setter  # @属性.setter 是@property的副产品
    def age(self, age):
        if age < 0 or age > 150:
            print('火星来的吧...')
            return
        self.__age = age

    def __str__(self):
        msg = '{}今年{}岁了'.format(self.__name, self.__age)
        return msg


person = Person('zs', 12)
print(person)  # zs今年12岁了
# 对象.属性=值
person.age = 20
print(person)  # zs今年20岁了
print(person.name)  # zs
print(person.age)  # 20

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值