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:
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.
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:
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.
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.
Penutupan amat berguna apabila anda ingin mengekalkan keadaan antara panggilan fungsi tanpa menggunakan pembolehubah atau kelas global. Berikut ialah beberapa kes penggunaan biasa:
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.
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.
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.
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.
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.
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)
Python menyediakan beberapa penghias terbina dalam, seperti @staticmethod, @classmethod dan @property.
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'>
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
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.
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 can also accept their own arguments. This is useful when you need to pass configuration values to the decorator.
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.
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
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
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!
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!