2009-01-24 36 views
14

Gần đây tôi đã phát hiện thấy metaclasses trong python.Có ai sử dụng meta-meta-classes/meta-meta-meta-classes bằng Python/các ngôn ngữ khác không?

Về cơ bản một metaclass trong python là một lớp tạo ra một lớp. Có nhiều lý do hữu ích tại sao bạn muốn làm điều này - bất kỳ kiểu khởi tạo lớp nào chẳng hạn. Đăng ký các lớp học trên các nhà máy, xác nhận các thuộc tính phức tạp, thay đổi cách thức hoạt động của thừa kế, vv Tất cả điều này trở thành không chỉ có thể nhưng đơn giản.

Nhưng trong trăn, metaclasses cũng là lớp đồng bằng. Vì vậy, tôi bắt đầu tự hỏi liệu trừu tượng có thể hữu ích đi cao hơn không, và có vẻ như với tôi rằng nó có thể và:

  • metaclass tương ứng hoặc thực hiện vai trò (như trong ngôn ngữ mẫu GOF).
  • một meta-metaclass là mô hình riêng của mình (nếu chúng ta cho phép nó để tạo ra các bộ của các tầng lớp đại diện cho vai trò trừu tượng, chứ không phải chỉ là một lớp duy nhất)
  • một meta-meta-metaclass là một nhà máy mẫu, tương ứng đối với các nhóm mẫu GOF, ví dụ Creational, Structural, Behavioral. Một nhà máy nơi bạn có thể mô tả một trường hợp của một loại vấn đề nhất định và nó sẽ cung cấp cho bạn một bộ các lớp học đã giải quyết nó.
  • siêu meta meta meta meta (theo như tôi có thể đi), là nhà máy sản xuất mẫu , một nhà máy mà bạn có thể mô tả loại vấn đề của mình và nó sẽ mang đến cho bạn hỏi.

Tôi đã tìm thấy một số nội dung về trực tuyến này, nhưng hầu hết không hữu ích. Một vấn đề là các ngôn ngữ khác nhau xác định metaclasses hơi khác nhau.

Có ai khác sử dụng metaclasses như thế này trong python/ở nơi khác, hoặc nhìn thấy điều này được sử dụng trong tự nhiên, hoặc nghĩ về nó? Các chất tương tự trong các ngôn ngữ khác là gì? Ví dụ. trong C++ làm thế nào sâu đệ quy mẫu có thể đi?

Tôi rất muốn nghiên cứu thêm.

+0

Cập nhật: một thời gian dài đã trôi qua. Tôi đã sử dụng metaclasses rất nhiều và tôi đoán chúng rất hữu ích, nhưng sau đó tôi đã hoàn thành metaclasses. Lý do là sau khi nhìn vào tương tác ngữ cảnh miền, và một số nghiên cứu của IBM, tôi nhận ra rằng khái niệm về kiểu nội tại đối với một đối tượng là chính nó thiếu sót. Thay vào đó, loại phụ thuộc vào 'có yêu cầu'. Với một con chim, một cái cây chỉ là một nơi để xây tổ. Với một người ghi chép, một nguồn thu nhập, cho một người đánh giá thuế, có lẽ một cái gì đó khác. –

Trả lời

4

Hệ thống lớp học trong Smalltalk là một điều thú vị để nghiên cứu. Trong Smalltalk, mọi thứ đều là một đối tượng và mọi đối tượng đều có một lớp. Điều này không ngụ ý rằng hệ thống phân cấp chuyển sang vô cùng. Nếu tôi nhớ không lầm thì nó đi một cái gì đó như:

5 -> Integer -> lớp Integer -> metaclass -> lớp metaclass -> metaclass -> ... (nó vòng)

đâu '->' biểu thị "là một thể hiện của".

+0

Cảm ơn, một số người khác đã đề cập đến smalltalk. Tôi sẽ phải đào tôi ra khỏi máy ảo và so sánh metaclasses của smalltalk với python's. –

7

Để trả lời câu hỏi của bạn: không.

Hãy nghiên cứu thêm.

Lưu ý, tuy nhiên, bạn đã lồng việc các mẫu thiết kế (mà chỉ là ý tưởng) với mã (đó là một thực hiện.)

Tốt mã thường phản ánh một số mẫu thiết kế lồng vào nhau. Không có cách nào dễ dàng để chính thức hóa điều này. Điều tốt nhất bạn có thể làm là một hình ảnh đẹp, các tài liệu được viết tốt và các tên phương thức phản ánh các mẫu thiết kế khác nhau.

Cũng lưu ý rằng một lớp meta là một lớp. Đó là một vòng lặp. Không có mức trừu tượng cao hơn. Tại thời điểm đó, nó chỉ là ý định. Ý tưởng của meta-meta-class không có nghĩa là nhiều - đó là một meta-class cho các lớp meta, mà là ngớ ngẩn nhưng về mặt kỹ thuật có thể. Đó là tất cả chỉ là một lớp học, tuy nhiên.


Sửa

"Are lớp tạo metaclasses thực sự rất ngớ ngẩn? Làm thế nào để tiện ích của họ đột nhiên chạy ra ngoài?"

Lớp học tạo lớp học là tốt.Nó khá là nhiều. Thực tế là lớp đích là một lớp meta hoặc một siêu lớp trừu tượng hoặc một lớp cụ thể không quan trọng. Metaclasses tạo ra các lớp học. Họ có thể tạo ra những chiếc metaclasses khác, điều này thật kỳ lạ, nhưng chúng vẫn chỉ là những chiếc metaclasses tạo nên những lớp học.

Tiện ích "đột nhiên" hết vì không có thứ thực sự bạn cần (hoặc thậm chí có thể viết) trong một metaclass tạo ra một metaclass khác. Nó không phải là nó "đột nhiên" trở nên ngớ ngẩn. Đó là không có gì hữu ích ở đó.

Khi tôi hạt giống, hãy nghiên cứu nó. Ví dụ, thực sự viết một metaclass xây dựng một metaclass khác. Chúc vui vẻ. Có thể có cái gì đó hữu ích ở đó.

Điểm của OO là viết các định nghĩa lớp mô hình các thực thể trong thế giới thực. Như vậy, một metaclass đôi khi có ích để xác định các mặt cắt ngang của một số lớp liên quan. (Đó là một cách để làm một số lập trình hướng Aspect.) Đó là tất cả một metaclass thực sự có thể làm; đó là một nơi để giữ một vài chức năng, như __new__(), không phải là một phần của chính lớp đó.

+0

Tôi tôn trọng điểm của bạn. Tôi không nên so sánh metaclasses dưới dạng các mẫu/vai trò mà chỉ cần thực hiện chúng. Nhưng tránh chính thức hóa vì nó có thể khó? Các lớp học có tạo nên metaclasses thực sự ngớ ngẩn không? Tiện ích của họ đột nhiên chạy ra sao? Ngay cả metaclasses cũng có những điểm giống nhau. –

+0

@ mike.amy: bởi "cứng" tôi có nghĩa là không thể hiểu nổi. Không phải là "một chút khó khăn". Rất khó - đôi khi không thể - để giải tán một số mẫu thiết kế được suy nghĩ kỹ lưỡng thành các hình thức. Một số quyết định thiết kế tốt là thói quen và khó chính thức hóa. –

18

Điều này nhắc tôi về nhiệm vụ vĩnh cửu mà một số người dường như đang thực hiện "thực hiện chung một mẫu." Giống như một nhà máy có thể tạo bất kỳ đối tượng nào (including another factory) hoặc khung tiêm phụ thuộc mục đích chung phức tạp hơn nhiều so với việc chỉ viết mã thực tế không điều gì đó.

Tôi đã phải đối phó với ý định của mọi người về trừu tượng đến điểm rốn khi nhìn vào dự án Zend Framework. Tôi đã từ chối một loạt các đề xuất để tạo ra các thành phần không làm bất cứ điều gì, chúng chỉ là sự triển khai phép thuật của các mẫu GoF, như thể mô hình là một mục tiêu trong chính nó, thay vì một phương tiện cho mục tiêu.

Có một điểm thu nhập giảm dần để trừu tượng hóa. Một số trừu tượng là tuyệt vời, nhưng cuối cùng bạn cần phải viết mã mà làm một cái gì đó hữu ích.

Nếu không, chỉ cần turtles all the way down.

+1

+1 cho rùa! – Seth

+1

Chúng ta cần phải tìm ra một mô hình kiến ​​trúc Discworld –

+0

Bạn đang đăng bài nhắc tôi về một [máy Von Neumann] (https://en.wikipedia.org/wiki/Monolith_ (Space_Odyssey)), còn gọi là Monoliths, từ Dòng Space Odyssey. –

6

Trong hội nghị Ngôn ngữ lập trình ngôn ngữ trong năm 2007, Simon Peyton Jones nhận xét rằng Haskell cho phép lập trình meta bằng cách sử dụng loại lớp, nhưng thực sự rùa của nó tất cả các con đường xuống. Bạn có thể dùng meta-meta-meta-meta etc trong Haskell, nhưng rằng anh ta chưa bao giờ nghe nói đến bất cứ ai sử dụng hơn 3 cấp độ không xác định.

Guy Steele đã chỉ ra rằng điều tương tự trong Lisp và Đề án. Bạn có thể làm meta-lập trình bằng cách sử dụng backticks và evals (bạn có thể nghĩ về một backtick như là một lambda Python, kinda), nhưng anh ta không bao giờ nhìn thấy hơn 3 backticks được sử dụng.

Có lẽ họ đã nhìn thấy nhiều mã hơn bạn hoặc tôi từng có, do đó, chỉ có một chút cường điệu khi nói rằng không ai từng vượt quá 3 cấp độ meta.

Nếu bạn nghĩ về điều đó, hầu hết mọi người không bao giờ sử dụng lập trình meta, và hai cấp độ là khá khó khăn để quấn đầu của bạn xung quanh. Tôi đoán rằng ba là gần như không thể, và anh chàng cuối cùng để thử bốn đã kết thúc trong một tị nạn.

+0

Bạn thực sự cảm thấy như bạn đang đi điên cố gắng để đạt được qua một vài cấp độ. 1 cho việc xin tị nạn. – Triptych

1

Kể từ khi lần đầu tiên tôi hiểu metaclasses trong Python, tôi vẫn tự hỏi "những gì có thể được thực hiện với một lớp meta meta?". Đây là cách đây ít nhất 10 năm - và bây giờ, chỉ một vài tháng trước, nó trở nên rõ ràng đối với tôi rằng có một cơ chế trong việc tạo lớp Python thực sự liên quan đến một lớp "meta-meta". Và do đó, có thể thử tưởng tượng một số sử dụng cho điều đó.

Để tóm tắt lại đối tượng trong Python: Bất cứ khi nào một đối tượng khởi tạo trong Python bằng cách "gọi" lớp của nó với cùng cú pháp được sử dụng để gọi hàm bình thường, lớp __new____init__ của lớp. Những gì "dàn nhạc" gọi các phương pháp này trên lớp là chính xác phương pháp class'metaclass '__call__. Thông thường khi người ta viết một metaclass bằng Python, phương pháp __new__ hoặc __init__ của metaclass được tùy chỉnh. Vì vậy, nó chỉ ra rằng bằng cách viết một "meta-meta" lớp người ta có thể tùy chỉnh phương pháp __call__ của nó và do đó kiểm soát các tham số được thông qua và phương pháp __new____init__ metaclass, và nếu một số mã khác được gọi là trước sau đó. Điều cuối cùng là những bản thân metcalsses thường được hardcoded và một nhu cầu chỉ là một vài, nếu có, ngay cả trong các dự án rất lớn. Vì vậy, bất kỳ tùy chỉnh nào có thể được thực hiện tại cuộc gọi "meta meta" thường được thực hiện trực tiếp trên chính metaclass.

Và chúng, có những cách sử dụng ít thường xuyên hơn cho metaclasses Python - người ta có thể tùy chỉnh phương pháp __add__ trong metaclass để các lớp mà chúng định nghĩa là "có thể thêm" và tạo một lớp dẫn xuất có hai lớp được thêm vào làm siêu lớp . Cơ chế đó cũng hoàn toàn hợp lệ với metaclasses - do đó, chỉ cần chúng ta "có một số mã thực", sau một ví dụ về "meta-meta" class cho phép người ta tạo "metaclasses" cho một lớp chỉ bằng cách thêm chúng vào khai báo lớp :

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) 

Và chúng ta có thể thấy rằng làm việc trên giao diện điều khiển tương tác:

In [22]: class Base(metaclass = M1 + M2): 
    ...:  pass 
    ...: 
At M1 creation 
At M2 creation 

Lưu ý rằng metaclasses như khác nhau bằng Python thường rất khó kết hợp, điều này thực sự có thể hữu ích bằng cách cho phép người dùng tạo metaclass được kết hợp với một thư viện hoặc một thư viện, mà không cần phải khai báo một cách rõ ràng như là cha mẹ của cựu:

In [23]: import abc 

In [24]: class Combined(metaclass=M1 + abc.ABCMeta): 
    ...:  pass 
    ...: 
At M1 creation 
Các vấn đề liên quan