2011-07-27 31 views
10

Tôi đã học muộn Python, và tôi ngạc nhiên bởi khả năng lập trình meta metaprogram tuyệt vời của nó. Trước đây tôi đã đi qua thuật ngữ 'lập trình meta thời gian chạy' là khi tôi đọc về Smalltalk, theo như tôi biết tự hào về khả năng lập trình siêu lập trình thời gian chạy tốt nhất. Python hoạt động tốt như thế nào so với Smalltalk w.r.t. metaprogramming? Sự khác biệt đáng chú ý giữa các cách tiếp cận được thực hiện bởi hai ngôn ngữ là gì?Python và Smalltalk - So sánh khả năng lập trình Metaprogram

+0

Trong trăn, các loại và các cuộc gọi là lớp đầu tiên, và nó là hợp lý để soạn chúng, hoặc thậm chí tạo ra chúng trong thời gian chạy. Bất cứ điều gì huyền diệu hơn điều này thường được cho là un * "pythonic" *. Chúng tôi không muốn tạo DSL trong python, chúng tôi chỉ sử dụng python. – SingleNegationElimination

+0

@TokenMacGuy: Cảm ơn bạn đã phản hồi! Câu hỏi của tôi không phải là liệu metaprogramming có phải là Pythonic hay không, hoặc liệu người ta có nên làm điều đó hay không. Đây là một câu hỏi học thuật đơn giản về nghiên cứu so sánh khả năng lập trình meta của hai ngôn ngữ. – missingfaktor

+3

Một trong những ý tưởng lớn của Smalltalk là trực giao. Frankly Python chịu sự tôn trọng này. Không phải mọi thứ đều hoạt động trên mọi thứ. Ví dụ: inspect.getargspec() không hoạt động trên các hàm dựng sẵn (trong trình thông dịch C). eval chỉ hoạt động cho các chuỗi biểu thức và exec chỉ hoạt động đối với các chuỗi lệnh. Biểu thức lambda không thể được ngâm. Có lẽ PyPy không có những vấn đề này, tôi không chắc chắn. Nhưng tôi yêu Python rất nhiều và thấy rất thuận tiện khi sử dụng metaclasses, currying và thỉnh thoảng descriptor trong các ứng dụng thực tế. – wberry

Trả lời

12

Python thực sự nắm giữ khá tốt ở đây. Smalltalk thường không phân biệt rõ ràng giữa chương trình và metaprogramm, nhưng Python rõ ràng hơn - ví dụ, cú pháp đặc biệt cho trang trí hoặc quy ước đặt tên __foo__() cho móc lập trình meta. Đây là một điều tốt.

Mặt khác, đó là một chút so sánh giữa táo và cam. Smalltalk là một ngôn ngữ nhỏ hơn, chặt chẽ hơn so với Python, và do đó, chỉ có ít tài liệu hơn để thao tác với metaprograms. Ví dụ: xem xét __getattr__(). Đây là một hook cho phép các đối tượng Python cung cấp một tùy chỉnh thực hiện truy cập thuộc tính. Smalltalk không có bất cứ điều gì như thế này. Nhưng! Smalltalk thực thi đóng gói chặt chẽ hơn về trạng thái bên trong của một đối tượng, và không có tương đương với cú pháp object.attribute được sử dụng trong Python. Vì vậy, đọc trạng thái của đối tượng yêu cầu phải trải qua một phương thức ... chính xác là những gì mà __getattr__() cung cấp. Vì vậy, đối với rất nhiều trường hợp bạn muốn sử dụng __getattr__() bằng Python, bạn chỉ cần viết một phương thức bình thường trong Smalltalk - không cần lập trình meta.

Và nó giống như tất cả các nơi: Python __getitem__() và bạn bè có thể viết các lớp bắt chước danh sách hoặc từ điển. Smalltalk không cần điều đó vì Array và Dictionary chỉ là các lớp Smalltalk thông thường và không có cú pháp đặc biệt để sử dụng chúng. Python __eq__() và như vậy cho phép quá tải toán tử. Smalltalk không có toán tử, vì vậy bạn có thể triển khai + mà không cần thực hiện bất kỳ điều gì đặc biệt. Ngữ cảnh của Python cung cấp một số công cụ tiện lợi để thực hiện các trình quản lý ngữ cảnh của riêng bạn. Smalltalk không có cấu trúc with, nhưng nó có cú pháp thực sự nhẹ cho lambdas, cho phép bạn thực hiện cùng một loại điều theo một cách đơn giản.

Cơ sở lập trình meta của Smalltalk có xu hướng khá thấp. Ví dụ: bạn có thể tạo các trường hợp CompiledMethod của riêng mình và dán chúng vào từ điển của lớp học. Bạn cũng có thể viết trình biên dịch của riêng bạn và xác định rằng tất cả các phương thức của một lớp cụ thể được biên dịch với nó. Điều đó cho phép tất cả mọi thứ - tôi đã thấy các dự án thử nghiệm với các cú pháp thay thế, bytecode cụ để lược tả, bẫy đọc và ghi vào các biến mẫu để duy trì trong suốt, v.v.

Cơ sở lập trình siêu lập trình của Smalltalk rất mạnh, nhưng chúng không được tổ chức gọn gàng như Python và không được sử dụng thường xuyên.

10

Được đăng dưới dạng câu trả lời theo yêu cầu của người hỏi.

Một trong những ý tưởng lớn của Smalltalk là trực giao. Frankly Python chịu sự tôn trọng này. Không phải mọi thứ đều hoạt động trên mọi thứ. Ví dụ:

  • inspect.getargspec() không hoạt động trên được xây dựng trong các chức năng hoặc các kết quả của các cuộc gọi đến functools.partial (trong thông dịch C anyway).
  • eval chỉ hoạt động đối với các chuỗi biểu thức và exec chỉ hoạt động đối với chuỗi tuyên bố.
  • Không thể chọn biểu thức Lambda.
  • myclass = type('x', (object,), {'__init__': partial(foo, value)}) tạo lớp không thể khởi tạo được, trong khi chuyển biểu thức lambda tương đương thay vì partial hoạt động tốt. (Mặc dù đây có thể chỉ là một lỗi không phải là một tính năng.)

Có lẽ PyPy không có những vấn đề này, tôi không chắc chắn. Nhưng tôi yêu Python rất nhiều và thấy rất thuận tiện khi sử dụng metaclasses, currying và thỉnh thoảng descriptor trong các ứng dụng thực tế.

+1

Rất nhiều sự khác biệt giữa hàm C và Python thực sự bị loại bỏ trong PyPy (bạn thực sự không thể phân biệt chúng bằng hành vi). hạn chế tẩy rửa ở lại (chỉ vì tẩy là điên) – fijal

+0

@fijal: Có gì điên rồ về tẩy? – missingfaktor

+1

Pickling dựa trên trạng thái toàn cầu tham chiếu tất cả các chức năng và các lớp theo tên. Xem NamedTuple crazy sys._getframe hack để làm việc xung quanh nó cho một ví dụ. Bạn không thể tham chiếu lambda bằng tên trong không gian tên toàn cầu, do đó bạn không thể chọn chúng (đây là cách nó được thiết kế và nó hoạt động trong PyPy theo cách tương tự) – fijal

Các vấn đề liên quan