摘要
本文围绕 Python 面向对象三大核心知识点展开:issubclass/type/isinstance类型判断、函数与方法精准区分、反射四大内置方法(hasattr/getattr/setattr/delattr),搭配可运行代码示例、总结表格,反射是 Python 框架底层核心原理,适合零基础学习与面试复习,所有代码可直接复制运行。
关键词:Python 反射;isinstance;函数与方法区分;面向对象
一、类型判断:issubclass、type、isinstance
1.1 issubclass ():判断子类关系
作用:issubclass(子类, 父类),校验第一个类是否是第二个类的子类(包含多级继承)
class Base: pass class Foo(Base): pass class Bar(Foo): pass print(issubclass(Bar, Foo)) # True print(issubclass(Foo, Bar)) # False print(issubclass(Bar, Base)) # True
1.2 type ():精准查看对象所属类
作用:type(对象),严格匹配创建对象的直接类,不会向上识别父类,常用于数据类型强校验、统计对象。
# 示例1:查看对象所属类 class Foo: pass obj = Foo() print(type(obj)) # <class '__main__.Foo'> # 示例2:统计不同实例数量 class Boy: pass class Girl: pass def func(*args): b = 0 g = 0 for obj in args: if type(obj) == Boy: b += 1 elif type(obj) == Girl: g += 1 return b, g ret = func(Boy(), Girl(), Girl(), Girl(), Boy(), Boy(), Girl()) print(ret) # (3,4) # 示例3:数值类型校验 def add(a, b): if (type(a) in (int, float)) and (type(b) in (int, float)): return a + b else: print("数据类型错误,仅支持数字运算") print(add(10, 20.5))1.3 isinstance ():宽泛判断继承体系
作用:isinstance(对象, 类型),向上兼容父类,只要对象属于该类及其父类体系,返回 True。
class Base: pass class Foo(Base): pass class Bar(Foo): pass print(isinstance(Foo(), Foo)) # True print(isinstance(Foo(), Base)) # True(父类也成立) print(isinstance(Foo(), Bar)) # False
1.4 type 与 isinstance 核心区别对照表
| 函数 | 判断规则 | 继承识别 | 使用场景 |
|---|---|---|---|
type(obj)==类名 | 严格匹配直接创建类 | 不识别父类 | 精准类型校验、分类统计 |
isinstance(obj,类名) | 对象属于类 / 子类均可 | 向上识别所有父类 | 宽泛类型判断 |
二、区分函数与方法(重点)
2.1 直观打印区分
实例方法通过实例调用 = 绑定方法 (method);通过类名调用 = 普通函数 (function);静态方法永远是函数,类方法永远是方法。
class Foo: def chi(self): print("实例方法") @staticmethod def static_method(): print("静态方法") @classmethod def class_method(cls): print("类方法") # 实例对象 f = Foo() # 实例调用 print(f.chi) # <bound method Foo.chi of <__main__.Foo object ...>> method print(f.static_method) # <function Foo.static_method ...> function print(f.class_method) # <bound method Foo.class_method of <class '__main__.Foo'>> method # 类名调用 print(Foo.chi) # <function Foo.chi ...> function print(Foo.static_method)# <function Foo.static_method ...> function print(Foo.class_method)# <bound method Foo.class_method of <class '__main__.Foo'>> method2.2 借助 types 模块精准判断
导入FunctionType(函数类型)、MethodType(方法类型)做类型判定
from types import FunctionType, MethodType def func(): pass class Foo: def chi(self): pass @staticmethod def static_method(): pass @classmethod def class_method(cls): pass obj = Foo() # 判断 print(isinstance(func, FunctionType)) # True print(isinstance(obj.chi, MethodType)) # True(实例调用=方法) print(isinstance(Foo.chi, FunctionType)) # True(类调用=函数) print(isinstance(Foo.static_method, FunctionType)) # True print(isinstance(Foo.class_method, MethodType)) # True
2.3 三类成员总结表格
| 成员类型 | 实例访问 | 类名访问 |
|---|---|---|
| 实例方法 | Method (方法) | Function (函数) |
| 静态方法 staticmethod | Function (函数) | Function (函数) |
| 类方法 classmethod | Method (方法) | Method (方法) |
2.4 练习题:封装通用判断函数
需求:编写函数,入参接收对象,返回该对象是「函数」还是「方法」
from types import FunctionType, MethodType def check_func_or_method(item): if isinstance(item, MethodType): return "方法" elif isinstance(item, FunctionType): return "函数" else: return "非函数/方法" # 测试代码 class Foo: @classmethod def func1(self): pass @staticmethod def func2(self): pass def func3(self): pass obj = Foo() print(check_func_or_method(obj.func3)) # 方法 print(check_func_or_method(Foo.func3)) # 函数
三、反射(Python 核心重点)
3.1 反射概念
通过字符串动态操作对象的属性 / 方法,正常:对象。属性;反射:字符串映射属性,解决「用户输入字符串动态调用代码」场景,是 Django/Flask 等框架底层核心。
反射四大内置函数:
hasattr(obj, "字符串"):判断对象是否存在该成员,返回布尔值getattr(obj, "字符串", 默认值):根据字符串获取对象成员setattr(obj, "字符串", value):动态新增 / 修改对象属性 / 方法delattr(obj, "字符串"):动态删除对象成员
注意:所有操作仅修改内存,不会改动源文件代码。
3.2 场景 1:动态调用模块函数
新建master.py(大牛模块)
# master.py def chi(): print("大牛一顿吃100个螃蟹") def he(): print("大牛一顿喝100瓶可乐") def la(): print("大牛不用拉") def shui(): print("大牛一次睡一年")主程序:用户输入字符串,反射调用对应函数
# 主程序 import master from types import FunctionType while True: tip = """ 作为大牛,提供功能: chi:吃 | he:喝 | la:拉 | shui:睡 """ print(tip) gn = input("请输入要执行的功能名:").strip() # 先判断是否存在 if hasattr(master, gn): func = getattr(master, gn) # 仅函数执行 if isinstance(func, FunctionType): func() else: print(func) else: print("不存在该功能!")3.3 场景 2:面向对象中使用反射
通过字符串动态调用实例方法
class Person: def chi(self): print("吃饭") def he(self): print("喝水") def la(self): print("如厕") def shui(self): print("睡觉") def run(self): func_list = ["chi", "he", "la", "shui"] tip = """ 1.吃饭 2.喝水 3.如厕 4.睡觉 """ num = int(input(tip + "请输入序号:")) # 反射获取方法并执行 method_name = func_list[num - 1] method = getattr(self, method_name) method() p = Person() p.run()3.4 setattr/delattr 动态增删属性示例
class Foo: pass f = Foo() # 1.动态添加普通属性 setattr(f, "name", "张三") print(f.name) # 张三 # 2.动态添加方法 setattr(f, "calc", lambda x:x+1) print(f.calc(5)) #6 #3.判断属性 print(hasattr(f,"calc")) #True #4.删除属性 delattr(f,"calc") print(hasattr(f,"calc")) #False print(f.__dict__) #查看实例所有属性字典
3.5 反射四大方法汇总表
| 方法 | 作用 |
|---|---|
| hasattr(obj,str) | 判断成员是否存在 |
| getattr(obj,str) | 获取指定成员 |
| setattr(obj,str,val) | 新增 / 修改成员 |
| delattr(obj,str) | 删除指定成员 |