Python自省

什么是自省


在计算机编程中,自省是指这种能力:检查某些事物以确定它是什么、它知道什么以及它能做什么。自省向程序员提供了极大的灵活性和控制力。
一旦使用了支持自省的编程语言,就会产生类似这样的感觉:“未经检查的对象不值得实例化。”

sys模块


sys模块是提供关于 Python 本身的详尽内在信息的模块。通过导入模块,并用点(.)符号引用其内容(如变量、函数和类)来使用模块。sys 模块包含各种变量和函数,它们揭示了当前的 Python 解释器有趣的详细信息。

首先,我们将导入 sys 模块。然后,我们会输入 sys.executable 变量,它包含到 Python 解释器的路径:
>>>sys.executable
'/usr/bin/python'

platform 变量告诉我们现在处于什么操作系统上:
>>>sys.platform
'darwin'

在当前的 Python 中,版本以字符串和元组(元组包含对象序列)来表示:
>>>sys.version
'2.7.2 (default, Jun 16 2012, 12:38:40) \n[GCC 4.2.1 Compatible Apple Clang 4.0 (tags/Apple/clang-418.0.60)]'

>>>sys.version_info
sys.version_info(major=2, minor=7, micro=2, releaselevel='final', serial=0)

maxint 变量反映了可用的最大整数值:
>>>sys.maxint
 9223372036854775807

argv 变量是一个包含命令行参数的列表(如果参数被指定的话)。第一项 argv[0] 是所运行脚本的路径。当我们以交互方式运行 Python 时,这个值是空字符串:
>>>sys.argv
['/usr/local/bin/ipython']

path 变量是模块搜索路径,Python 在导入期间将在其中的目录列表中寻找模块。最前面的空字符串 '' 是指当前目录:
>>>sys.path 
['',
 '/usr/local/bin',
 '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python27.zip',
 '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7',
 '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat-darwin',
 '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat-mac',
 '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat-mac/lib-scriptpackages',
 '/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python',
 '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-tk',
 '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-old',
 '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-dynload',
 '/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/PyObjC',
 '/Library/Python/2.7/site-packages',
 '/Library/Python/2.7/site-packages/IPython/extensions']

id函数


id(object)函数是返回对象object在其生命周期内位于内存中的地址,id函数的参数类型是一个对象。
>>>a = 111

>>>id(a)
140239460979432

>>>b = a

>>>id(b)
140239460979432

>>>id(111)
140239460979432

dir函数


尽管查找和导入模块相对容易,但要记住每个模块包含什么却不是这么简单。Python 提供了一种方法,可以使用内置的 dir() 函数来检查模块(以及其它对象)的内容。dir() 函数可能是 Python 自省机制中最著名的部分了。它返回传递给它的任何对象的属性名称经过排序的列表。如果不指定对象,则 dir() 返回当前作用域中的名称。

sys模块的属性
>>>dir(sys) 
['__displayhook__',
 '__doc__',
 '__excepthook__',
 '__name__',
 '__package__',
 '__stderr__',
 '__stdin__',
 '__stdout__',
 '_clear_type_cache',
 '_current_frames',
 '_getframe',
 '_mercurial',
 'api_version',
 'argv',
 'builtin_module_names',
 'byteorder',
 'call_tracing',
 'callstats',
 'copyright',
 'displayhook',
 'dont_write_bytecode',
 'exc_clear',
 'exc_info',
 'exc_type',
 'excepthook',
 'exec_prefix',
 'executable',
 'exit',
 'exitfunc',
 'flags',
 'float_info',
 'float_repr_style',
 'getcheckinterval',
 'getdefaultencoding',
 'getdlopenflags',
 'getfilesystemencoding',
 'getprofile',
 'getrecursionlimit',
 'getrefcount',
 'getsizeof',
 'gettrace',
 'hexversion',
 'last_traceback',
 'last_type',
 'last_value',
 'long_info',
 'maxint',
 'maxsize',
 'maxunicode',
 'meta_path',
 'modules',
 'path',
 'path_hooks',
 'path_importer_cache',
 'platform',
 'prefix',
 'ps1',
 'ps2',
 'ps3',
 'py3kwarning',
 'setcheckinterval',
 'setdlopenflags',
 'setprofile',
 'setrecursionlimit',
 'settrace',
 'stderr',
 'stdin',
 'stdout',
 'subversion',
 'version',
 'version_info',
 'warnoptions']

string的属性
>>>dir(str)
['__add__',
 '__class__',
 '__contains__',
 '__delattr__',
 '__doc__',
 '__eq__',
 '__format__',
 '__ge__',
 '__getattribute__',
 '__getitem__',
 '__getnewargs__',
 '__getslice__',
 '__gt__',
 '__hash__',
 '__init__',
 '__le__',
 '__len__',
 '__lt__',
 '__mod__',
 '__mul__',
 '__ne__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__rmod__',
 '__rmul__',
 '__setattr__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 '_formatter_field_name_split',
 '_formatter_parser',
 'capitalize',
 'center',
 'count',
 'decode',
 'encode',
 'endswith',
 'expandtabs',
 'find',
 'format',
 'index',
 'isalnum',
 'isalpha',
 'isdigit',
 'islower',
 'isspace',
 'istitle',
 'isupper',
 'join',
 'ljust',
 'lower',
 'lstrip',
 'partition',
 'replace',
 'rfind',
 'rindex',
 'rjust',
 'rpartition',
 'rsplit',
 'rstrip',
 'split',
 'splitlines',
 'startswith',
 'strip',
 'swapcase',
 'title',
 'translate',
 'upper',
 'zfill']

callable函数


callable 函数, 可以检查一个对象是否是可调用的 (无论是直接调用或是通过 apply)。
对于函数, 方法, lambda 函式, 类, 以及实现了__call__方法的类实例, 它都返回 True。
>>>callable(len)
True

>>>callable(os)
False

>>>class A:
   .....:     def __init__(self):
   .....:         self.a = 'apple'
   .....: 

>>>callable(A)
True

>>>a = A()

>>>callable(a)
False

>>>class B:
   .....:     def __init__(self):
   .....:         self.b = 'banana'
   .....:     def __call__(self):
   .....:         self.c = 'orange'
   .....: 

>>>instantB = B()

>>>callable(instantB)
True

属性

class A:   
    def __init__(self):   
        self.name = 'my name is a'  
    def method(self):   
        print "method print"  
  
a = A()

hasattr函数


简介


hasattr(object,name)
用来检查object中是否有name的属性,返回一个布尔值。

实例


print hasattr(a,'name') #true
print hasattr(a,'age')  #false

getattr函数


简介


getattr(object,name)或者getattr(object,name,default)
getattr可以获得对象的方法或者属性的引用
如果object是一个模块,那么name可以是模块中的类,方法或者全局变量中的一个

实例

print getattr(a, 'name', 'default') #如果有属性name则打印name,否则打印default   
print getattr(a, 'age', 'default') #如果有属性age则打印age,否则打印default   
print getattr(a, 'method', 'default')   
#如果有方法method,否则打印其地址,否则打印default   
print getattr(a, 'method', 'default')()   
#如果有方法method,运行函数并打印None否则打印default


setattr函数


简介


setattr(object,name,val)
这个函数将为object名为name的属性赋值为val,相当于object.name=val

实例


setattr(a,'age',12)
print getattr(a,'age',10) #12


<think>好的,我现在要介绍Python自省和反射。首先,我需要明确这两个概念的定义,确保自己理解正确。自省(Introspection)是指程序在运行时能够查看和访问对象的属性和方法的能力。而反射(Reflection)则更进一步,允许程序在运行时动态地修改对象的属性和方法,甚至创建新的对象实例。用户可能需要了解它们的区别以及如何在Python中使用这些特性。 接下来,我应该分步骤组织内容。先从自省开始,举例说明Python中常用的自省函数,比如type(), dir(), id(), hasattr(), getattr()等。需要说明每个函数的作用和使用场景,例如type()用于获取对象类型,dir()列出对象的属性和方法。然后可以提到inspect模块,它提供了更高级的自省功能,比如检查函数参数或源代码。 然后是反射部分,需要强调反射的动态特性。例如,通过setattr()动态设置属性,或者使用getattr()获取属性并调用方法。这里可以举一个实际的例子,比如根据字符串名称调用对象的方法,展示反射的灵活性。此外,可以提到__import__函数动态导入模块,这也是反射的一种应用。 需要注意的是,用户可能对这两个概念容易混淆,因此要明确区分自省和反射的不同。自省主要是查询信息,而反射则是修改或操作。同时,要提醒用户在使用反射时注意安全性和可维护性,因为动态修改可能会带来意想不到的问题。 另外,可以补充一些实际应用场景,比如在框架开发中,反射常用于根据配置动态加载类或方法;自省则常用于调试或日志记录,查看对象状态。还可以提到装饰器、元类等高级特性如何与自省和反射结合使用,但可能不需要深入细节,保持回答的简洁性。 最后,总结两者的重要性和在Python中的实现方式,帮助用户形成整体理解。检查是否有遗漏的关键点,比如特殊属性__dict__的使用,或者如何处理异常情况(如属性不存在时的处理)。确保示例代码正确,语法无误,并符合用户的可读性需求。</think>### Python 自省(Introspection)与反射(Reflection)详解 --- #### **1. 自省(Introspection)** **定义**:程序在运行时**查看和访问对象信息**的能力,例如对象的类型、属性、方法等。 **核心函数与工具**: - **`type(obj)`**:获取对象类型 ```python print(type(42)) # <class 'int'> ``` - **`dir(obj)`**:列出对象所有属性和方法 ```python print(dir("hello")) # 显示字符串的所有方法,如 'upper', 'split' 等 ``` - **`id(obj)`**:获取对象内存地址 - **`hasattr(obj, 'attr')`**:检查对象是否有某个属性或方法 ```python hasattr([1,2,3], 'append') # True ``` - **`getattr(obj, 'attr')`**:获取属性的值(或方法引用) ```python method = getattr("hello", "upper") print(method()) # 输出 "HELLO" ``` - **`inspect` 模块**:更强大的自省工具,例如检查函数参数、源码等 ```python import inspect print(inspect.getfullargspec(print)) # 查看print函数的参数 ``` --- #### **2. 反射(Reflection)** **定义**:程序在运行时**动态修改或创建对象**的能力,例如通过字符串操作属性或方法。 **核心操作**: - **`setattr(obj, 'attr', value)`**:动态设置属性 ```python class MyClass: pass obj = MyClass() setattr(obj, 'new_attr', 100) print(obj.new_attr) # 输出 100 ``` - **`delattr(obj, 'attr')`**:删除属性 - **动态调用方法**:通过字符串名称调用方法 ```python class Calculator: def add(self, a, b): return a + b calc = Calculator() method = getattr(calc, 'add') print(method(2, 3)) # 输出 5 ``` - **动态导入模块**:通过字符串导入模块 ```python module_name = "math" math_module = __import__(module_name) print(math_module.sqrt(4)) # 输出 2.0 ``` --- #### **3. 自省 vs 反射** | **特性** | **自省** | **反射** | |----------------|-----------------------------|-----------------------------| | **核心功能** | 查看对象信息 | 动态修改/创建对象 | | **典型函数** | `type()`, `dir()`, `hasattr()` | `setattr()`, `getattr()` | | **应用场景** | 调试、日志、文档生成 | 插件系统、ORM框架、动态配置 | --- #### **4. 应用场景** - **框架开发**:Django 或 Flask 通过反射动态加载路由和视图函数。 - **动态配置**:根据配置文件字符串调用对应方法。 - **调试工具**:通过自省检查对象状态。 - **装饰器与元类**:结合自省实现动态行为控制。 --- #### **5. 注意事项** 1. **安全性**:反射可能引入安全风险(如通过用户输入直接调用方法)。 2. **可读性**:过度使用反射会降低代码可维护性。 3. **异常处理**:使用 `try...except` 处理属性不存在的情况。 --- #### **示例:动态调用方法** ```python class User: def login(self): print("登录成功") def logout(self): print("退出登录") user = User() action = input("请输入操作(login/logout): ") if hasattr(user, action): method = getattr(user, action) method() # 根据输入动态调用方法 else: print("无效操作") ``` --- 通过自省和反射,Python 能够实现高度灵活的编程模式,但也需谨慎使用以保持代码清晰和安全。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值