鱼C论坛

 找回密码
 立即注册
查看: 2201|回复: 2

[已解决]函数修饰符

[复制链接]
发表于 2021-4-11 09:05:10 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
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 11:22:54
本帖最后由 阿奇_o 于 2021-4-11 12:17 编辑

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

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

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

  6. in_f = outer_func()
  7. print(in_f)
  8. in_f()
  9. in_f()

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

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


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

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

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

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

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



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


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

复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2021-4-11 09:40:41 | 显示全部楼层
  1. import time

  2. def timeslong(func):
  3.     def call():
  4.         start = time.perf_counter()
  5.         print("It's time starting ! ")
  6.         func()   #这句话什么作用啊?
  7.         print("It's time ending ! ")
  8.         end = time.perf_counter()
  9.         return "It's used : %s ." % (end - start)
  10.     return call

  11. def f():
  12.     y = 0
  13.     for i in range(10):
  14.         y = y + i + 1
  15.         print(y)
  16.     return y

  17. print(timeslong(f)())
复制代码


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

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

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

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

创建函数修饰符的规则:
(1)修饰符是一个函数
(2)修饰符取被修饰函数为参数
(3)修饰符返回一个新函数
(4)修饰符维护被维护函数的签名
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-4-11 11:22:54 | 显示全部楼层    本楼为最佳答案   
本帖最后由 阿奇_o 于 2021-4-11 12:17 编辑

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

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

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

  6. in_f = outer_func()
  7. print(in_f)
  8. in_f()
  9. in_f()

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

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


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

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

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

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

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



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


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

复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-6-25 04:49

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表