2009-01-24 80 views
14

我最近在python中發現了metaclasses。是否有人在Python /其他語言中使用元元類/元元元類?

基本上在python元類是創建一個類的類。有很多有用的理由你爲什麼要這麼做 - 例如任何類的初始化。在工廠註冊類,對屬性進行復雜的驗證,改變繼承的工作方式等等。所有這些都變得不僅可能而且簡單。

但是在Python中,元類也是普通類。於是,我開始想,如果抽象可以有效走得更高,而且在我看來,它可以和:

  • 元類對應於或實現某種模式中的角色(如GOF模式語言)。
  • 一元元類是模式本身(如果我們允許它來創建的代表抽象的角色,而不僅僅是一個單一的類類的元組)
  • 的元元元類是模式工廠,相當於到GOF模式分組,例如創造型,結構型,行爲型。一個工廠,你可以描述某種類型的問題,它會給你一組解決它的類。
  • meta-meta-meta-class(盡我所能),是一個模式工廠工廠,一個工廠,你可能可以描述你的問題的類型,它會給你一個模式工廠問。

我發現這個網上的一些東西,但大多不是非常有用。一個問題是不同的語言對元類的定義略有不同。

有沒有其他人這樣使用元類在python /其他地區,或該用在野外,或者想過見過?其他語言中的類似物是什麼?例如。在C++中,模板遞歸有多深?

我非常希望進一步研究它。

+0

更新:很長一段時間過去了。我使用了很多元類,我想他們很有幫助,但後來我完全脫離了元類。原因在於,在研究了域環境交互以及IBM的一些研究之後,我意識到類型對於對象固有的概念本身就是有缺陷的。相反,類型取決於「誰的問題」。對一隻鳥來說,一棵樹只是一個築巢的地方。對於一個記錄者來說,收入來源,還是稅收評估者,或許還有其他的東西。 – 2011-03-16 18:55:12

回答

4

Smalltalk中的類系統是一個有趣的研究。在Smalltalk中,一切都是一個對象,每個對象都有一個類。這並不意味着層次結構趨於無窮大。如果我沒記錯的話,它會是這樣的:

5 - >整數 - > Integer類 - >元類 - >元類類 - >元類 - > ...(它循環)

在哪裏 ' - >'表示「是一個實例」。

7

回答你的問題:沒有。

隨意進一步研究。

但是請注意,你已經與代碼混爲一談設計模式(這只是想法),(這是一個實現)。

良好的代碼往往反映了一些聯鎖設計模式。沒有簡單的方法來形式化這個。你可以做的最好的是一張不錯的圖片,寫得很好的文檔,以及反映各種設計模式的方法名稱。

還要注意的是一個元類是一類。這是一個循環。沒有更高層次的抽象。那時,它只是意圖。元元類的概念並不多 - 它是元類的元類,這是愚蠢的,但在技術上是可能的。然而,這只是一個階級。


編輯

「是創建元類真的這麼傻?如何其效用突然冒了出來班?」

創建類的類很好。這是非常多的。目標類是元類或抽象超類或具體類的事實並不重要。元類創建類。他們可能會製造其他的元類,這很奇怪,但它們仍然只是構成類的元類。

實用程序「突然」耗盡,因爲在創建另一個元類的元類中沒有您需要(或甚至可以寫入)的實際事物。並不是它「突然」變得愚蠢。這是沒有用的。

隨着我的種子,隨時研究它。例如,實際上編寫一個構建另一個元類的元類。玩的開心。那裏可能有用處。

面向對象的一點是編寫模擬真實世界實體的類定義。因此,元類有時很容易定義幾個相關類的交叉方面。 (這是做一些面向方面編程的一種方法。)這是一個元類實際上可以做到的事情;這是一個可以容納一些功能的地方,如__new__(),這些功能並不屬於課程本身的適當部分。

+0

我尊重你的觀點。我不應該將元類作爲模式/角色,而只是將它們實現。 但是避免形式化,因爲它可能很難?創建元類的類真的很愚蠢嗎?他們的效用如何突然耗盡? 即使是元類也表現出相似之處。 – 2009-01-29 04:03:03

+0

@ mike.amy:通過「硬」我的意思是難以理解。不是「有點具有挑戰性」。將一些經過深思熟慮的設計模式分解爲形式化是非常困難的 - 有時是不可能的。一些好的設計決定是習慣,很難正式確定。 – 2009-01-29 11:12:01

18

這讓我想起了一些人似乎在做一個「模式的通用實現」的永恆追求。就像可以創建任何對象的工廠(including another factory)或通用依賴注入框架一樣,它的管理要複雜得多,而不是簡單地編寫實際上確實是的代碼。

當我管理Zend Framework項目時,我不得不將處理抽象的人處理成肚臍眼。我拒絕了一些建議,以創建沒有做任何事情的組件,它們只是GoF模式的神奇實現,好像模式本身就是一個目標,而不是達到目標的手段。

抽象的收益遞減點。一些抽象是很好的,但最終你需要編寫一些有用的代碼。

否則它只是turtles all the way down

+1

海龜+1! – Seth 2010-01-28 23:18:07

+1

我們需要想出Discworld建築模式 – 2010-12-02 11:14:35

6

在2007年編程語言會議歷史中,Simon Peyton Jones評論說Haskell允許使用類型類進行元編程,但是它的真正的烏龜一直在下降。你可以在Haskell中使用meta-meta-meta等程序,但是他從來沒有聽說過任何使用超過3級間接尋址的人。

Guy Steele指出它在Lisp和Scheme中是一樣的。你可以使用反引號和evals來進行元編程(你可以將反引號看作是一個Python lambda,但是),但是他從來沒有看到使用過3個反引號。

想必他們已經看到了比你或我曾經有過的更多的代碼,所以它只是略微誇張地說,沒有人超越了meta的三個層次。

如果你仔細想想,大多數人都不會使用元編程,並且兩個級別都很難包圍你的頭。我猜想三個幾乎是不可能的,而最後一個嘗試四個的人最終會進入一個避難所。

1

從我第一次瞭解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 
相關問題