在 Python 中,函数(function)是一种对象,因此它拥有许多内置属性(attributes)。这些属性可以用于获取函数的元信息(如名称、文档字符串、参数等),或者在装饰器、反射等场景中动态操作函数。
1. 常用函数属性
以下是一些常见的函数属性:
属性说明示例
__name__函数的名字func.__name__ → "func"
__doc__函数的文档字符串(docstring)func.__doc__
__module__函数所在的模块名func.__module__ → "__main__"
__annotations__函数的类型注解(Python 3+){"x": int, "return": str}
__defaults__默认参数值(元组形式)(3,)(如果 def f(x=3))
__kwdefaults__关键字参数的默认值(Python 3+){"y": 5}(如果 def f(*, y=5))
__code__函数的字节码对象(code 对象)func.__code__.co_varnames
__globals__函数所在的全局命名空间func.__globals__
__closure__闭包变量(cell 对象,用于嵌套函数)func.__closure__
2. 查看函数的所有属性
可以使用 dir(func) 查看函数的所有属性和方法:
python
defexample(x:int=1)->str:"""示例函数"""returnstr(x)print(dir(example))
输出(部分):
python
['__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__']
3. 关键属性详解
(1) __name__:获取函数名
python
defgreet():passprint(greet.__name__)# 输出: "greet"
(2) __doc__:获取文档字符串
python
defgreet():"""这是一个问候函数"""passprint(greet.__doc__)# 输出: "这是一个问候函数"
(3) __annotations__:获取类型注解(Python 3+)
python
defadd(x:int,y:int)->int:returnx+yprint(add.__annotations__)# 输出: {'x': <class 'int'>, 'y': <class 'int'>, 'return': <class 'int'>}
(4) __defaults__ 和 __kwdefaults__:获取默认参数
python
defgreet(name,age=18,*,city="Beijing"):passprint(greet.__defaults__)# 输出: (18,)print(greet.__kwdefaults__)# 输出: {'city': 'Beijing'}
(5) __code__:获取字节码信息
__code__ 是一个 code 对象,包含函数的字节码信息,例如:
co_varnames:局部变量名
co_argcount:参数个数(不含 *args 和 **kwargs)
co_filename:函数所在的文件名
python
defadd(x,y):z=x+yreturnzprint(add.__code__.co_varnames)# 输出: ('x', 'y', 'z')print(add.__code__.co_argcount)# 输出: 2
4. 动态修改函数属性
由于函数是对象,我们可以动态修改它的属性:
python
defgreet():passgreet.author="Alice"# 自定义属性print(greet.author)# 输出: "Alice"
5. functools.wraps 保留原函数属性
在装饰器中,如果不使用 functools.wraps,被装饰的函数的 __name__、__doc__ 等属性会被覆盖:
python
fromfunctoolsimportwrapsdefmy_decorator(func):@wraps(func)# 保留原函数的属性defwrapper(*args,**kwargs):returnfunc(*args,**kwargs)returnwrapper@my_decoratordefgreet():"""Greet someone"""passprint(greet.__name__)# 输出: "greet"(而不是 "wrapper")print(greet.__doc__)# 输出: "Greet someone"
总结
属性用途
__name__获取函数名
__doc__获取文档字符串
__annotations__获取类型注解
__defaults__获取位置参数的默认值
__kwdefaults__获取关键字参数的默认值
__code__获取字节码信息(参数、局部变量等)
__globals__获取全局命名空间
__closure__获取闭包变量(用于嵌套函数)
这些属性在 **反射(introspection)、装饰器、动态分析代码