Files
Obsidian-Main/21.01. Programming/Python/decorator.md

1.6 KiB

在decorator內取得function的default argument與class member

import sys
import inspect
from functools import wraps


def exampleDecorator(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        print(f"Decorator: call by {func.__name__}")
        def get_default_args(func):
            signature = inspect.signature(func)
            return {
                k: v.default for k, v in signature.parameters.items() if v.default is not inspect.Parameter.empty
            }

        ## Get default
        defaultKwargs = get_default_args(func)
        defaultKwargs.update(kwargs)
        print(f"Decorator: args = {args}, kwargs = {kwargs}, defaultKwargs = {defaultKwargs}")

        objectInstance = args[0]
        if hasattr(objectInstance, 'defaultArg1'):
            print(f'objectInstance has defaultArg1, a.defaultArg1({type(objectInstance.defaultArg1)}) = {objectInstance.defaultArg1}')
            if objectInstance.defaultArg1:
                ## Do something here
                print("Decorator: some message...")
        else:
            print('objectInstance does not have defaultArg1')

        return func(*args, **kwargs)
    return wrapper


class ExampleClass():
    def __init__(self, defaultArg1=True, defaultArg2="SomeString"):
        self.defaultArg1 = defaultArg1
        self.defaultArg2 = defaultArg2
        print(f'self.defaultArg1 = {self.defaultArg1}, self.defaultArg2 = {self.defaultArg2}')

    @exampleDecorator
    def run(self, arg1=1, arg2=2):
        print(f"ExampleClass.run(), arg1 = {arg1}, arg2 = {arg2}")

example = ExampleClass()
example.run()