python自省

在计算机编程中,自省是指这种能力:检查某些事物以确定它是什么、它知道什么以及它能做什么。自省向程序员提供了极大的灵活性和控制力。

下面开始介绍日常coding中最常用的自省方法:

访问对象的属性

当你想要对某个对象的属性(包括方法)进行操作但是记不清它的名字、甚至都不确定它是否存在的时候,python提供的自省功能就派上用场了。

#实现一个简单的类
class MyClass:

    def __init__(self, name):
        self.name = name

    def instance_method(self):
        print(self,'调用了实例方法~')  

#开始测试        
obj = MyClass('trophy')             # 创建一个实例对象obj

if hasattr(obj, 'name'):            # 检查实例obj是否有name属性
    setattr(obj, 'name', 'jack')    # 相当于obj.name = 'jack'
    print(getattr(obj, 'name'))     # jack
    print(obj.name)                 # jack

if hasattr(obj, 'instance_method'):   # 检查实例obj是否有instance_method属性
    getattr(obj, 'instance_method')() # <__main__.MyClass object at 0x000000CA0833B668> 调用了实例方法~
    obj.instance_method()             #<__main__.MyClass object at 0x000000CA0833B668> 调用了实例方法~

print(dir(obj))
'''
dir(obj):
['__class__', '__delattr__', '__dict__', '__dir__',
......
'__subclasshook__', '__weakref__',
'instance_method', 'name']  #注意这一行哦~
'''

在上面的例子中使用了以下几个方法:

  • hasattr(obj, attr):
    这个方法用于检查obj是否有一个名为attr的属性,返回一个布尔值。
  • getattr(obj, attr):
    调用这个方法将返回obj中名为attr的属性的值。当attr为简单的属性名,getattr(obj, attr)相当于obj.attr。而当attr是个方法名的时候,getattr(obj, attr)()就相当于obj.attr()啦。
  • setattr(obj, attr, val):
    调用这个方法将给obj的名为attr的属性赋值为val。例如如果attr为’name’,则相当于obj.name= val。
  • dir([obj]):
    调用这个方法将返回参数obj的属性和方法列表,obj的默认值是当前的模块对象。我们自定义的属性和方法一般是排在返回列表的末尾(如上例中dir(obj)的最后一行)。

在python中一切皆对象,你可以对所有的对象使用上面的方法,我们再拿List类对象来试试:

#测试List类的clear和append方法
a = [1,2,3,4,5]
print(a)                     # [1, 2, 3, 4, 5]
if hasattr(a, 'clear'):      # 检查实例a是否有clear属性
    getattr(a, 'clear')()    # 相当于a.clear()
    print(a)                 # []
    getattr(a, 'append')(88) # 相当于a.append(88)
    print(a)                 # [88]

print(dir(a))
'''
['__add__', '__class__', '__contains__', '__delattr__',
 ......
 'append', 'clear', 'copy', 'count', 'extend', 'index',
 'insert', 'pop', 'remove', 'reverse', 'sort']
'''

确认对象的类型

有两种方式可以确认对象的类型

1. 使用type()函数,返回对象的类型

print(type(111))            #<class 'int'>
print(type('hello'))        #<class 'str'>
print(type([1,2,3]))        #<class 'list'>
print(type({'num':10}))     #<class 'dict'>
print(type(lambda x : x+1)) #<class 'function'>

2. 使用isinstance()函数,判断一个对象是否是一个已知的类型
用法:isinstance(obj, classinfo),其中obj为实例对象,即要检查的对象。classinfo -可以是直接或间接类名、基本类型或者由它们组成的元组。
classinfo基本类型有:int,float,bool,complex,str,list,dict,set,tuple

print(isinstance (1,int))                   #True
print(isinstance ('hello',str))             #True
print(isinstance ('[1,2,3]',list))          #False
print(isinstance ({'num':10},dict))         #True
print(isinstance ('[1,2]',(str,int,list)))  #True  匹配了元组中的str

快速查看帮助信息

python内置的help() 函数可以用于查看函数或模块用途的详细说明。
使用方法:help([obj]),obj为你想要查询的对象,当不传入参数时会进入help交互式环境。
下面来看看使用示例:

help('math') #查看math模块的帮助信息
help(str)    #查看str类型的帮助信息
help(int)    #查看int类型的帮助信息
help([])     #查看list类型的帮助信息
a = [1,2]
help(a.append)  #查看列表append方法的帮助信息

想了解更多?快去看看大神写的指南:Python自省(反射)指南

<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、付费专栏及课程。

余额充值