|
发表于 2022-2-25 08:33:10
|
显示全部楼层
本帖最后由 lzb1001 于 2022-2-25 10:52 编辑
# 以下代码必须在python3下运行!!!
class PlugIn(object): # 定义一个能给对象扩展方法类PlugIn(最顶层基类)
def __init__(self): # 初始化定义
self.methods = [] # 对象方法列表
def add(self, owner): # 定义add函数(具体添加方法),owner是类对象(也就是下面的c)
# 关键代码:修改对象的行为(而不是修改类的),利用__dict__来扩展对象的方法!!!
for f in self.methods: # 当f在对象方法列表中则循环
owner.__dict__[f.__name__] = f # 将f赋值给对象属性(对象的方法中原本没有方法f,通过赋值扩展方法f)
# _ _name_ _是一个Python预定义全局变量,在模块内部是用来标识模块名称的
# 如果模块是被其他模块导入的,_ _name_ _的值是模块的名称,主动执行时它的值就是字符串“_ _main_ _”
# 没有下面这段代码,最后返回结果也一样!!!
def minors(self, owner): # 定义minors函数,owner是类对象(也就是下面的c)
# 关键代码:修改对象的行为(而不是修改类的),利用__dict__来扩展对象的方法!!!
for f in self.methods: # 当f在对象方法列表中则循环
del owner.__dict__[f.__name__] # 删除对象属性赋值(对象的方法中原本有方法f,通过del删除方法f)?
class AFeature(PlugIn): # 定义PlugIn子类AFeature(子类AFeature继承了基类Plugin上面所有的方法)
def __init__(self): # 初始化定义
super(AFeature, self).__init__() # 自动找到基类的方法,并传入self参数,此处super().__init__()也可
self.methods.append(self.get_a_value) # 方法列表添加get_a_value的值
# 上面这句代码是将AFeature的方法添加(贮存)到一个列表中,以备add或者minors函数的使用
def get_a_value(self): # 定义get_a_value函数
print('a feature.') # 打印输出字符串a feature.
class BFeature(PlugIn): # 定义PlugIn子类BFeature(子类BFeature继承了基类Plugin上面所有的方法)
def __init__(self): # 初始化定义
super(BFeature, self).__init__() # # 自动找到基类的方法,并传入self参数,此处super().__init__()也可
self.methods.append(self.get_b_value) # 方法列表添加get_b_value的值
# 上面这句代码是将AFeature的方法添加(贮存)到一个列表中,以备add或者minors函数的使用
def get_b_value(self): # 定义get_b_value函数
print('b feature.') # 打印输出字符串b feature.
# class Combine: # 也可以执行
class Combine(AFeature, BFeature): # 定义Combine子类,同时继承AFeature、BFeature两个基类
pass # ……
c = Combine() # 将Combine子类实例化(c是Combine子类的实例对象)
AFeature().add(c) # 将c这个实例对象作为参数传入add函数(super帮助找到add函数在子类AFeature的基类PlugIn的方法中)
BFeature().add(c) # 将c这个实例对象作为参数传入add函数(super帮助找到add函数在子类AFeature的基类PlugIn的方法中)
c.get_a_value() # 给实例对象c添加AFeature的方法,具体为:找到get_a_value函数并执行
c.get_b_value() # 给实例对象c添加BFeature的方法,具体为:找到get_b_value函数并执行
# 以上就是Mixin编程机制的插件方式,即通过使用__dict__这个特殊属性来扩展对象c的方法的同时确保类Combine不会受到影响
print(AFeature.__bases__) # 打印输出类AFeature的基类,输出格式(<class '__main__.基类名'>,)
print(BFeature.__bases__) # 打印输出类BFeature的基类,输出格式(<class '__main__.基类名'>,)
print(Combine.__bases__) # 打印输出类Combine的基类,输出格式(<class '__main__.基类名'>, ……)
print(PlugIn.__bases__) # 打印输出最顶层类PlugIn的基类,输出格式(<class 'object'>,)
print(AFeature.__bases__, BFeature.__bases__, Combine.__bases__, PlugIn.__bases__) # 打印输出所有类的基类,输出格式为以上的汇总,中间以空格间隔
运行后返回结果:
a feature.
b feature.
(<class '__main__.PlugIn'>,)
(<class '__main__.PlugIn'>,)
(<class '__main__.AFeature'>, <class '__main__.BFeature'>)
(<class 'object'>,)
(<class '__main__.PlugIn'>,) (<class '__main__.PlugIn'>,) (<class '__main__.AFeature'>, <class '__main__.BFeature'>) (<class 'object'>,)
辅助说明:
1、首先定义了一个能给对象扩展方法的类(PlugIn),具体添加的方法是plugin函数, 即这一句:
owner.__dict__[f.__name__] = f
owner就是类对象,也就是下面的c。
2、接着定义了两个用作例子的类AFeature、BFeature, 它们都是Plugin 的子类,所以它们都继承了plugin的方法。其中AFeature中的:
self._exported_methods.append(self.get_a_value)
就是将AFeature 的方法 添加(贮存)到一个列表中,以备plugin或者plugout函数的使用。
3、最后就是:
AFeature().plugin(c)
将c这个实例对象作为参数传入 plugin函数,然后给c添加AFeature的方法。 通过插件方式使用__dict__类Combine不会受到影响。
PS. 代码中的 super函数的写法只写 super().__init__() 也是可以的。 |
|