首页 > Python > 什么是mixin,为什么它有用?

什么是mixin,为什么它有用?

上一篇 下一篇

Programming Python中,Mark Lutz提到了mixin这个术语。我来自C / C++ / C#背景,以前从未听说过这个词。什么是混合?

阅读此示例的行间(我已经链接到它,因为它很长),我假设这是使用多重继承来扩展类而不是适当的子类的情况。这是对的吗?

为什么我要这样做而不是将新功能放入子类中?就此而言,为什么混合/多重继承方法比使用组合更好?

混合与多重继承的区别是什么?这只是语义问题吗?

分割线

网友回答:

首先,您应该注意,mixins 仅存在于多继承语言中。你不能在Java或C#中进行混音。

基本上,mixin 是一种独立的基本类型,它为子类提供有限的功能和多态共振。如果您正在考虑 C#,请考虑一个您不必实际实现的接口,因为它已经实现;您只需从中继承并从其功能中受益即可。

混合通常范围很窄,并不意味着要扩展。

[编辑 — 关于原因:]

我想我应该解决为什么,既然你问了。最大的好处是你不必一遍又一遍地自己做。在 C# 中,混合可以从处置模式中受益的最大位置。每当您实现 IDisposable 时,您几乎总是希望遵循相同的模式,但您最终会编写和重新编写相同的基本代码,但略有变化。如果有可扩展的处置混合,您可以节省很多额外的打字时间。

[编辑 2 — 回答您的其他问题]

混合与多重继承的区别是什么?这只是语义问题吗?

是的。mixin 和标准多重继承之间的区别只是语义问题;具有多重继承的类可能会使用 mixin 作为该多重继承的一部分。

mixin 的要点是创建一个类型,该类型可以通过继承“混合”到任何其他类型,而不会影响继承类型,同时仍为该类型提供一些有益的功能。

同样,考虑一个已经实现的接口。

我个人不使用mixins,因为我主要使用不支持它们的语言进行开发,所以我很难想出一个像样的例子来为你提供“啊哈!”的时刻。但我会再试一次。我将使用一个人为的例子——大多数语言已经以某种方式提供了这个功能——但希望这将解释应该如何创建和使用 mixins。这里是:

假设您有一个类型,您希望能够序列化到 XML 和从 XML 序列化。您希望该类型提供一个“ToXML”方法,该方法返回一个字符串,其中包含一个包含该类型的数据值的 XML 片段,以及一个“FromXML”,该方法允许该类型从字符串中的 XML 片段重建其数据值。同样,这是一个人为的示例,因此您可能使用文件流或语言运行时库中的 XML 编写器类…无论什么。关键是您希望将对象序列化为 XML,并从 XML 中获取新对象。

此示例中的另一个重要点是您希望以通用方式执行此操作。您不希望必须为要序列化的每个类型实现“ToXML”和“FromXML”方法,您需要一些通用方法来确保您的类型将执行此操作并且它正常工作。您希望代码重用。

如果您的语言支持它,您可以创建 XmlSerializable mixin 来为您完成工作。此类型将实现 ToXML 和 FromXML 方法。它将使用一些对示例不重要的机制,能够从与它混合的任何类型的类型中收集所有必要的数据,以构建 ToXML 返回的 XML 片段,并且同样能够在调用 FromXML 时恢复该数据。

和。。就是这样。若要使用它,您需要将任何需要序列化为 XML 继承的类型 XmlSerializable。每当需要序列化或反序列化该类型时,只需调用 ToXML 或 FromXML。事实上,由于 XmlSerializable 是一个成熟的类型和多态的,因此您可以设想构建一个文档序列化程序,它对原始类型一无所知,只接受 XmlSerializable 类型的数组。

现在想象一下将此方案用于其他事情,例如创建一个 mixin,以确保混合它的每个类都记录每个方法调用,或者创建一个 mixin,为混合它的类型提供事务性。这个清单可以继续下去。

如果您只是将 mixin 视为一种小型基本类型,旨在向类型添加少量功能而不会以其他方式影响该类型,那么您就是黄金。

希望。🙂

分割线

网友回答:

混合是一种特殊的多重继承。使用混合有两种主要情况:

  1. 您希望为类提供许多可选功能。
  2. 您想在许多不同的类中使用一个特定功能。

对于第一个示例,请考虑werkzeug的请求和响应系统。我可以通过说来制作一个普通的旧请求对象:

from werkzeug import BaseRequest

class Request(BaseRequest):
    pass

如果我想添加接受标头支持,我会这样做

from werkzeug import BaseRequest, AcceptMixin

class Request(AcceptMixin, BaseRequest):
    pass

如果我想创建一个支持接受标头、etags、身份验证和用户代理支持的请求对象,我可以这样做:

from werkzeug import BaseRequest, AcceptMixin, ETagRequestMixin, UserAgentMixin, AuthenticationMixin

class Request(AcceptMixin, ETagRequestMixin, UserAgentMixin, AuthenticationMixin, BaseRequest):
    pass

区别是微妙的,但在上面的例子中,mixin 类并不是独立存在的。在更传统的多重继承中,(例如)可能更像 .也就是说,该类可能会被设计为独立存在。AuthenticationMixinAuthenticator

分割线

网友回答:

这个答案旨在通过以下示例来解释混合:

  • 自包含:简短,无需了解任何库即可理解示例。
  • 在Python中,而不是在其他语言中。
    可以理解的是,有来自其他语言(如 Ruby)的示例,因为该术语在这些语言中更为常见,但这是一个 Python 线程。

它还应审议有争议的问题:

多重继承是否有必要表征混合蛋白?

定义

我还没有看到来自“权威”来源的引用清楚地说明什么是 Python 中的混合。

我已经看到了 mixin 的 2 种可能定义(如果它们被认为与其他类似概念(如抽象基类)不同),人们并不完全同意哪一个是正确的。

不同语言的共识可能有所不同。

定义1:无多重继承

mixin 是一个类,使得该类的某些方法使用类中未定义的方法。

因此,该类不是要实例化,而是用作基类。否则,实例将具有在不引发异常的情况下无法调用的方法。

一些来源添加的一个约束是该类可能不包含数据,只包含方法,但我不明白为什么这是必要的。然而,在实践中,许多有用的mixin没有任何数据,而没有数据的基类更容易使用。

一个典型的例子是仅从和实现所有比较运算符:<===

class ComparableMixin(object):
    """This class has methods which use `<=` and `==`,
    but this class does NOT implement those methods."""
    def __ne__(self, other):
        return not (self == other)
    def __lt__(self, other):
        return self <= other and (self != other)
    def __gt__(self, other):
        return not self <= other
    def __ge__(self, other):
        return self == other or self > other

class Integer(ComparableMixin):
    def __init__(self, i):
        self.i = i
    def __le__(self, other):
        return self.i <= other.i
    def __eq__(self, other):
        return self.i == other.i

assert Integer(0) <  Integer(1)
assert Integer(0) != Integer(1)
assert Integer(1) >  Integer(0)
assert Integer(1) >= Integer(1)

# It is possible to instantiate a mixin:
o = ComparableMixin()
# but one of its methods raise an exception:
#o != o 

这个特殊的例子可以通过装饰器来实现,但这里的游戏是重新发明轮子:functools.total_ordering()

import functools

@functools.total_ordering
class Integer(object):
    def __init__(self, i):
        self.i = i
    def __le__(self, other):
        return self.i <= other.i
    def __eq__(self, other):
        return self.i == other.i

assert Integer(0) < Integer(1)
assert Integer(0) != Integer(1)
assert Integer(1) > Integer(0)
assert Integer(1) >= Integer(1)

定义2:多重继承

mixin 是一种设计模式,其中基类的某些方法使用它未定义的方法,并且该方法旨在由另一个基类实现,而不是像定义 1 中那样由派生类实现。

术语mixin类是指旨在用于该设计模式的基类(TODO那些使用该方法的基类,还是那些实现它的人?

确定给定的类是否是mixin并不容易:该方法可以在派生类上实现,在这种情况下,我们回到定义1。你必须考虑作者的意图。

这种模式很有趣,因为可以将功能与不同的基类选择重新组合:

class HasMethod1(object):
    def method(self):
        return 1

class HasMethod2(object):
    def method(self):
        return 2

class UsesMethod10(object):
    def usesMethod(self):
        return self.method() + 10

class UsesMethod20(object):
    def usesMethod(self):
        return self.method() + 20

class C1_10(HasMethod1, UsesMethod10): pass
class C1_20(HasMethod1, UsesMethod20): pass
class C2_10(HasMethod2, UsesMethod10): pass
class C2_20(HasMethod2, UsesMethod20): pass

assert C1_10().usesMethod() == 11
assert C1_20().usesMethod() == 21
assert C2_10().usesMethod() == 12
assert C2_20().usesMethod() == 22

# Nothing prevents implementing the method
# on the base class like in Definition 1:

class C3_10(UsesMethod10):
    def method(self):
        return 3

assert C3_10().usesMethod() == 13

权威的 Python 实例

在collections.abc的官方文档中,文档明确使用了术语Mixin Methods

它指出,如果一个类:

  • 实现__next__
  • 从单个类继承Iterator

然后该类免费获得一个 mixin 方法__iter__

因此,至少在文档的这一点上,mixin 不需要多重继承,并且与定义 1 一致。

当然,文档在不同点上可能是矛盾的,其他重要的 Python 库可能在其文档中使用其他定义。

本页也使用了术语,这清楚地表明类喜欢并且可以称为Mixin类。Set mixinSetIterator

其他语言

  • Ruby:显然不需要 mixin 的多重继承,正如 Programming Ruby 和 The Ruby 编程语言等主要参考书中提到的
  • C++:设置的方法是一个纯虚拟方法。virtual=0
    定义 1 与抽象类(具有纯虚拟方法的类)的定义一致。
    无法实例化该类。

    定义 2 可以通过虚拟继承实现:从两个派生类进行多重继承

模板简介:该模板名称为【什么是mixin,为什么它有用?】,大小是暂无信息,文档格式为.编程语言,推荐使用Sublime/Dreamweaver/HBuilder打开,作品中的图片,文字等数据均可修改,图片请在作品中选中图片替换即可,文字修改直接点击文字修改即可,您也可以新增或修改作品中的内容,该模板来自用户分享,如有侵权行为请联系网站客服处理。欢迎来懒人模板【Python】栏目查找您需要的精美模板。

相关搜索
  • 下载密码 lanrenmb
  • 下载次数 905次
  • 使用软件 Sublime/Dreamweaver/HBuilder
  • 文件格式 编程语言
  • 文件大小 暂无信息
  • 上传时间 03-18
  • 作者 网友投稿
  • 肖像权 人物画像及字体仅供参考
栏目分类 更多 >
热门推荐 更多 >
微信图片 单页式简历模板 自适应 微信素材 企业网站 微信文章 微信模板 微信公众平台 响应式 html5
您可能会喜欢的其他模板