dandan0523 发表于 2021-4-11 09:05:10

函数修饰符

import time

def timeslong(func):
    def call():
      start = time.clock()
      print("It's time starting ! ")
      func()   #这句话什么作用啊?
      print("It's time ending ! ")
      end = time.clock()
      return "It's used : %s ." % (end - start)
    return call

@timeslong
def f():
    y = 0
    for i in range(10):
      y = y + i + 1
      print(y)
    return y

print(f())                #这整块代码什么意思啊?

逃兵 发表于 2021-4-11 09:40:41

import time

def timeslong(func):
    def call():
      start = time.perf_counter()
      print("It's time starting ! ")
      func()   #这句话什么作用啊?
      print("It's time ending ! ")
      end = time.perf_counter()
      return "It's used : %s ." % (end - start)
    return call

def f():
    y = 0
    for i in range(10):
      y = y + i + 1
      print(y)
    return y

print(timeslong(f)())

将代码修改成以上这样你能否看明白呢?

函数timeslong传入的参数是个函数,在内嵌函数call中被调用

在上面的函数中,通过@timeslong给原函数f()增加了计时的功能

python函数修饰符@的作用是为现有函数增加额外的功能,常用于插入日志、性能测试、事务处理等等。

创建函数修饰符的规则:
(1)修饰符是一个函数
(2)修饰符取被修饰函数为参数
(3)修饰符返回一个新函数
(4)修饰符维护被维护函数的签名

阿奇_o 发表于 2021-4-11 11:22:54

本帖最后由 阿奇_o 于 2021-4-11 12:17 编辑

你们叫“修饰符”? 一般翻译为 装饰器 吧,毕竟 英文原词是 Decorator
Decorator 装饰器,本质是 函数的嵌套。 其特别在于,传递的是 所装饰/修饰下的那个函数对象。

理解的关键是:函数,竟然像 一个对象。函数也有“初始化”,函数初始化生成一个内存地址,和它真正被执行,是可以分开的!

# 1. 装饰器的本质是:函数嵌套。   外层函数返回 内层函数对象(内存地址),等待遇到小括号来执行。
def outer_func():
    def inner_func():
      print('Hi')
    return inner_func

in_f = outer_func()
print(in_f)
in_f()
in_f()

# 2. 装饰器,就像 一种包装、包裹,一种特殊的封装方法。
def decorator_func():
    print('--------------------')
    def wrapper_func():
      print('Hi, Hi.')
   # return ? 如果这里返回的是传入函数对象,会怎样呢?
    return wrapper_func

w_f = decorator_func()
w_f()
#继续扩展,如果 w_f 不叫 w_f,而是和 传入的函数对象名 同名呢?——这时,@decorator_func就诞生了!


# 请看:
def my_decorator(decorated_func):
    # print('------- xxxx -------') #暂不要理会这句
    def wrapper_func(name, age):
      print('------- 我在这就 装 饰一下 -------')
      return decorated_func(name, age)
    return wrapper_func

# @my_decorator
def hi(name, age):
    print(f'Hi, 你好。我叫{name}, {age}岁。 交个朋友?')

# 1.
# 传入函数对象(参数暂不传入,因为参数需要加小括号,函数对象遇到小括号立马执行了,这里不是我们需要的)
decorated_func = my_decorator(decorated_func=hi)
decorated_func('王大锤', 2333)

# 2.
# 若用上 @my_decorator 这一语法,就可以简化成:
# hi('王大锤', 2333) # 注:因为装饰器的“装饰”,该函数执行的逻辑 就不完全等于其本身的定义。

# 2.0
# 它实际上 等价于 下面两句
# hi = my_decorator(hi)   # 注意 要注释掉@my_decoratorn那句,不然print(装饰一下) 会 被执行两次,因为@my_decorator,相当于调用my_decorator(hi)
# hi('王大锤', 2333)



# 这样 以后 很方便地,只要你 @my_decorator 装饰下你自定义的函数,就可以 得到该装饰的附加效果。


# 典型应用,就是你代码想要实现的 计时功能(可看做是一种装饰),只要传入该函数对象 被@timelong 就可以被计时用时多久。
# 另一个典型应用是,触发写日记。 即创建一个专属的日记装饰器(如myLogger),再装饰和定义 一个日记信息函数(如 @myLoggerdef web_login(user, ip): ...

页: [1]
查看完整版本: 函数修饰符