def log_decorator(func):
def wrapper(*args, **kwargs):
print(f"Calling {func.__name__} with args: {args}, kwargs: {kwargs}")
result = func(*args, **kwargs)
print(f"{func.__name__} returned: {result}")
return result
return wrapper
@log_decorator
def add(a, b):
return a + b
@log_decorator
def greet(name, greeting="Hello"):
return f"{greeting}, {name}!"
add(5, 10)
greet("Alice", greeting="Hi")
데코레이터가 다음과 같이 사용될 수 있음;
출력 형태
Calling add with args: (5, 10), kwargs: {}
add returned: 15
Calling greet with args: ('Alice',), kwargs: {'greeting': 'Hi'}
greet returned: Hi, Alice!
초기 프로젝트 진행 시 데코레이터를 통해 확장성, 관리를 하고자 한다면, 임의의 파라미터의 개수, 이름, 형식을 미리 지정하는 것이 아닌, *args **kwargs 로 받아와서 사용해야 겠다....
현재 data_processing 의 내용을 구현했음, decorator 를 통해 데이터 형식에 대한 검증, 확인이 앞으로 필요하게 될텐데, 이를 decorator 를 통해 추가, 구현 해보자
class AccumulateDecorator:
def __init__(self, func):
self.func = func
self.accumulated_args = []
self.accumulated_kwargs = {}
def __call__(self, *args, **kwargs):
# 새로운 인자를 누적합니다.
self.accumulated_args.extend(args)
for key, value in kwargs.items():
self.accumulated_kwargs[key] = value
# 지금까지 누적된 모든 인자를 사용하여 함수를 호출합니다.
return self.func(*self.accumulated_args, **self.accumulated_kwargs)
# 함수에 데코레이터를 적용합니다.
@AccumulateDecorator
def display_accumulated(*args, **kwargs):
print("Args:", args)
print("Kwargs:", kwargs)
# 첫 번째 호출: 인자 1개 전달
display_accumulated(1)
# 두 번째 호출: 인자 2개 전달
display_accumulated(2, 3)
# 세 번째 호출: 키워드 인자 전달
display_accumulated(a=4, b=5)
Args: (1,)
Kwargs: {}
Args: (1, 2, 3)
Kwargs: {}
Args: (1, 2, 3)
Kwargs: {'a': 4, 'b': 5}
인자가 전달되고 누적되는 형식의 확인...
class AccumulateDecorator:
def __init__(self, func):
self.func = func
self.accumulated_args = []
self.accumulated_kwargs = {}
print(f"AccumulateDecorator 인스턴스가 생성되었습니다: {self}")
def __call__(self, *args, **kwargs):
# 새로운 인자를 누적합니다.
self.accumulated_args.extend(args)
for key, value in kwargs.items():
self.accumulated_kwargs[key] = value
# 지금까지 누적된 모든 인자를 사용하여 함수를 호출합니다.
return self.func(*self.accumulated_args, **self.accumulated_kwargs)
@AccumulateDecorator
def display_accumulated_one(*args, **kwargs):
print("display_accumulated_one - Args:", args)
print("display_accumulated_one - Kwargs:", kwargs)
@AccumulateDecorator
def display_accumulated_two(*args, **kwargs):
print("display_accumulated_two - Args:", args)
print("display_accumulated_two - Kwargs:", kwargs)
# 두 함수에 대해 각각 호출
display_accumulated_one(1)
display_accumulated_one(2)
display_accumulated_two(10)
display_accumulated_two(20)
출력
AccumulateDecorator 인스턴스가 생성되었습니다: <__main__.AccumulateDecorator object at 0x7f3a0c1fbd90>
display_accumulated_one - Args: (1,)
display_accumulated_one - Kwargs: {}
display_accumulated_one - Args: (1, 2)
display_accumulated_one - Kwargs: {}
AccumulateDecorator 인스턴스가 생성되었습니다: <__main__.AccumulateDecorator object at 0x7f3a0c1fbee0>
display_accumulated_two - Args: (10,)
display_accumulated_two - Kwargs: {}
display_accumulated_two - Args: (10, 20)
display_accumulated_two - Kwargs: {}
데코레이터는 데코레이터를 사용하는 함수, 메서드에 종속된다.
클래스 위에서도 데코레이터의 호출이 가능...
클래스 데코레이터는 클래스의 정의를 수정하거나 확장하는 데 사용됩니다. 함수 데코레이터와 마찬가지로, 클래스 데코레이터도 클래스의 동작을 변경하거나 추가적인 기능을 부여하는 데 활용됩니다.
def log_methods(cls):
original_methods = {k: v for k, v in cls.__dict__.items() if callable(v)}
for name, method in original_methods.items():
def logged_method(self, *args, **kwargs):
print(f"Method {name} is called with arguments: {args} {kwargs}")
return method(self, *args, **kwargs)
setattr(cls, name, logged_method)
return cls
@log_methods
class Example:
def greet(self, name):
print(f"Hello, {name}!")
def farewell(self, name):
print(f"Goodbye, {name}!")
# 인스턴스 생성 및 메서드 호출
example = Example()
example.greet("Alice")
example.farewell("Bob")
출력
Method greet is called with arguments: ('Alice',) {}
Hello, Alice!
Method farewell is called with arguments: ('Bob',) {}
Goodbye, Bob!
k와 v는 클래스의 __dict__.items() 메서드로 반환된 항목의 키와 값입니다. 클래스의 __dict__ 속성은 클래스에 정의된 모든 속성과 메서드를 포함하는 사전(dictionary)입니다. 이 사전의 items() 메서드는 (키, 값) 쌍으로 이루어진 이터러블 객체(dict_items)를 반환합니다.
k와 v의 역할:
- k (Key): 클래스 속성의 이름(문자열)입니다. 예를 들어, 클래스의 메서드 이름이나 클래스 변수 이름이 k에 해당합니다.
- v (Value): 해당 속성의 실제 객체입니다. 예를 들어, 메서드 객체, 클래스 변수 값 등이 v에 해당합니다.
Example.__dict__.items()의 결과
Example.__dict__.items()는 Example 클래스의 속성들을 (키, 값) 쌍으로 반환합니다. 아래는 이 예제 클래스에서 k와 v에 저장되는 값들입니다.
- 첫 번째 항목:
- k: "__module__"
- v: "__main__"
- 설명: 이 항목은 클래스가 정의된 모듈의 이름을 나타냅니다.
- 두 번째 항목:
- k: "class_variable"
- v: 42
- 설명: class_variable 속성의 이름이 k에 저장되고, 그 값인 42가 v에 저장됩니다.
- 세 번째 항목:
- k: "greet"
- v: <function Example.greet at 0x...>
- 설명: greet 메서드의 이름이 k에 저장되고, greet 메서드 자체가 v에 저장됩니다. 이 값은 함수 객체로서, 메모리 주소를 포함합니다.
- 네 번째 항목:
- k: "farewell"
- v: <function Example.farewell at 0x...>
- 설명: farewell 메서드의 이름이 k에 저장되고, farewell 메서드 자체가 v에 저장됩니다.
- 다른 항목들:
- k: "__dict__", "__weakref__", "__doc__" 등의 특별한(기본적으로 포함된) 클래스 속성들이 있습니다.
- v: 이들 속성의 값들입니다. 예를 들어, __dict__는 클래스의 속성들을 담은 사전이고, __doc__는 클래스의 문서 문자열입니다.
설명:
- **k**에는 속성 이름이, **v**에는 해당 속성의 값이 저장됩니다.
- greet와 farewell 메서드는 callable(v) 조건을 통과하는 항목들입니다. 그 외의 class_variable과 특별 속성(__module__, __dict__, __doc__ 등)은 callable(v) 조건에 의해 필터링됩니다.
이로써, k와 v가 각각 클래스의 속성 이름과 속성 값이라는 것을 알 수 있습니다. 이 정보는 클래스의 메서드나 특정 속성만을 필터링하여 작업을 수행하는 데 유용합니다.
실제 적용하려면... data_processing 클래스 내에는 각 함수가 존재. 클래스에 데코레이터를 지정하고 실행, 관리를 하는게 나을려나...
아니면 각 함수위에 데코레이터를 작성할지.
데이터 전처리 시 객체를 생성하지 않으므로 data_processing 클래스 자체는 필요 없을 수 있겠네.
data_processing 클래스는 만들지말고 함수들을 만들어놓고 사용하자.
다른 Framework 에서도 이러한 방식을 사용하는 것을 확인
from data_processing import method_name
을 통해 호출하고,
data_processing_method 가 반드시 포함되어야 할 작업들의 데코레이터 작성, 적용
데이터 검증 decorator 를 작성하자
논리적 경로명의 적용, 실제 파일 위치와는 상관없이 함수, 클래스에 논리적 경로명을 지정하여 해당 경로로 사용자가 접근할 수 있도록
'dev_AI_framework' 카테고리의 다른 글
모델 모듈의 개발 (0) | 2024.08.22 |
---|---|
디렉토리 내 __init__ 파일의 역할 (0) | 2024.08.21 |
기존 FrameWork model 확인 - LinearRegression ( 데이터 검증, 희소 행렬에 대해 알게 되었다 ) (0) | 2024.08.09 |
sklearn : _rescale_data ( sparse_matrix, inplace ) (0) | 2024.08.09 |
sklearn : _preprocess_data ( 전처리 및 중앙값 제거 ) (0) | 2024.08.09 |