在本文中,我们讨论了Python中的内省。
内省是一种自我检查的行为。在计算机编程中,内省是在运行时确定对象的类型或属性的能力。Python编程语言非常支持内省。Python中的一切都是对象。Python中的每个对象都可能有属性和方法。通过使用内省,我们可以动态检查Python对象。
Python目录函数
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(object):
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函数返回对象的类型。
#!/usr/bin/python
# typefun.py
import sys
def function():
pass
class MyObject(object):
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(object):
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模块提供对解释器使用或维护的系统特定变量和函数的访问,以及对与解释器交互作用强的函数的访问。该模块允许我们查询Python环境。
>>> import sys >>> sys.version '3.10.6 (main, Aug 10 2022, 11:40:04) [GCC 11.3.0]' >>> sys.platform 'linux' >>> sys.path ['', '/usr/lib/python310.zip', '/usr/lib/python3.10', '/usr/lib/python3.10/lib-dynload', '/home/jano/.local/lib/python3.10/site-packages', '/usr/local/lib/python3.10/dist-packages', '/usr/lib/python3/dist-packages']
在上面的代码中,我们检查了Python版本、平台和搜索路径位置。
我们还可以使用dir函数来获取sys模块的变量和函数的完整列表。
>>> sys.executable '/usr/bin/python3' >>> sys.argv [''] >>> sys.byteorder 'little'
该示例展示了sys模块的executable、argv和byteorder属性。
>>> sys.executable '/usr/bin/python'
可执行文件是一个字符串,在有意义的系统上为Python解释器提供可执行二进制文件的名称。
>>> sys.argv ['']
这给出了传递给Python脚本的命令行参数列表。
>>> sys.byteorder 'little'
字节顺序是本机字节顺序的指示器。这将在big-endian(最高有效字节优先)平台上具有值“big”,在little-endian(最低有效字节优先)平台上具有“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(object):
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(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(object):
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教程。
