偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

從零到精通:Python 裝飾器的完整指南與實(shí)戰(zhàn)應(yīng)用

開發(fā)
本文將從基礎(chǔ)原理出發(fā),逐步深入裝飾器的各種應(yīng)用場(chǎng)景,幫助你真正掌握這項(xiàng)強(qiáng)大的工具。

裝飾器是Python中最優(yōu)雅卻最容易被誤解的特性之一。許多初學(xué)者對(duì)"裝飾"這個(gè)概念感到困惑,高級(jí)開發(fā)者則可能陷入過度使用裝飾器的陷阱。本文將從基礎(chǔ)原理出發(fā),逐步深入裝飾器的各種應(yīng)用場(chǎng)景,幫助你真正掌握這項(xiàng)強(qiáng)大的工具。

一、裝飾器的本質(zhì)原理

1. 什么是裝飾器

裝飾器本質(zhì)上是一個(gè)函數(shù),它接收另一個(gè)函數(shù)作為參數(shù),并返回一個(gè)新函數(shù)。這個(gè)新函數(shù)通常會(huì)在原函數(shù)執(zhí)行前后進(jìn)行某些操作。

# 最簡(jiǎn)單的裝飾器
defmy_decorator(func):
    defwrapper():
        print("執(zhí)行前")
        func()
        print("執(zhí)行后")
    return wrapper

@my_decorator
defsay_hello():
    print("Hello!")

# 等同于:say_hello = my_decorator(say_hello)

say_hello()
# 輸出:
# 執(zhí)行前
# Hello!
# 執(zhí)行后

2. 保留原函數(shù)的元數(shù)據(jù)

使用裝飾器后,原函數(shù)的元數(shù)據(jù)(如函數(shù)名、文檔字符串)會(huì)丟失。使用functools.wraps可以解決這個(gè)問題。

from functools import wraps

defmy_decorator(func):
    @wraps(func)
    defwrapper(*args, **kwargs):
        """這是wrapper函數(shù)"""
        print("執(zhí)行前")
        result = func(*args, **kwargs)
        print("執(zhí)行后")
        return result
    return wrapper

@my_decorator
defadd(a, b):
    """將兩個(gè)數(shù)相加"""
    return a + b

print(add.__name__)  # 'add',而不是'wrapper'
print(add.__doc__)  # '將兩個(gè)數(shù)相加'

二、裝飾器的常見應(yīng)用場(chǎng)景

1. 性能監(jiān)測(cè)裝飾器

import time
from functools import wraps

deftimeit(func):
    @wraps(func)
    defwrapper(*args, **kwargs):
        start = time.time()
        result = func(*args, **kwargs)
        end = time.time()
        print(f"{func.__name__} 耗時(shí):{end - start:.4f}秒")
        return result
    return wrapper

@timeit
defslow_function():
    time.sleep(1)
    return"完成"

result = slow_function()

2. 日志記錄裝飾器

import logging
from functools import wraps

deflog_calls(level=logging.INFO):
    defdecorator(func):
        @wraps(func)
        defwrapper(*args, **kwargs):
            logging.log(level, f"調(diào)用 {func.__name__} 參數(shù):{args}, {kwargs}")
            result = func(*args, **kwargs)
            logging.log(level, f"{func.__name__} 返回值:{result}")
            return result
        return wrapper
    return decorator

@log_calls(level=logging.DEBUG)
defprocess_data(data):
    return data.upper()

process_data("hello")

3. 函數(shù)參數(shù)驗(yàn)證裝飾器

from functools import wraps

defvalidate_types(**type_checks):
    defdecorator(func):
        @wraps(func)
        defwrapper(*args, **kwargs):
            for arg_name, expected_type in type_checks.items():
                if arg_name in kwargs:
                    ifnot isinstance(kwargs[arg_name], expected_type):
                        raise TypeError(f"{arg_name} 必須是 {expected_type}")
            return func(*args, **kwargs)
        return wrapper
    return decorator

@validate_types(name=str, age=int)
defcreate_user(name, age):
    returnf"創(chuàng)建用戶:{name}, 年齡:{age}"

create_user(name="Alice", age=25)  # 正常
# create_user(name="Alice", age="25")  # 會(huì)拋出TypeError

4. 緩存裝飾器(Memoization)

from functools import wraps, lru_cache

# 簡(jiǎn)單的緩存實(shí)現(xiàn)
defcache(func):
    cached_data = {}
    
    @wraps(func)
    defwrapper(*args):
        if args notin cached_data:
            cached_data[args] = func(*args)
        return cached_data[args]
    
    wrapper.cache = cached_data
    return wrapper

@cache
deffibonacci(n):
    if n < 2:
        return n
    return fibonacci(n-1) + fibonacci(n-2)

# 使用內(nèi)置的lru_cache
@lru_cache(maxsize=128)
deffibonacci_builtin(n):
    if n < 2:
        return n
    return fibonacci_builtin(n-1) + fibonacci_builtin(n-2)

print(fibonacci(30))  # 快速計(jì)算
print(fibonacci.cache)  # 查看緩存

5. 重試裝飾器

from functools import wraps
import time
import random

defretry(max_attempts=3, delay=1, backoff=2):
    defdecorator(func):
        @wraps(func)
        defwrapper(*args, **kwargs):
            current_delay = delay
            last_exception = None
            
            for attempt in range(max_attempts):
                try:
                    return func(*args, **kwargs)
                except Exception as e:
                    last_exception = e
                    if attempt < max_attempts - 1:
                        print(f"嘗試 {attempt + 1} 失敗,{current_delay}秒后重試...")
                        time.sleep(current_delay)
                        current_delay *= backoff
            
            raise last_exception
        
        return wrapper
    return decorator

@retry(max_attempts=3, delay=1, backoff=2)
defunstable_api_call():
    if random.random() < 0.7:
        raise Exception("API調(diào)用失敗")
    return"成功"

result = unstable_api_call()

6. 權(quán)限驗(yàn)證裝飾器

from functools import wraps

defrequire_permission(*required_perms):
    defdecorator(func):
        @wraps(func)
        defwrapper(user, *args, **kwargs):
            ifnot hasattr(user, 'permissions'):
                raise PermissionError("用戶無(wú)權(quán)限屬性")
            
            user_perms = set(user.permissions)
            required = set(required_perms)
            
            ifnot required.issubset(user_perms):
                raise PermissionError(f"用戶缺少權(quán)限:{required - user_perms}")
            
            return func(user, *args, **kwargs)
        
        return wrapper
    return decorator

classUser:
    def__init__(self, name, permissions):
        self.name = name
        self.permissions = permissions

@require_permission('admin', 'delete')
defdelete_user(user, user_id):
    returnf"{user.name} 刪除了用戶 {user_id}"

admin_user = User("Admin", ['admin', 'delete', 'read', 'write'])
delete_user(admin_user, 123)  # 成功

7. 速率限制裝飾器

from functools import wraps
import time
from collections import defaultdict

defrate_limit(calls_per_second=1):
    min_interval = 1.0 / calls_per_second
    last_called = [0.0]
    
    defdecorator(func):
        @wraps(func)
        defwrapper(*args, **kwargs):
            elapsed = time.time() - last_called[0]
            if elapsed < min_interval:
                time.sleep(min_interval - elapsed)
            
            last_called[0] = time.time()
            return func(*args, **kwargs)
        
        return wrapper
    return decorator

@rate_limit(calls_per_second=2)
defapi_call():
    print(f"API調(diào)用時(shí)間:{time.time()}")
    return"成功"

for _ in range(5):
    api_call()

8. 方法裝飾器和類裝飾器

from functools import wraps

# 方法裝飾器
defmethod_logger(func):
    @wraps(func)
    defwrapper(self, *args, **kwargs):
        print(f"調(diào)用方法 {self.__class__.__name__}.{func.__name__}")
        return func(self, *args, **kwargs)
    return wrapper

# 類裝飾器
defadd_str_repr(cls):
    def__str__(self):
        attrs = ', '.join(f"{k}={v}"for k, v in self.__dict__.items())
        returnf"{cls.__name__}({attrs})"
    
    cls.__str__ = __str__
    return cls

@add_str_repr
classPerson:
    def__init__(self, name, age):
        self.name = name
        self.age = age
    
    @method_logger
    defgreet(self):
        returnf"你好,我是{self.name}"

person = Person("Alice", 25)
print(person)  # Person(name=Alice, age=25)
person.greet()  # 調(diào)用方法 Person.greet

三、高級(jí)裝飾器模式

9. 可選參數(shù)的裝飾器

from functools import wraps

defsmart_decorator(func=None, *, enabled=True):
    defdecorator(f):
        ifnot enabled:
            return f
        
        @wraps(f)
        defwrapper(*args, **kwargs):
            print("裝飾器生效")
            return f(*args, **kwargs)
        return wrapper
    
    if func isNone:
        # 被調(diào)用時(shí)帶參數(shù):@smart_decorator(enabled=True)
        return decorator
    else:
        # 被調(diào)用時(shí)不帶參數(shù):@smart_decorator
        return decorator(func)

@smart_decorator
deffunc1():
    return"func1"

@smart_decorator(enabled=False)
deffunc2():
    return"func2"

10. 鏈?zhǔn)窖b飾器

defdecorator_a(func):
    @wraps(func)
    defwrapper(*args, **kwargs):
        print("A前")
        result = func(*args, **kwargs)
        print("A后")
        return result
    return wrapper

defdecorator_b(func):
    @wraps(func)
    defwrapper(*args, **kwargs):
        print("B前")
        result = func(*args, **kwargs)
        print("B后")
        return result
    return wrapper

@decorator_a
@decorator_b
defmy_func():
    print("執(zhí)行函數(shù)")
    return"結(jié)果"

my_func()
# 輸出:
# A前
# B前
# 執(zhí)行函數(shù)
# B后
# A后

四、結(jié)尾

裝飾器是Python中最強(qiáng)大的工具之一,也是代碼復(fù)用和關(guān)注點(diǎn)分離的最佳實(shí)踐。從簡(jiǎn)單的日志記錄到復(fù)雜的權(quán)限驗(yàn)證,裝飾器都能優(yōu)雅地解決問題。然而,要記住裝飾器的目的是讓代碼更清晰、更易維護(hù)。過度使用裝飾器反而會(huì)增加代碼復(fù)雜性。

責(zé)任編輯:趙寧寧 來(lái)源: Python數(shù)智工坊
相關(guān)推薦

2025-10-09 01:33:00

2024-06-07 08:51:50

OpenPyXLPythonExcel文件

2024-09-06 17:45:55

Linux磁盤

2023-11-08 08:32:16

2025-06-27 06:30:08

2023-05-09 08:34:51

PythonWith語(yǔ)句

2024-04-11 14:00:28

2025-01-16 10:46:31

2025-07-17 13:52:57

通配符Linux命令行

2025-03-26 08:01:18

2025-01-07 14:42:09

2025-08-27 04:15:00

LlamaIndexRAG數(shù)據(jù)源

2025-10-17 07:05:00

Python數(shù)據(jù)可視化數(shù)據(jù)科學(xué)

2025-04-11 02:30:00

2025-09-29 01:50:00

2025-08-05 07:26:06

2023-02-07 07:47:52

Python裝飾器函數(shù)

2025-06-23 10:20:00

開源機(jī)器學(xué)習(xí)PyTorch

2024-02-26 08:52:20

Python傳遞函數(shù)參數(shù)參數(shù)傳遞類型
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)