Update - 2012/12/13động thêm các phương pháp có hoặc không có metaclass
Chỉ cần làm rõ - Tôi không quá nhiều quan tâm đến cách làm thế nào để thêm các phương pháp đến các lớp học - như bạn có thể nhìn thấy dưới đây trong tôi câu hỏi và trong câu trả lời của mọi người, có nhiều hơn một cách để làm điều đó (lưỡi trong má và mũ nón để tự Perl của tôi). Điều tôi quan tâm là tìm hiểu sự khác biệt cơ bản của việc thêm phương pháp vào các lớp học bằng cách sử dụng các cách tiếp cận khác nhau và câu hỏi lớn thực sự là lý do tại sao tôi cần phải sử dụng metaclasses cho. Ví dụ: A Primer on Python Metaclass Programming nói rằng:
Có lẽ cách sử dụng phổ biến nhất của metaclasses [...]: thêm, xóa, đổi tên hoặc thay thế các phương thức cho những người được xác định trong lớp được tạo.
Và vì có nhiều cách để làm điều đó, tôi bối rối và tìm kiếm giải thích.
Cảm ơn!
Original - 2012/12/12
tôi cần phải tự động thêm các phương pháp để một lớp học (và các lớp học mới được tạo ra dựa trên lớp đó). Tôi đã đưa ra hai cách tiếp cận, một phương pháp liên quan đến metaclass, một cái khác đang làm mà không có một. Tôi không thể nhìn thấy bất kỳ sự khác biệt trong những gì hai cách tiếp cận cho tôi khác với thực tế sau này không liên quan đến "ma thuật đen" metaclass;)
Tiếp cận # 1với metaclass:
class Meta(type):
def __init__(cls, *args, **kwargs):
setattr(cls, "foo", lambda self: "[email protected]%s(class %s)" % (self,
cls.__name__))
class Y(object):
__metaclass__ = Meta
y = Y()
y.foo() # Gives '[email protected]<__main__.Y object at 0x10e4afd10>(class Y)'
Tiếp cận # 2mà không metaclass:
class Z(object):
def __init__(self):
setattr(self.__class__, "foo",
lambda self: "[email protected]%s(class %s)" %
(self, self.__class__.__name__))
z = Z()
z.foo() # Gives '[email protected]<__main__.Z object at 0x10c865dd0>(class Z)'
theo như tôi có thể cho biết, cả hai cách tiếp cận đều cho tôi kết quả tương tự và "biểu hiện". Ngay cả khi tôi cố gắng tạo một lớp mới bằng cách sử dụng type("NewClassY", (Y,), {})
hoặc type("NewClassZ", (Z,), {})
Tôi nhận được kết quả mong đợi tương tự mà không khác nhau giữa hai phương pháp tiếp cận.
Vì vậy, tôi đang tự hỏi nếu có thực sự là bất kỳ "cơ bản" khác biệt trong cách tiếp cận, hoặc nếu có bất cứ điều gì mà sẽ "cắn" tôi sau này nếu tôi sử dụng một trong hai # 1 hoặc # 2 hoặc nếu nó chỉ là một cú pháp?
PS: Có, tôi đã đọc các chủ đề khác ở đây nói về metaclasses trong Python và mô hình dữ liệu pythonic.
Bạn có thể gọi 'Y.foo' và 'Z.foo' sử dụng cả hai cách tiếp cận? – Blender
Sự khác biệt là metaclass sẽ tạo ra các phương thức tại thời điểm lớp được định nghĩa và '__init__'way sẽ tạo ra các phương thức khi bạn khởi tạo lớp. Ngoài ra còn có nhiều thừa kế (mixins) mà bạn có thể sử dụng để thêm các phương thức. –
@Blender Không, bạn không thể gọi chúng như thế vì chúng không phải là "phương pháp lớp". – TomasHeran