클로저와 데코레이터는 더 유연하고 재사용 가능한 코드를 작성할 수 있게 해주는 Python의 강력한 기능입니다. 이러한 개념을 이해하면 Python 기술을 한 단계 더 발전시켜 로깅, 액세스 제어, 메모와 같은 보다 복잡한 시나리오를 쉽게 처리할 수 있습니다.
이 블로그 게시물에서 살펴볼 내용은 다음과 같습니다.
이 글을 마치면 클로저와 데코레이터에 대해 확실히 이해하고 이를 자신의 코드에 효과적으로 적용할 수 있을 것입니다.
Python에서 클로저는 외부 함수의 실행이 완료된 경우에도 바깥쪽 어휘 범위의 변수 값을 유지하는 함수입니다. 클로저는 함수 호출 간에 상태를 유지하는 방법이므로 일부 컨텍스트를 유지해야 하는 시나리오에 유용합니다.
클로저는 세 가지 주요 구성 요소로 구성됩니다.
다음은 간단한 종료의 예입니다.
def outer_function(message): def inner_function(): print(message) return inner_function # Create a closure closure = outer_function("Hello, World!") closure() # Output: Hello, World!
이 예에서 inner_function은 external_function의 실행이 완료된 후에도 external_function의 메시지 변수를 참조합니다. 내부 함수는 외부 범위의 변수를 "닫습니다". 따라서 클로저라는 용어가 사용됩니다.
클로저는 자유 변수의 상태를 캡처하고 이를 함수 객체의 __closure__ 속성에 저장하는 방식으로 작동합니다.
이전 예의 클로저를 살펴보겠습니다.
print(closure.__closure__[0].cell_contents) # Output: Hello, World!
__closure__ 속성은 클로저가 유지하는 변수에 대한 참조를 보유합니다. 각 변수는 "셀"에 저장되며 cell_contents를 사용하여 해당 내용에 액세스할 수 있습니다.
클로저는 전역 변수나 클래스를 사용하지 않고 함수 호출 사이의 상태를 유지하려는 경우 특히 유용합니다. 다음은 몇 가지 일반적인 사용 사례입니다.
클로저를 사용하여 동적으로 함수를 생성할 수 있습니다.
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
이 예에서 multiplier는 주어진 숫자에 특정 요소를 곱하는 함수를 반환합니다. 클로저 times_two 및 times_3은 포함 범위의 요소 값을 유지합니다.
클로저를 사용하면 내부 상태를 노출하지 않고 동작을 캡슐화할 수 있습니다. 이는 객체지향 프로그래밍의 프라이빗 메소드 개념과 유사합니다.
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
이 예에서 count 변수는 클로저 내에 캡슐화되어 있으며 증분 함수만 해당 값을 수정할 수 있습니다.
데코레이터는 원래 함수의 코드를 수정하지 않고 다른 함수를 가져와 해당 동작을 확장하거나 변경하는 함수입니다. 데코레이터는 함수 및 메서드에 로깅, 액세스 제어, 타이밍 등의 기능을 추가하는 데 자주 사용됩니다.
Python에서는 함수 정의 위에 @ 기호를 사용하여 함수에 데코레이터를 적용합니다.
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!
여기서 decorator_function은 say_hello에 적용되어 say_hello()가 실행되기 전에 추가 기능을 추가합니다.
데코레이터는 본질적으로 Python의 일반적인 패턴, 즉 다른 함수를 인수로 사용하는 고차 함수에 대한 구문 설탕입니다. @ decorator를 작성하면 다음과 같습니다.
say_hello = decorator_function(say_hello)
데코레이터 함수는 원래 함수의 동작을 확장하는 새로운 함수(wrapper_function)를 반환합니다.
데코레이트되는 함수가 인수를 사용하는 경우 래퍼 함수는 인수를 전달하기 위해 *args 및 **kwargs를 허용해야 합니다.
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은 @staticmethod, @classmethod 및 @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!
위 내용은 Python의 클로저와 데코레이터 익히기: 기초부터 고급까지의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!