Python: inspect

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

import inspect


def b(x, y: int = 5, *args, z, t=55, **kwargs) -> int:
    return x + y


signature = inspect.signature(b)

print(signature)
print(signature.parameters)

for i, (name, parameter) in enumerate(signature.parameters.items()):
    # name, parameter = item
    print(i + 1, name, parameter.annotation, parameter.kind, parameter.default)

    print(parameter.default is parameter.empty, end='\n' * 2)

 

print(x=5) 错在 x=5 是关键字传参, print函数没有定义x参数

 

 

import inspect, functools


def discretion(fn):
    @functools.wraps(fn)
    def wrapper(*args, **kwargs):
        signature = inspect.signature(fn)
        parameters = signature.parameters  # OrderedDict
        print(parameters)
        # OrderedDict([('x', < Parameter "x" >), ('y', < Parameter "y: int = 5" >), ('args', < Parameter "*args" >), ('z', < Parameter "z" >), ('t', < Parameter "t=55" >), ('kwargs', < Parameter "**kwargs" >)])
        # for parameter in parameters.values():
        #     print(parameter.name,parameter.annotation,parameter.kind,parameter.default)

        # 找到没有显式传递的默认值参数 ******* args, kwargs 不可能有默认值
        # def b(x, y: int = 5, *args, z=55, t, **kwargs): pass
        # 传递的默认值参数: 1. position 2. keyword only

        keys = tuple(parameters.keys())
        default_parameters = list(keys)  # 所有默认形参

        print(f'keys: {keys}')
        print(f'args: {args}')
        print(f'kwargs: {kwargs}')

        # position arguments
        for i, v in enumerate(args):
            name = keys[i]
            default_parameters.remove(name)

            if parameters[name].annotation is inspect._empty:
                continue  # 类型为空, 跳过检查
            if isinstance(v, parameters[name].annotation):
                print(f'name: {name}, value: {repr(v)}, type: {parameters[name].annotation}')
            else:
                raise TypeError(f'value {repr(v)} is not type {parameters[name].annotation}')

        # keyword arguments
        for k, v in kwargs.items():  # Refactor -> Extract Method 提取公共方法
            default_parameters.remove(k)

            if parameters[k].annotation is parameters[k].empty:
                continue
            if isinstance(v, parameters[k].annotation):
                print(f'name: {k}, value: {repr(v)}, type: {parameters[k].annotation}')
            else:
                raise TypeError(f'value {repr(v)} is not type {parameters[k].annotation}')

        # filter parameter using default
        if 'args' in default_parameters:
            default_parameters.remove('args')
        if 'kwargs' in default_parameters:
            default_parameters.remove('kwargs')

        for parameter in default_parameters:
            print(f'parameter {parameter} using default value {parameters[parameter].default}')

        ret = fn(*args, **kwargs)
        return ret

    return wrapper


@discretion
def b(x: int, y: str = '5') -> None:
    print(x, y)


# b('5', 5)
# b(4)  # y有默认值, discretion没做检查
# b(4, '5')

@discretion
def p(x, y: int = 5, *args, z=55, t, **kwargs):
    print(f'x: {x}, y: {y}, args: {args}, z: {z}, t: {t}, kwargs: {kwargs}')


# p(555, 22, 33, t=666)  # x: 555, y: 22, args: (33,), z: 55, t: 666, kwargs: {}

p(555, t=666)
# keys: ('x', 'y', 'args', 'z', 't', 'kwargs')
# args: (555,)
# kwargs: {'t': 666}

 

import inspect


def b(x, y: int = 55, *args, z=5, t, **kwargs):
    return 5


signature = inspect.signature(b)

for name, parameter in signature.parameters.items():
    print(list(signature.parameters.keys()))
    print(name, parameter.annotation)


class B:
    print(__qualname__)
    print(__name__)


B()


def p():
    print(inspect.stack()[0].filename)
    print(inspect.stack()[0].index)
    print(inspect.stack()[0].frame)
    print(inspect.stack()[0].function)
    print(inspect.stack()[0].code_context)
    print(inspect.stack()[0].lineno)
    for v in inspect.stack():
        print(v, '\n', type(v))
        print(v.function, type(v.function))


p()
import inspect


def myself():
    for frame_info in inspect.stack():
        print('~' * 60)
        print(frame_info)
        print(type(frame_info))
        print('~' * 60)
        for v in frame_info:
            print(type(v), v)
            print('#' * 60)
    return inspect.stack()[1][3]


myself()

 

import inspect, functools


def discretion(fn):
    @functools.wraps(fn)
    def wrapper(*args, **kwargs):
        signature = inspect.signature(fn)
        parameters = signature.parameters
        # OrderedDict([('x', <Parameter "x">), ('y', <Parameter "y: int = 7">), ('args', <Parameter "*args">), ('z', <Parameter "z=10">), ('t', <Parameter "t">), ('kwargs', <Parameter "**kwargs">)])
        # POSITIONAL_ONLY = _POSITIONAL_ONLY
        # POSITIONAL_OR_KEYWORD = _POSITIONAL_OR_KEYWORD
        # VAR_POSITIONAL = _VAR_POSITIONAL
        # KEYWORD_ONLY = _KEYWORD_ONLY
        # VAR_KEYWORD = _VAR_KEYWORD
        # print(parameters)
        keys = tuple(parameters.keys())
        default_parameters = list(keys)
        print(f'keys: {keys}')
        print(f'args: {args}')
        print(f'kwargs: {kwargs}')
        print('~' * 80)

        # positional
        print('{0}Dispose Positional Arguments{0}'.format('*' * 20))
        print()
        for i, v in enumerate(args):
            name = keys[i]
            if str(parameters[name].kind) == 'VAR_POSITIONAL':  # 进行到了*args, 此时参数name是VAR_POSITIONAL, 被*args收集, 暂不支持参数类型检查, type(parameters[name].kind) 不是 str
                break

            default_parameters.remove(name)  # 移除位置参数
            print('-->', 'removing', name, '-->', 'default_parameters:', default_parameters)
            if parameters[name].annotation is parameters[name].empty:
                continue
            if isinstance(v, parameters[name].annotation):
                print(f'--> passed --> name: {name}, value: {repr(v)}, type: {parameters[name].annotation}')
            else:
                raise TypeError(f'value {repr(v)} is not type {parameters[name].annotation}')
        print('~' * 80)

        # keyword
        print('{0}Dispose Keyword Arguments{0}'.format('*' * 20))
        print()
        for k, v in kwargs.items():
            default_parameters.remove(k)
            print('-->', 'removing', k, '-->', 'default_parameters:', default_parameters)
            if parameters[k].annotation is parameters[k].empty:
                continue
            if isinstance(v, parameters[k].annotation):
                print(f'--> passed --> name: {k}, value: {repr(v)}, type: {parameters[k].annotation}')
            else:
                raise TypeError(f'value: {repr(v)} is not type {parameters[name].annotation}')

        print('~' * 80)
        print('after dispose positional and keyword arguments, default_parameters:', default_parameters)
        for name in default_parameters:
            if str(parameters[name].kind) in ('VAR_POSITIONAL', 'VAR_KEYWORD'):
                default_parameters.remove(name)
        print('after removing default_parameters:', default_parameters)

        print('~' * 80)
        return fn(*args, **kwargs)

    return wrapper


@discretion
def vet(x, /, y: int = 7, *args, z=10, t: int, **kwargs) -> int:
    print(f'x: {x}, y: {y}, args: {args}, z: {z}, t: {t}, kwargs: {kwargs}')
    return 5


vet(555, 22, 33, 44, 55, t=666)

 

posted @ 2022-02-27 21:32  ascertain  阅读(85)  评论(0编辑  收藏  举报