Rumah >pembangunan bahagian belakang >Tutorial Python >Menguasai Penutupan dan Penghias dalam Python: Daripada Asas kepada Lanjutan

Menguasai Penutupan dan Penghias dalam Python: Daripada Asas kepada Lanjutan

DDD
DDDasal
2024-09-19 01:39:33653semak imbas

Mastering Closures and Decorators in Python: From Basics to Advanced

pengenalan

Penutupan dan penghias ialah ciri berkuasa dalam Python yang membolehkan anda menulis kod yang lebih fleksibel dan boleh digunakan semula. Memahami konsep ini akan membawa kemahiran Python anda ke peringkat seterusnya, membolehkan anda mengendalikan senario yang lebih kompleks seperti pengelogan, kawalan akses dan hafalan dengan mudah.

Dalam catatan blog ini, kami akan meneroka:

  1. Apakah itu penutupan?
  2. Memahami cara penutupan berfungsi dalam Python
  3. Gunakan bekas untuk penutupan
  4. Apakah itu penghias?
  5. Memahami cara penghias berfungsi
  6. Menggunakan penghias terbina dalam
  7. Menulis penghias tersuai
  8. Konsep lanjutan dengan penghias

Menjelang akhir artikel ini, anda akan mempunyai pemahaman yang kukuh tentang penutup dan penghias, dan anda akan dapat menerapkannya dengan berkesan dalam kod anda sendiri.

Apakah Penutupan?

Dalam Python, penutupan ialah fungsi yang mengekalkan nilai pembolehubah daripada skop leksikal yang disertakan walaupun fungsi luar telah selesai dilaksanakan. Penutupan ialah cara untuk mengekalkan keadaan antara panggilan fungsi, yang menjadikannya berguna untuk senario di mana anda perlu mengekalkan beberapa konteks.

Penutupan terdiri daripada tiga komponen utama:

  1. Fungsi bersarang
  2. Rujukan kepada pembolehubah bebas dalam fungsi lampiran
  3. Fungsi lampiran telah selesai dilaksanakan, tetapi fungsi bersarang masih mengingati keadaan pembolehubah bebas.

Contoh Asas Penutupan

Berikut ialah contoh penutupan mudah:

def outer_function(message):
    def inner_function():
        print(message)
    return inner_function

# Create a closure
closure = outer_function("Hello, World!")
closure()  # Output: Hello, World!

Dalam contoh ini, inner_function merujuk pembolehubah mesej daripada outer_function, walaupun selepas outer_function telah selesai dilaksanakan. Fungsi dalaman "menutup" pembolehubah dari skop luar, oleh itu istilah penutupan.

Cara Penutupan Berfungsi Secara Dalaman

Penutupan berfungsi dengan menangkap keadaan pembolehubah bebas dan menyimpannya dalam atribut __closure__ objek fungsi.

Mari kita periksa penutupan daripada contoh sebelumnya:

print(closure.__closure__[0].cell_contents)  # Output: Hello, World!

Atribut __closure__ memegang rujukan kepada pembolehubah yang dikekalkan oleh penutupan. Setiap pembolehubah disimpan dalam "sel", dan anda boleh mengakses kandungannya dengan cell_contents.

Gunakan Sarung untuk Penutupan

Penutupan amat berguna apabila anda ingin mengekalkan keadaan antara panggilan fungsi tanpa menggunakan pembolehubah atau kelas global. Berikut ialah beberapa kes penggunaan biasa:

1. Fungsi Kilang

Anda boleh menggunakan penutupan untuk mencipta fungsi secara dinamik.

def multiplier(factor):
    def multiply_by_factor(number):
        return number * factor
    return multiply_by_factor

times_two = multiplier(2)
times_three = multiplier(3)

print(times_two(5))  # Output: 10
print(times_three(5))  # Output: 15

Dalam contoh ini, pengganda mengembalikan fungsi yang mendarab nombor tertentu dengan faktor tertentu. Penutupan kali_dua dan kali_tiga mengekalkan nilai faktor daripada skop lampirannya.

2. Ekapsulasi

Penutupan membolehkan anda merangkum tingkah laku tanpa mendedahkan keadaan dalaman. Ini serupa dengan konsep kaedah persendirian dalam pengaturcaraan berorientasikan objek.

def counter():
    count = 0
    def increment():
        nonlocal count
        count += 1
        return count
    return increment

counter_fn = counter()
print(counter_fn())  # Output: 1
print(counter_fn())  # Output: 2

Dalam contoh ini, pembolehubah kiraan dirangkumkan dalam penutupan dan hanya fungsi kenaikan boleh mengubah suai nilainya.

Apa Itu Penghias?

penghias ialah fungsi yang mengambil fungsi lain dan memanjangkan atau mengubah kelakuannya tanpa mengubah suai kod fungsi asal. Penghias selalunya digunakan untuk menambah kefungsian seperti pengelogan, kawalan akses atau pemasaan pada fungsi dan kaedah.

Dalam Python, penghias digunakan pada fungsi menggunakan simbol @ di atas definisi fungsi.

Contoh Asas Seorang Penghias

def decorator_function(original_function):
    def wrapper_function():
        print(f"Wrapper executed before {original_function.__name__}()")
        return original_function()
    return wrapper_function

@decorator_function
def say_hello():
    print("Hello!")

say_hello()

# Output:
# Wrapper executed before say_hello()
# Hello!

Di sini, decorator_function digunakan untuk say_hello, menambahkan fungsi tambahan sebelum say_hello() dilaksanakan.

Cara Penghias Berfungsi

Penghias pada asasnya ialah gula sintaksis untuk corak biasa dalam Python: fungsi tertib tinggi, yang mengambil fungsi lain sebagai hujah. Apabila anda menulis @decorator, ia bersamaan dengan:

say_hello = decorator_function(say_hello)

Fungsi penghias mengembalikan fungsi baharu (fungsi_pembungkus), yang memanjangkan gelagat fungsi asal.

Penghias dengan Hujah

Jika fungsi yang dihias mengambil argumen, fungsi pembungkus perlu menerima *args dan **kwargs untuk menyampaikan hujah bersama.

def decorator_function(original_function):
    def wrapper_function(*args, **kwargs):
        print(f"Wrapper executed before {original_function.__name__}()")
        return original_function(*args, **kwargs)
    return wrapper_function

@decorator_function
def display_info(name, age):
    print(f"display_info ran with arguments ({name}, {age})")

display_info("John", 25)

# Output:
# Wrapper executed before display_info()
# display_info ran with arguments (John, 25)

Penghias Terbina Dalam dalam Python

Python menyediakan beberapa penghias terbina dalam, seperti @staticmethod, @classmethod dan @property.

@staticmethod and @classmethod

These decorators are commonly used in object-oriented programming to define methods that are either not bound to the instance (@staticmethod) or bound to the class itself (@classmethod).

class MyClass:
    @staticmethod
    def static_method():
        print("Static method called")

    @classmethod
    def class_method(cls):
        print(f"Class method called from {cls}")

MyClass.static_method()   # Output: Static method called
MyClass.class_method()    # Output: Class method called from <class '__main__.MyClass'>

@property

The @property decorator allows you to define a method that can be accessed like an attribute.

class Circle:
    def __init__(self, radius):
        self._radius = radius

    @property
    def radius(self):
        return self._radius

    @radius.setter
    def radius(self, value):
        if value <= 0:
            raise ValueError("Radius must be positive")
        self._radius = value

c = Circle(5)
print(c.radius)  # Output: 5

c.radius = 10
print(c.radius)  # Output: 10

Writing Custom Decorators

You can write your own decorators to add custom functionality to your functions or methods. Decorators can be stacked, meaning you can apply multiple decorators to a single function.

Example: Timing a Function

Here’s a custom decorator that measures the execution time of a function:

import time

def timer_decorator(func):
    def wrapper(*args, **kwargs):
        start_time = time.time()
        result = func(*args, **kwargs)
        end_time = time.time()
        print(f"{func.__name__} ran in {end_time - start_time:.4f} seconds")
        return result
    return wrapper

@timer_decorator
def calculate_square(numbers):
    result = [n * n for n in numbers]
    return result

nums = range(1, 1000000)
calculate_square(nums)

Decorators with Arguments

Decorators can also accept their own arguments. This is useful when you need to pass configuration values to the decorator.

Example: Logger with Custom Message

def logger_decorator(message):
    def decorator(func):
        def wrapper(*args, **kwargs):
            print(f"{message}: Executing {func.__name__}")
            return func(*args, **kwargs)
        return wrapper
    return decorator

@logger_decorator("DEBUG")
def greet(name):
    print(f"Hello, {name}!")

greet("Alice")

# Output:
# DEBUG: Executing greet
# Hello, Alice!

In this example, the decorator logger_decorator takes a message as an argument, and then it wraps the greet function with additional logging functionality.

Advanced Decorator Concepts

1. Decorating Classes

Decorators can be applied not only to functions but also to classes. Class decorators modify or extend the behavior of entire classes.

def add_str_repr(cls):
    cls.__str__ = lambda self: f"Instance of {cls.__name__}"
    return cls

@add_str_repr
class Dog:
    pass

dog = Dog()
print(dog)  # Output: Instance of Dog

2. Memoization with Decorators

Memoization is an optimization technique where the results of expensive function calls are cached, so subsequent calls with the same arguments can be returned faster.

def memoize(func):
    cache = {}
    def wrapper(*args):
        if args not in cache:
            cache[args] = func(*args)
        return cache[args]
    return wrapper

@memoize
def fibonacci(n):


 if n in [0, 1]:
        return n
    return fibonacci(n - 1) + fibonacci(n - 2)

print(fibonacci(30))  # Output: 832040

Conclusion

Closures and decorators are advanced Python concepts that unlock powerful capabilities for writing cleaner, more efficient code. Closures allow you to maintain state and encapsulate data, while decorators let you modify or extend the behavior of functions and methods in a reusable way. Whether you're optimizing performance with memoization, implementing access control, or adding logging, decorators are an essential tool in your Python toolkit.

By mastering these concepts, you'll be able to write more concise and maintainable code and handle complex programming tasks with ease.

Feel free to experiment with closures and decorators in your projects and discover how they can make your code more elegant and powerful!


Connect with Me

  • GitHub
  • Linkedin

Atas ialah kandungan terperinci Menguasai Penutupan dan Penghias dalam Python: Daripada Asas kepada Lanjutan. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn