是否有人在Python /其他语言中使用元元类/元元元类?
我最近在python中发现了metaclasses。是否有人在Python /其他语言中使用元元类/元元元类?
基本上在python元类是创建一个类的类。有很多有用的理由你为什么要这么做 - 例如任何类的初始化。在工厂注册类,对属性进行复杂的验证,改变继承的工作方式等等。所有这些都变得不仅可能而且简单。
但是在Python中,元类也是普通类。于是,我开始想,如果抽象可以有效走得更高,而且在我看来,它可以和:
- 元类对应于或实现某种模式中的角色(如GOF模式语言)。
- 一元元类是模式本身(如果我们允许它来创建的代表抽象的角色,而不仅仅是一个单一的类类的元组)
- 的元元元类是模式工厂,相当于到GOF模式分组,例如创造型,结构型,行为型。一个工厂,你可以描述某种类型的问题,它会给你一组解决它的类。
- meta-meta-meta-class(尽我所能),是一个模式工厂工厂,一个工厂,你可能可以描述你的问题的类型,它会给你一个模式工厂问。
我发现这个网上的一些东西,但大多不是非常有用。一个问题是不同的语言对元类的定义略有不同。
有没有其他人这样使用元类在python /其他地区,或该用在野外,或者想过见过?其他语言中的类似物是什么?例如。在C++中,模板递归有多深?
我非常希望进一步研究它。
Smalltalk中的类系统是一个有趣的研究。在Smalltalk中,一切都是一个对象,每个对象都有一个类。这并不意味着层次结构趋于无穷大。如果我没记错的话,它会是这样的:
5 - >整数 - > Integer类 - >元类 - >元类类 - >元类 - > ...(它循环)
在哪里 ' - >'表示“是一个实例”。
回答你的问题:没有。
随意进一步研究。
但是请注意,你已经与代码混为一谈设计模式(这只是想法),(这是一个实现)。
良好的代码往往反映了一些联锁设计模式。没有简单的方法来形式化这个。你可以做的最好的是一张不错的图片,写得很好的文档,以及反映各种设计模式的方法名称。
还要注意的是一个元类是一类。这是一个循环。没有更高层次的抽象。那时,它只是意图。元元类的概念并不多 - 它是元类的元类,这是愚蠢的,但在技术上是可能的。然而,这只是一个阶级。
编辑
“是创建元类真的这么傻?如何其效用突然冒了出来班?”
创建类的类很好。这是非常多的。目标类是元类或抽象超类或具体类的事实并不重要。元类创建类。他们可能会制造其他的元类,这很奇怪,但它们仍然只是构成类的元类。
实用程序“突然”耗尽,因为在创建另一个元类的元类中没有您需要(或甚至可以写入)的实际事物。并不是它“突然”变得愚蠢。这是没有用的。
随着我的种子,随时研究它。例如,实际上编写一个构建另一个元类的元类。玩的开心。那里可能有用处。
面向对象的一点是编写模拟真实世界实体的类定义。因此,元类有时很容易定义几个相关类的交叉方面。 (这是做一些面向方面编程的一种方法。)这是一个元类实际上可以做到的事情;这是一个可以容纳一些功能的地方,如__new__()
,这些功能并不属于课程本身的适当部分。
我尊重你的观点。我不应该将元类作为模式/角色,而只是将它们实现。 但是避免形式化,因为它可能很难?创建元类的类真的很愚蠢吗?他们的效用如何突然耗尽? 即使是元类也表现出相似之处。 – 2009-01-29 04:03:03
@ mike.amy:通过“硬”我的意思是难以理解。不是“有点具有挑战性”。将一些经过深思熟虑的设计模式分解为形式化是非常困难的 - 有时是不可能的。一些好的设计决定是习惯,很难正式确定。 – 2009-01-29 11:12:01
这让我想起了一些人似乎在做一个“模式的通用实现”的永恒追求。就像可以创建任何对象的工厂(including another factory)或通用依赖注入框架一样,它的管理要复杂得多,而不是简单地编写实际上确实是的代码。
当我管理Zend Framework项目时,我不得不将处理抽象的人处理成肚脐眼。我拒绝了一些建议,以创建没有做任何事情的组件,它们只是GoF模式的神奇实现,好像模式本身就是一个目标,而不是达到目标的手段。
抽象的收益递减点。一些抽象是很好的,但最终你需要编写一些有用的代码。
否则它只是turtles all the way down。
海龟+1! – Seth 2010-01-28 23:18:07
我们需要想出Discworld建筑模式 – 2010-12-02 11:14:35
在2007年编程语言会议历史中,Simon Peyton Jones评论说Haskell允许使用类型类进行元编程,但是它的真正的乌龟一直在下降。你可以在Haskell中使用meta-meta-meta等程序,但是他从来没有听说过任何使用超过3级间接寻址的人。
Guy Steele指出它在Lisp和Scheme中是一样的。你可以使用反引号和evals来进行元编程(你可以将反引号看作是一个Python lambda,但是),但是他从来没有看到使用过3个反引号。
想必他们已经看到了比你或我曾经有过的更多的代码,所以它只是略微夸张地说,没有人超越了meta的三个层次。
如果你仔细想想,大多数人都不会使用元编程,并且两个级别都很难包围你的头。我猜想三个几乎是不可能的,而最后一个尝试四个的人最终会进入一个避难所。
从我第一次了解Python中的元类开始,我一直在想“元元类可以做什么?”。这至少在10年前 - 现在,就在几个月前,对我来说很清楚,Python类创建中有一种机制实际上涉及到“元元”类。因此,有可能设法想象一些用途。
回顾Python中的对象实例化:每当使用与调用普通函数相同的语法“调用”它的类来实例化Python中的对象时,该类的__new__
和__init__
。什么“编排”这些方法在课堂上的调用恰恰是课程的'类别'__call__
方法。通常当用Python写元类时,元类的__new__
或__init__
方法是自定义的。
所以,事实证明,通过写“元元”级一个可以自定义其__call__
方法,从而控制其参数传递和元类的__new__
和__init__
方法,如果一些其他的代码被调用之前和之后。最终发现的结果是,metcalsses本身通常是硬编码的,即使在非常大的项目中,也只需少数几个(如果有的话)。因此,任何可能在“meta meta”调用中完成的定制通常都是直接在元类本身上完成的。
而它们,还有那些其他较少用于Python元类的用法 - 可以在元类中定制__add__
方法,以便它们定义的类是“可添加的”,并创建派生类,将两个添加的类作为超类。该机制对元类也是完全有效的 - 因此,我们只是“有一些实际的代码”,它遵循一个“meta-meta”类的例子,它允许通过将类添加到类声明中来构造类的“元类” :
class MM(type):
def __add__(cls, other):
metacls = cls.__class__
return metacls(cls.__name__ + other.__name__, (cls, other), {})
class M1(type, metaclass=MM):
def __new__(metacls, name, bases, namespace):
namespace["M1"] = "here"
print("At M1 creation")
return super().__new__(metacls, name, bases, namespace)
class M2(type, metaclass=MM):
def __new__(metacls, name, bases, namespace):
namespace["M2"] = "there"
print("At M2 creation")
return super().__new__(metacls, name, bases, namespace)
,我们可以看到交互式控制台上工作:通过允许
In [22]: class Base(metaclass = M1 + M2):
...: pass
...:
At M1 creation
At M2 creation
注意的是Python不同的元类通常很难结合起来,这其实是有用的用户自制元类与库或stdlib结合使用,而不必将其明确声明为前者的父代:
In [23]: import abc
In [24]: class Combined(metaclass=M1 + abc.ABCMeta):
...: pass
...:
At M1 creation
更新:很长一段时间过去了。我使用了很多元类,我想他们很有帮助,但后来我完全脱离了元类。原因在于,在研究了域环境交互以及IBM的一些研究之后,我意识到类型对于对象固有的概念本身就是有缺陷的。相反,类型取决于“谁的问题”。对一只鸟来说,一棵树只是一个筑巢的地方。对于一个记录者来说,收入来源,还是税收评估者,或许还有其他的东西。 – 2011-03-16 18:55:12