鱼C论坛

 找回密码
 立即注册
楼主: 小甲鱼

[扩展阅读] Python Mixin 编程机制(转)

  [复制链接]
发表于 2021-8-16 17:51:54 | 显示全部楼层
小有所获
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-9-18 15:51:59 | 显示全部楼层
看来还是得多学习
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-9-21 20:06:07 | 显示全部楼层
第三个没看懂
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 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__() 也是可以的。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 2 反对 0

使用道具 举报

发表于 2022-3-2 19:46:05 From FishC Mobile | 显示全部楼层
还可以坚持下去
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-4-8 17:21:31 | 显示全部楼层
van314159 发表于 2016-8-15 21:29
首先定义了一个能给对象添加方法的类(PlugIn),具体添加的方法是plugin函数, 即这一句 owner就是类对象, ...

self._exported_methods不是空列表吗?这里是什么意思呢
for f in self._exported_methods:
            owner.__dict__[f.__name__] = f
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-8-5 15:48:23 | 显示全部楼层
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2024-7-18 19:07:21 | 显示全部楼层
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-11-22 03:11

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表