[Day1]PythonAdvanced学习笔记-装饰器decorator

[PythonAdvanced] 学习笔记 - Day 1

概览

Date: 2024-11-26 Time Spent: 6 hours

Topics: Decorators Difficulty: ⭐⭐⭐☆☆ (1-5 stars)

学习内容

  1. [*args & **kwargs]

    • 概念: (使用中*是必须的,名称可以根据个人习惯更换)

      *args is used to send a non-keyworded variable length argument list to the function. *args用来传递没有keyword的值。

      **kwargs allows you to pass keyworded variable length of arguments to a function. **kwargs是用来传递有keyword的值。

    • *args Example code

      def test_var_args(f_arg, *argv):
       print("first normal arg:", f_arg)
       for arg in argv:
       print("another arg through *argv:", arg)
      
      >>> test_var_args('yasoob', 'python', 'eggs', 'test')
      first normal arg: yasoob
      another arg through *argv: python
      another arg through *argv: eggs
      another arg through *argv: test
      
    • **kwargs Example code

      def greet_me(**kwargs):
          for key, value in kwargs.items():#遍历字符串
              print("{0} = {1}".format(key, value))#以key=value的格式化形式输出
      
      >>> greet_me(name="yasoob") //key=name, value=yasoob
      name = yasoob
      
  2. [Decorators]

    • 概念: 不改变原代码的基础上,对函数进行修饰。

    • Example code

      def decorator(func):
       def wrapper():
           print("Something is happening before the function is called.")
           func()
           print("Something is happening after the function is called.")
       return wrapper 
      def say_whee():
       print("Whee!") 
      say_whee = decorator(say_whee)
      
    • Example code

      def do_twice(func):
          def wrapper_do_twice(*args, **kwargs):
              func(*args, **kwargs)
              func(*args, **kwargs)
          return wrapper_do_twice
      
      @do_twice # greet = do_twice(greet)
      def greet(name):
          print(f"Hello {name}")
      >>> greet(name = "Mia")
      
    • Example code

      def do_twice(func):
          def wrapper_do_twice(*args, **kwargs):
              func(*args, **kwargs)
              func(*args, **kwargs)
              return func(*args, **kwargs)
          return wrapper_do_twice
      
      @do_twice
      def return_greeting(name):
          print("Creating greeting")
          return f"Hi {name}"
      
      >>> return_greeting("Adam")
      Creating greeting
      Creating greeting
      'Hi Adam'
      
    • Example code

      import functools
      def do_twice(func):
          @functools.wraps(func) 
          def wrapper_do_twice(*args, **kwargs):
              func(*args, **kwargs)
              return func(*args, **kwargs)
          return wrapper_do_twice
      @do_twice
      def say_whee():
          print("Whee!")
      
      >>> say_whee
      <function say_whee at 0x7ff79a60f2f0>
      
      >>> say_whee.__name__
      'say_whee'
      
      >>> help(say_whee)
      Help on function say_whee in module whee:
      
    • Example code

      import functools
      
      def decorator(func):
          @functools.wraps(func)
          def wrapper_decorator(*args, **kwargs):
              # Do something before
              value = func(*args, **kwargs)
              # Do something after
              return value
          return wrapper_decorator
      
    • Timer Example Code

      import functools
      import time
      
      def timer(func):
          """Print the runtime of the decorated function"""
          @functools.wraps(func)
          def wrapper_timer(*args, **kwargs):
              start_time = time.perf_counter()
              value = func(*args, **kwargs)
              end_time = time.perf_counter()
              run_time = end_time - start_time
              print(f"Finished {func.__name__}() in {run_time:.4f} secs")
              return value
          return wrapper_timer
      
      @timer
      def waste_some_time(num_times):
          for _ in range(num_times):
               sum([number**2 for number in range(10_000)])
      
      >>> waste_some_time(1)
      Finished waste_some_time() in 0.0010 secs
      
      >>> waste_some_time(999)
      Finished waste_some_time() in 0.3260 secs
      

练习代码

# *args and **kwargs 传递不定数量的值,如没有规定数量的字符串等
# 当使用 * 解包时,如果传入的是一个字符串,它会将字符串解包为字符序列。
# 当使用 ** 解包时,如果传入的是一个字典,它会将字典解包为关键字参数。

def test_args(value, *args):
    print("first:", value)
    for arg in args:
        print("next:", arg)


# test_args('hello','world','three','four')

def test_kwargs(**kwargs):
    for key, value in kwargs.items():
        print("{} = {}".format(key, value))


# test_kwargs(name='GPT',age='0.5 year',sex='none')

def test_args_and_kwargs(name, age, sex):
    print("name:", name)
    print("age:", age)
    print("sex:", sex)


args = ("GPT", "0.5 year", 'none')
# test_args_and_kwargs(*args)
kwargs = {"name": 'GPT', "sex": 'none', "age": '0.5 year'}


# test_args_and_kwargs(**kwargs) #使用**输出时需要注意列表里的key要与函数里的key对应

def decorator(func):
    def wrapper():  # 包装内容
        print("before the function")
        func()
        print("after the function")

    return wrapper


def say_hello():
    print("hello!")


# say_hello() #装饰前
say_hello = decorator(say_hello)  # 装饰后的


# say_hello()

@decorator  # 文法糖的装饰功能与say_hello = decorator(say_hello)功能一致
def say_hi():
    print("hi")


# say_hi()

import functools

def do_twice(func):
    @functools.wraps(func)  # 使用 @ functools.wraps裝飾器,它將保留有關原始函數的資訊
    def wrapper(*args, **kwargs):  # 接受任意數量的參數並將它們傳遞給它修飾的函數
        func(*args, **kwargs)
        func(*args, **kwargs)
        return func(*args, **kwargs)  # 保证如果与需求,可以回传函数值

    return wrapper


@do_twice
def say_hello(name):
    print("hello!", name)


# say_hello('Arden')
info = "Arden"
# say_hello(*info) #无法实现,*会将“Arden”解包为字符序列,因此有五个参数,与函数不符。
# say_hello(info)
info_me = {"name": "Arden"}
# say_hello(**info_me)

import functools  # 装饰器模板
import time

def timer(func):
    # 用来统计函数运行时间
    @functools.wraps(func)
    def wrapper_decorator(*args, **kwargs):
        start_time = time.time()  # 统计开始时时间
        value = func(*args, **kwargs)
        end_time = time.time()  # 记结束时间
        time_taken = end_time - start_time #时间差值
        print("It takes", time_taken, "seconds")
        return value
    return wrapper_decorator

@timer
def waste(num):
    for i in range(num):
        sum([i**2 for i in range(10000)]) #计算(1+...+2i)的和(i<=10000)

#waste(1)
#waste(999)

遇见的挑战难及解决方法和笔记点见注释。

学习资源

  • [Python Tips]: A book of many contents like generators, decorators, mutation and so on.
  • [Real Python]: Primer on Python Decorators.

明日计划

posted @   M-T-Arden  阅读(9)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
点击右上角即可分享
微信分享提示