python mix-in

Mix-in技术介绍

Mixin可 以译为混入,就是在不改变原对象的情况下对其进行扩展。本文介绍了在 Python 语言中,如何实现Mixin技术,及安装的相应技巧。
什么是Mix-in技术

Mix-in技术,中文不知道应该如何称呼,但意思好象是混入。它 的作用是,在运行期间,动态改变类的基类或类的方法,从而使得类的表现可以发生变化。可以用在一个通用类接口中,根据不同的选择使用不同的低层类实现,而 高层类不用发生变化。而且这一实现可以在运行过程中动态进行改变。由于我也是刚看到,大家有问题可以与我进行交流。这就是我看到的文 章的链接。

基类的增加

有一个类,

class foo:
    pass

我可以定义另外一个类,

class foobase:
    def hello(self):
        print "hello"

如果我直接调用:

>>> obj=foo()
>>> obj.hello()
这时你会看到出错。那么我可以这样:

>>> foo.bases +=(foobase,)
>>> obj.hello()
hello

成功了。原理是,每个类都有一个bases属性,它是一个 tuple,用来存放所有的基类。而且在运行中,可以动态改变。所以当我们向其中增加新的基类时,再次调用原来不存在的函数,由于基类中的函数已经存在 了,所以这次成功了。

这是一个最简单的应用,可以看到我们可以动态改变类的基类。 有几个注意事项要说一下:
bases是一个tuple,所以增加一个值要使用tuple类型,而单个元素tuple的写法为(foobase,)

类 必须先存在。所以,如果想使用这一技术,先要将相关的类的模块导入(import)。
由于Mix-in是一种动态技术,以多继承,对象为基础,而python正好是这样的语言,使得在python中实现 这一技术非常容易。

函数替换

在前面,简单地向大家介绍了一下Mix-in技术,它实现了基类的动态 增加。这样我们就可以在运行时,根据选择可以动态地增加基类,从而实现不同的目的。现在还有一个问题,就是,在基类与派生类中都有同名的函数,要如何处理 呢?
在Python中,如果派生类中有与基类同名的函数,那么调用 函数时,会调用派生类的函数,而不是基类的函数,可以测试一下:

>>> class foobase:
        def a(self):
                print "hello"
>>> class foo(foobase):
        def a(self):
                print "foo"
>>> c=foo()
>>> c.a()
foo

可以看出,执行的是foo类的函数。这样在使用Mix-in技术时,如果原来的类中存在与Mix类中同名的函数,那么 Mix类中的函数不会运行,如果想对其进行替换怎么办呢?方法就是使用getattr()和setattr()函数。当然还是最简单的。
定义两个类:

>>> class foobase:
        def a(self):
                print "hello"

>>> class foo:
        def a(self):
                print "foo"
>>> f=getattr(foobase, "a")
>>> setattr(foo, "a", f.im_func)     #f.im_func会得到真正的函数对象
>>> c=foo()
>>> c.a()
hello

可以看到,函数被替换了。
注意,使用dir(f)还会 看到其它的属性im_class,它表示这个函数属于哪个类,im_self表示属于哪个实例。

Mix-in安装函数

前面讲了基本的实现技术,下面给大家介绍一个Mix-in安装函数, 这个函数是从前面所说的文章copy下来的。

import types

def MixIn(pyClass, mixInClass, makeAncestor=0):
   if makeAncestor:
     if mixInClass not in pyClass.__bases__:
        pyClass.__bases__ = (mixInClass,) + pyClass.__bases__
   else:
     # Recursively traverse the mix-in ancestor
     # classes in order to support inheritance
     baseClasses = list(mixInClass.__bases__)
     baseClasses.reverse()
     for baseClass in baseClasses:
        MixIn(pyClass, baseClass)

     # Install the mix-in methods into the class
     for name in dir(mixInClass):
        if not name.startswith('__'):
        # skip private members
           member = getattr(mixInClass, name)
           if type(member) is types.MethodType:
               member = member.im_func
           setattr(pyClass, name, member)

这个函数可以将某个mix-in类安装为指定类的基类,同时可以通过关键字参数指定在基类中的顺序,是最前还是最后。 因为Python在处理基类时,是安顺序进行的,所以安装在最前则优先级最高。同时对于指定类的方法如果在mix-in类中存在,则将指定类中的方法替换 成mix-in类中的方法。

 if makeAncestor:
     if mixInClass not in pyClass.__bases__:
        pyClass.__bases__ = (mixInClass,) + pyClass.__bases__

如果makeAncestor为1,表示是安装在最前,则首先判断在pyClass的基类中是否存在 mixInClass类,如果不存在,再进行安装。

   else:
     # Recursively traverse the mix-in ancestor
     # classes in order to support inheritance
     baseClasses = list(mixInClass.__bases__)
     baseClasses.reverse()
     for baseClass in baseClasses:
        MixIn(pyClass, baseClass)

如果makeAncestor为0,并不将mixInClass安装在最后,原作者说他在实际中没有这样用的。那么它 完成什么任务呢?它实际完成了一个递归,即从mixInClass的最底层的基类开始(因为mixInClass也可能是多重继承而来的),对 pyClass中也存在的函数进行替换。这样执行完毕后,mixInClass类中,包含所有基类中的函数,如果有与pyClass类中的函数重名的,都 将pyClass中的函数替换成mixInClass相应的函数。(有些复杂!)

    # Install the mix-in methods into the class
     for name in dir(mixInClass):
        if not name.startswith('__'):
        # skip private members
           member = getattr(mixInClass, name)
           if type(member) is types.MethodType:
               member = member.im_func
           setattr(pyClass, name, member)

这步完成重名函数的替换。首先去掉私有方法(私有方法名前有’__’). 得到mixInClass类中的指定名字的方法对象,判断是否为方法类型。因为还有可能取到属性。在types模块中包含了一些类型,可以用它来判断是否 为方法类型。对于方法对象,如果是类方法,实际的函数应使用它的属性im_func。然后将pyClass相应的方法替换成mixInClass中的方 法。
这样就将mixInClass安装为pyClass的基类 了。
使用例子如:

from classa import classa
from classb import classb
MixIn(classa, classb) #将classb安装为classa的基类

版权所有 limodou(chatme@263.net) ,如要转载请保留此信息

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Python是一种高级编程语言,而FFmpeg是一个开源的音视频处理工具。在Python中,可以使用FFmpeg库来进行音频混合操作,其中amix是FFmpeg的一个音频混合滤镜。 amix滤镜可以将多个音频流混合成一个输出音频流。它可以通过设置参数来控制混合的方式,例如混合的音量比例、混合的时间范围等。 在Python中使用FFmpeg的amix滤镜,可以通过调用subprocess模块来执行FFmpeg命令。首先需要安装FFmpeg,并确保其可执行文件在系统的环境变量中。 以下是一个使用Python调用FFmpeg的amix滤镜进行音频混合的示例代码: ```python import subprocess def audio_mix(input_files, output_file, duration=None, volume=None): # 构建FFmpeg命令 cmd = ['ffmpeg'] for file in input_files: cmd.extend(['-i', file]) cmd.extend(['-filter_complex', 'amix=inputs={}:duration={}:dropout_transition=2'.format(len(input_files), duration)]) if volume: cmd.extend(['-vol', str(volume)]) cmd.append(output_file) # 执行FFmpeg命令 subprocess.run(cmd) # 示例调用 input_files = ['audio1.mp3', 'audio2.mp3'] output_file = 'output.mp3' duration = 'longest' # 混合后的音频时长以最长的输入音频为准 volume = 0.5 # 混合后的音量为输入音频的一半 audio_mix(input_files, output_file, duration, volume) ``` 这段代码将会将`audio1.mp3`和`audio2.mp3`两个音频文件进行混合,输出为`output.mp3`文件。混合后的音频时长以最长的输入音频为准,混合后的音量为输入音频的一半。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值