zoukankan      html  css  js  c++  java
  • Python 函数内省

    函数内省(function introspection)

    除了__doc__属性, 函数对象还有很多属性,对于下面的函数,可以使用dir()查看函数具有的属性:

    def factorial(n):
        return 1 if n == 1 else n*factorial(n - 1)
    >>> dir(factorial)
    ['__annotations__', '__call__', '__class__', '__closure__', '__code__', 
    '__defaults__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', 
    '__format__', '__ge__', '__get__', '__getattribute__', '__globals__', '__gt__',
     '__hash__', '__init__', '__kwdefaults__', '__le__', '__lt__', '__module__', 
    '__name__', '__ne__', '__new__', '__qualname__', '__reduce__', 
    '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', 
    '__subclasshook__']

    其中大多数是Python常规类都有的属性,下面重点看看常规对象没有而函数对象有的属性:

    >>> class C:pass
    ... 
    >>> obj = C()
    >>> def func():pass
    ... 
    >>> sorted(set(dir(func)) - set(dir(obj))) # 计算差集,然后排序
    ['__annotations__', '__call__', '__closure__', '__code__', '__defaults__', '__get__', '__globals__', '__kwdefaults__', '__name__', '__qualname__']

    对于上面列出的函数特有属性,说明如下:

    接下来我们讨论__defaults__, __code__, __annotations__的作用

    (一) __defaults__, __code__:

    函数对象有个__defaults__属性,他的值是一个元组,里面保存着定位参数和关键字参数的默认值。然而,参数的名称在__code__属性中, 它的值是一个code对象引用,自身也有很多属性

    仅限关键字参数的默认值在__kwdefaults__属性中,

    我们借用下面的示例说明这些属性的用途:

    def clip(text=None, max_length=80):
        """
        Return text clipped at the last space before or after max_len
        """
        end = None
        if len(text) > max_length:
            space_before = text.rfind(' ', 0, max_length)
            if space_before >= 0:
                end = space_before
            else:
                space_after = text.rfind(' ', max_length)
                if space_after >= 0:
                    end = space_after
    
            if end is None:
                end = len(text)
    
            return text[:end].rstrip()

    提取clip函数参数的信息:

    >>> from Example5_15 import clip
    >>> clip.__defaults__
    (None, 80)
    >>> clip.__code__
    <code object clip at 0x7f8e50658f60, file "/root/python_demo/Example5_15.py", line 1>
    >>> clip.__code__.co_varnames
    ('text', 'max_length', 'end', 'space_before', 'space_after')
    >>> clip.__code__.co_argcount
    2

    从控制台信息可以看出,__code__.co_varnames包含函数参数,并且还包含函数体中的局部变量,函数参数个数由__code__.co_argcount确定(这里不包含前缀为*或者**的变长参数)

    从这些属性提取参数信息并不是很方便,我们有更好的方式-------使用inspect模块:

    >>> from inspect import signature
    >>> sig = signature(clip)
    >>> sig
    <Signature (text=None, max_length=80)>
    >>> for name, param in sig.parameters.items():
    ...     print(param.kind, ':', name, '=', param.default)
    ... 
    POSITIONAL_OR_KEYWORD : text = None
    POSITIONAL_OR_KEYWORD : max_length = 80

    这样就好多了, Inspect.signature 函数返回一个inspect.Signature对象,它有一个parameter属性,这是一个有序映射,把参数名和inspect.Parameter对象对应起来,各个Parameter属性也有自己的属性,比如name, default, kind

    如果是非默认值参数,特殊的inspect._empty值表示没有默认值,考虑到上面例子的None是有效默认值,这样处理是合理的

    (二) __annotations__属性:

    我们把上面的clip函数添加注解,如下所示:

    def clip(text: str =None, max_length: 'int > 0'=80) -> str:
        """
        :return text clipped at the last space before or after max_len
        :param text:
        :param max_length:
        """
        end = None
        if len(text) > max_length:
            space_before = text.rfind(' ', 0, max_length)
            if space_before >= 0:
                end = space_before
            else:
                space_after = text.rfind(' ', max_length)
                if space_after >= 0:
                    end = space_after
    
            if end is None:
                end = len(text)
    
            return text[:end].rstrip()

    注意函数头部的第一行

    函数声明中的各个参数可以在:之后添加注解,添加注解的方法:

    (1)参数有默认值,注解放在参数名和=号之间

    (2)返回值,在)和函数声明尾部的:之间添加->和一个表达式,表达式可以是任何类型

    对于注解,Python解释器不做任何处理,只是存储在__annotations__属性(字典形式)中:

    >>> from Example5_15 import clip
    >>> clip.__annotations__
    {'return': <class 'str'>, 'max_length': 'int > 0', 'text': <class 'str'>}
  • 相关阅读:
    HDU 1166 敌兵布阵
    HDU 1397 Goldbach's Conjecture
    VC 界面库皮肤库
    入门基础VC网络编程入门
    入门基础VC网络编程入门(2)
    线程 消息循环
    BMP文件的读取
    Microsoft SQL Server 2008 Enterprise Edition 简体中文企业版
    成功采用设计模式的步骤
    vs2010调试
  • 原文地址:https://www.cnblogs.com/z-joshua/p/7793580.html
Copyright © 2011-2022 走看看