什么是python的自省

1. 什么是Python的自省

Python的自省是指在程序运行过程中,可以获取并操作程序本身的信息,包括模块、函数、类、对象等。易于编写灵活的代码以及检查代码中的错误,是Python成为动态语言的一个重要因素。自省是Python语言的一个重要特性。

1.1 自省的优点

Python的自省具有以下优点:

易于调试:自省函数和变量的信息是Python解释器本身运行时调用的,它们可以提供非常有用的信息,帮助程序员快速定位代码中的问题。

代码灵活性:不但可以在程序运行时操作自己,还可以把对象的描述保存下来,方便后续的调用。

1.2 自省的应用

自省的应用场景举不胜举,这里罗列几个典型的应用场景:

编写调试器: 自省提供了运行时动态查询代码的能力,这使得在Python中编写调试器变得非常容易。

数据分析: 在Python中进行数据分析时,经常需要操作大量的数据结构。利用自省可以查看一个复杂的对象的类型、属性,以及如何操作这些对象。

模块应用: 自省可以帮助我们在当前模块中查找特定函数或变量。

2. Python中的自省方法

Python提供了一些内置函数和模块,可以用于实现自省。常用的自省方法有:

2.1 type()函数

type()函数可以用来获取对象的类型。例如:

a = 5

b = 'hello'

print(type(a)) # <class 'int'>

print(type(b)) # <class 'str'>

2.2 dir()函数

dir()函数可以查看一个对象的所有属性和方法,例如:

a = 'hello'

print(dir(a))

输出结果如下:

['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__',

'__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__',

'__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__',

'__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'capitalize', 'casefold', 'center', 'count', 'encode', 'endswith',

'expandtabs', 'find', 'format', 'format_map', 'index', 'isalnum', 'isalpha', 'isascii', 'isdecimal', 'isdigit', 'isidentifier',

'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'maketrans',

'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith',

'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']

这个列表包含了字符串可以使用的所有方法和属性,例如:a.capitalize()可以将字符串的首字母大写。

2.3 inspect模块

inspect模块是Python自省中最强大的模块之一。它提供了很多用于获取对象信息的函数。例如:

2.3.1 检查对象类型

inspect.ismodule(object): 如果对象是一个模块,则返回True,否则返回False。

inspect.isclass(object): 如果对象是一个类,则返回True,否则返回False。

inspect.isfunction(object): 如果对象是一个函数,则返回True,否则返回False。

inspect.isgenerator(object): 如果对象是一个生成器函数(不是生成器对象),则返回True,否则返回False。

2.3.2 获取参数信息和函数返回值

inspect.getargspec(function): 获取函数的参数信息。返回一个元组,包含参数名称、默认值和变长参数。

inspect.getfullargspec(function): 获取函数的完整参数信息。返回一个命名元组,包含参数名称、默认值和变长参数。

inspect.getargvalues(frame): 获取当前调用堆栈所在函数的参数信息。返回一个命名元组,包含参数名称、默认值、变长参数、参数值等。

inspect.getcallargs(func, *args, **kwds): 把函数的参数列表和参数字典合并成一个新的字典,其键是参数名称,值是参数的值。

inspect.getdoc(object): 获取对象的文档字符串。

inspect.getsource(object): 获取对象的源代码。

3. 自省的实践

下面以一个简单的实例来演示自省的使用。假设我们有以下三个类:

class Person(object):

def __init__(self, name, age):

self.name = name

self.age = age

class Engineer(Person):

def __init__(self, name, age, salary):

super(Engineer, self).__init__(name, age)

self.salary = salary

class Manager(Person):

def __init__(self, name, age, department):

super(Manager, self).__init__(name, age)

self.department = department

现在我们想要使用自省来统计代码中定义了哪些类,以及这些类中有哪些方法和属性。

首先,我们可以使用dir()函数来查看当前模块中定义的所有类:

import inspect

for name, obj in inspect.getmembers(inspect.getmodule(inspect.currentframe()), inspect.isclass):

print(name)

输出结果如下:

Engineer

Manager

Person

接下来,我们可以使用dir()函数和getattr()函数来获取每个类的属性和方法:

for name, obj in inspect.getmembers(inspect.getmodule(inspect.currentframe()), inspect.isclass):

print(name)

print(dir(obj))

for attr_name in dir(obj):

attr = getattr(obj, attr_name)

if callable(attr):

print("Method: " + attr_name)

else:

print("Attribute: " + attr_name)

print()

输出结果如下:

Engineer

['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__',

'__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__',

'__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__',

'age', 'name', 'salary']

Attribute: __class__

Method: __delattr__

Attribute: __dict__

Method: __dir__

Attribute: __doc__

Method: __eq__

Method: __format__

Method: __ge__

Method: __getattribute__

Method: __gt__

Method: __hash__

Method: __init__

Method: __init_subclass__

Method: __le__

Method: __lt__

Attribute: __module__

Method: __ne__

Method: __new__

Method: __reduce__

Method: __reduce_ex__

Method: __repr__

Method: __setattr__

Method: __sizeof__

Method: __str__

Method: __subclasshook__

Method: __weakref__

Attribute: age

Attribute: name

Attribute: salary

Manager

['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__',

'__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__',

'__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__',

'age', 'department', 'name']

Attribute: __class__

Method: __delattr__

Attribute: __dict__

Method: __dir__

Attribute: __doc__

Method: __eq__

Method: __format__

Method: __ge__

Method: __getattribute__

Method: __gt__

Method: __hash__

Method: __init__

Method: __init_subclass__

Method: __le__

Method: __lt__

Attribute: __module__

Method: __ne__

Method: __new__

Method: __reduce__

Method: __reduce_ex__

Method: __repr__

Method: __setattr__

Method: __sizeof__

Method: __str__

Method: __subclasshook__

Method: __weakref__

Attribute: age

Attribute: department

Attribute: name

Person

['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__',

'__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__',

'__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__',

'age', 'name']

Attribute: __class__

Method: __delattr__

Attribute: __dict__

Method: __dir__

Attribute: __doc__

Method: __eq__

Method: __format__

Method: __ge__

Method: __getattribute__

Method: __gt__

Method: __hash__

Method: __init__

Method: __init_subclass__

Method: __le__

Method: __lt__

Attribute: __module__

Method: __ne__

Method: __new__

Method: __reduce__

Method: __reduce_ex__

Method: __repr__

Method: __setattr__

Method: __sizeof__

Method: __str__

Method: __subclasshook__

Method: __weakref__

Attribute: age

Attribute: name

通过上述代码,我们可以获取每个类的方法和属性信息,从而帮助我们更好地了解代码结构和设计。

总结

本文介绍了Python的自省以及如何使用内置函数和模块实现自省。自省是一种非常有用的编程技术,可以帮助开发者更好地理解对象结构和编写更灵活的代码。自省可以帮助我们实现调试、代码重构、代码审计等多种任务。

后端开发标签