Python 内省
最后修改于 2024 年 1 月 29 日
在本文中,我们将讨论 Python 中的内省。
内省是一种自我检查的行为。在计算机编程中,内省是指在运行时确定对象类型或属性的能力。Python 编程语言对内省提供了广泛的支持。Python 中的一切都是对象。Python 中的每个对象都可以拥有属性和方法。通过使用内省,我们可以动态地检查 Python 对象。
Python dir 函数
dir 函数返回属于对象的属性和方法的排序列表。
>>> dir(()) ['__add__', '__class__', '__contains__', '__delattr__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__getslice__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'count', 'index']
在这里,我们看到了 `dir` 函数对元组对象的输出。
>>> print(().__doc__) tuple() -> empty tuple tuple(iterable) -> tuple initialized from iterable's items If the argument is a tuple, the return value is the same object.
我们的研究表明,元组对象有一个 `__doc__` 属性。
#!/usr/bin/python
# direx.py
import sys
class MyObject:
def __init__(self):
pass
def examine(self):
print(self)
o = MyObject()
print(dir(o))
print(dir([]))
print(dir({}))
print(dir(1))
print(dir())
print(dir(len))
print(dir(sys))
print(dir("String"))
该示例使用 `dir` 函数检查了多个对象:用户定义的对象、本机数据类型、函数、字符串或数字。
不带任何参数时,`dir` 返回当前作用域中的名称。
>>> dir() ['__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__'] >>> import sys >>>import math, os >>> dir() ['__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'math', 'sys']
我们在导入一些模块之前和之后执行了 `dir` 函数。
Python type 函数
type 函数返回对象的类型。
#!/usr/bin/python
# typefun.py
import sys
def function():
pass
class MyObject:
def __init__(self):
pass
o = MyObject()
print(type(1))
print(type(""))
print(type([]))
print(type({}))
print(type(()))
print(type(object))
print(type(function))
print(type(MyObject))
print(type(o))
print(type(sys))
该示例将各种对象类型打印到控制台屏幕。
$ ./typefun.py <class 'int'> <class 'str'> <class 'list'> <class 'dict'> <class 'tuple'> <class 'type'> <class 'function'> <class 'type'> <class '__main__.MyObject'> <class 'module'>
id 函数
id 返回对象的特殊 ID。
#!/usr/bin/python
# idfun.py
import sys
def fun(): pass
class MyObject:
def __init__(self):
pass
o = MyObject()
print(id(1))
print(id(""))
print(id({}))
print(id([]))
print(id(sys))
print(id(fun))
print(id(MyObject))
print(id(o))
print(id(object))
代码示例打印了各种对象(内置和自定义)的 ID。
$ ./idfun.py 10914368 139696088742576 139696087935944 139696065155784 139696088325640 139696088244296 21503992 139696087910776 10738720
Python sys 模块
sys 模块提供了对解释器使用的或维护的系统特定变量和函数的访问,以及与解释器进行强交互的函数。该模块允许我们查询 Python 环境。
>>> import sys >>> sys.version '3.11.1 (tags/v3.11.1:a7a450f, Dec 6 2022, 19:58:39) [MSC v.1934 64 bit (AMD64)]' >>> sys.platform 'win32' >>> sys.path ['', 'C:\\Users\\Jano\\AppData\\Local\\Programs\\Python\\Python311\\python311.zip', 'C:\\Users\\Jano\\AppData\\Local\\Programs\\Python\\Python311\\Lib', 'C:\\Users\\Jano\\AppData\\Local\\Programs\\Python\\Python311\\DLLs', 'C:\\Users\\Jano\\AppData\\Local\\Programs\\Python\\Python311', ... ']
在上面的代码中,我们检查了 Python 版本、平台和搜索路径位置。
我们还可以使用 `dir` 函数获取 `sys` 模块的变量和函数完整列表。
>>> sys.executable 'C:\\Users\\Jano\\AppData\\Local\\Programs\\Python\\Python311\\python.exe' >>> sys.argv [''] >>> sys.byteorder 'little'
该示例展示了 `sys` 模块的 `executable`、`argv` 和 `byteorder` 属性。
>>> sys.executable 'C:\\Users\\Jano\\AppData\\Local\\Programs\\Python\\Python311\\python.exe'
executable 是一个字符串,给出 Python 解释器的可执行二进制文件的名称,在系统上这是有意义的。
>>> sys.argv ['']
这提供了传递给 Python 脚本的命令行参数列表。
>>> sys.byteorder 'little'
byteorder 是本机字节顺序的指示符。在大端(最高有效字节在前)平台上,它将具有值“big”,在小端(最低有效字节在前)平台上,它将具有值“little”。
其他内省
接下来,我们将展示检查 Python 对象的各种其他方法。
#!/usr/bin/python
# attr.py
def fun():
pass
print(hasattr(object, '__doc__'))
print(hasattr(fun, '__doc__'))
print(hasattr(fun, '__call__'))
print(getattr(object, '__doc__'))
print(getattr(fun, '__doc__'))
hasattr 函数检查对象是否具有某个属性。`getattr` 函数在存在某些属性时返回该属性的内容。
$ ./attr.py True True True The most base type None
`isinstance` 函数检查对象是否是特定类的实例。
>>> print(isinstance.__doc__) Return whether an object is an instance of a class or of a subclass thereof. A tuple, as in ``isinstance(x, (A, B, ...))``, may be given as the target to check against. This is equivalent to ``isinstance(x, A) or isinstance(x, B) or ...`` etc.
我们可以交互式地获取函数的描述。
#!/usr/bin/python
# instance.py
class MyObject:
def __init__(self):
pass
o = MyObject()
print(isinstance(o, MyObject))
print(isinstance(o, object))
print(isinstance(2, int))
print(isinstance('str', str))
正如我们所知,Python 中的一切都是对象;甚至是数字和字符串。`object` 是 Python 中所有对象的基类。
$ ./instance.py True True True True
`issubclass` 函数检查特定类是否是另一个类的派生类。
#!/usr/bin/python
# subclass.py
class Object:
def __init__(self):
pass
class Wall(Object):
def __init__(self):
pass
print(issubclass(Object, Object))
print(issubclass(Object, Wall))
print(issubclass(Wall, Object))
print(issubclass(Wall, Wall))
在我们的代码示例中,`Wall` 类是 `Object` 类的子类。`Object` 和 `Wall` 也是它们自身的子类。`Object` 类不是 `Wall` 类的子类。
$ ./subclass.py True False True True
`__doc__` 属性提供有关对象的文档,而 `__name__` 属性保存对象的名称。
#!/usr/bin/python
# namedoc.py
def noaction():
'''A function, which does nothing'''
pass
funcs = [noaction, len, str]
for i in funcs:
print(i.__name__)
print(i.__doc__)
print("-" * 75)
在我们的示例中,我们创建了一个包含三个函数的列表:一个自定义函数和两个内置函数。我们遍历列表并打印 `__name__` 和 `__doc__` 属性。
$ ./namedoc.py noaction A function, which does nothing --------------------------------------------------------------------------- len Return the number of items in a container. --------------------------------------------------------------------------- str str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'. ---------------------------------------------------------------------------
最后,还有一个 `callable` 函数。该函数检查对象是否是可调用对象(函数)。
#!/usr/bin/python
# callable.py
class Car:
def setName(self, name):
self.name = name
def fun():
pass
c = Car()
print(callable(fun))
print(callable(c.setName))
print(callable([]))
print(callable(1))
在代码示例中,我们检查了三个对象是否可调用。
print(callable(fun)) print(callable(c.setName))
`fun` 函数和 `setName` 方法是可调用的。(方法是绑定到对象的函数。)
$ ./callable.py True True False False
来源
在本文中,我们讨论了 Python 中的内省。更多用于执行内省的工具可以在 `inspect` 模块中找到。
作者
列出所有 Python 教程。