在 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 tupletuple(iterable) -> tuple initialized from iterable's itemsIf the argument is a tuple, the return value is the same object.
我们的研究表明,元组对象有一个__doc__属性。
direx.py
#!/usr/bin/env python# direx.pyimport sysclass MyObject(object):def __init__(self):passdef 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()函数返回对象的类型。
typefun.py
#!/usr/bin/env python# typefun.pyimport sysdef function():passclass MyObject(object):def __init__(self):passo = 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。
idfun.py
#!/usr/bin/env python# idfun.pyimport sysdef fun(): passclass MyObject(object):def __init__(self):passo = 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.py109143681396960887425761396960879359441396960651557841396960883256401396960882442962150399213969608791077610738720
Python sys模块
sys模块提供对解释器使用或维护的系统特定变量和函数以及与解释器强烈交互的函数的访问。 该模块允许我们查询有关 Python 环境的信息。
>>> import sys>>> sys.version'3.5.2 (default, Nov 17 2016, 17:05:23) \n[GCC 5.4.0 20160609]'>>> sys.platform'linux'>>> sys.path['', '/usr/lib/python35.zip', '/usr/lib/python3.5', '/usr/lib/python3.5/plat-x86_64-linux-gnu','/usr/lib/python3.5/lib-dynload', '/home/janbodnar/.local/lib/python3.5/site-packages','/usr/local/lib/python3.5/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/python3'
可执行文件是一个字符串,给出有意义的系统上 Python 解释器的可执行二进制文件的名称。
>>> sys.argv['']
这给出了传递给 Python 脚本的命令行参数列表。
>>> sys.byteorder'little'
字节顺序是本机字节顺序的指示。 在大端(最高有效字节在前)平台上,值将为"big",在小端(最低有效字节在前)平台值将为"little"。
其他自省
接下来,我们展示检查 Python 对象的各种其他方式。
attrs.py
#!/usr/bin/env python# attr.pydef fun():passprint(hasattr(object, '__doc__'))print(hasattr(fun, '__doc__'))print(hasattr(fun, '__call__'))print(getattr(object, '__doc__'))print(getattr(fun, '__doc__'))
hasattr()函数检查对象是否具有属性。 getattr()函数返回属性的内容(如果有的话)。
$ ./attr.pyTrueTrueTrueThe most base typeNone
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 tocheck against. This is equivalent to ``isinstance(x, A) or isinstance(x, B)or ...`` etc.
我们可以交互地描述一个函数。
instance.py
#!/usr/bin/env python# instance.pyclass MyObject(object):def __init__(self):passo = MyObject()print(isinstance(o, MyObject))print(isinstance(o, object))print(isinstance(2, int))print(isinstance('str', str))
众所周知,一切都是 Python 中的对象; 偶数和字符串。 object是 Python 中所有对象的基本类型。
$ ./instance.pyTrueTrueTrueTrue
issubclass()函数检查特定的类是否是另一个类的派生类。
subclass.py
#!/usr/bin/env python# subclass.pyclass Object(object):def __init__(self):passclass Wall(Object):def __init__(self):passprint(issubclass(Object, Object))print(issubclass(Object, Wall))print(issubclass(Wall, Object))print(issubclass(Wall, Wall))
在我们的代码示例中,Wall类是Object类的子类。 Object和Wall本身也是它们的子类。 Object类不是Wall类的子类。
$ ./subclass.pyTrueFalseTrueTrue
__doc__属性提供了有关对象的一些文档,__name__属性包含对象的名称。
namedoc.py
#!/usr/bin/env python# namedoc.pydef noaction():'''A function, which does nothing'''passfuncs = [noaction, len, str]for i in funcs:print(i.__name__)print(i.__doc__)print("-" * 75)
在我们的示例中,我们创建了三个函数的列表:一个自定义函数和两个本机函数。 我们浏览列表并打印__name__和__doc__属性。
$ ./namedoc.pynoactionA function, which does nothing---------------------------------------------------------------------------lenReturn the number of items in a container.---------------------------------------------------------------------------strstr(object='') -> strstr(bytes_or_buffer[, encoding[, errors]]) -> strCreate a new string object from the given object. If encoding orerrors is specified, then the object must expose a data bufferthat 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()函数。 该函数检查对象是否为可调用对象(函数)。
callable.py
#!/usr/bin/env python# callable.pyclass Car(object):def setName(self, name):self.name = namedef fun():passc = Car()print(callable(fun))print(callable(c.setName))print(callable([]))print(callable(1))
在代码示例中,我们检查三个对象是否可调用。
print(callable(fun))print(callable(c.setName))
fun()函数和setName()方法是可调用的。 (方法是绑定到对象的函数。)
$ ./callable.pyTrueTrueFalseFalse
在 Python 教程的这一部分中,我们讨论了 Python 中的自省。 在inspect模块中可以找到更多进行内省的工具。
