2010-03-23 24 views
5

Đây là vấn đề của tôi. Tôi muốn lớp sau có một loạt thuộc tính thuộc tính. Tôi có thể viết tất cả chúng ra như foobar hoặc dựa trên một số ví dụ khác mà tôi đã thấy, có vẻ như tôi có thể sử dụng trình trang trí lớp học, metaclass hoặc ghi đè phương thức __new__ để đặt thuộc tính tự động. Tôi chỉ không chắc những gì "đúng" cách để làm điều đó sẽ được.Tôi có nên sử dụng metaclass, trang trí lớp học hoặc ghi đè phương pháp __new__ không?

class Test(object): 
    def calculate_attr(self, attr): 
     # do calculaty stuff 
     return attr 

    @property 
    def foo(self): 
     return self.calculate_attr('foo') 

    @property 
    def bar(self): 
     return self.calculate_attr('bar') 
+2

Khi nghi ngờ, luôn luôn đi với đơn giản và rõ ràng. Nếu * bạn * không thể dễ dàng tìm ra nó, cả hai đều không thể giả vờ (như tôi), người sẽ được yêu cầu duy trì mã của bạn. –

+0

Khi bạn thay đổi bản chất câu hỏi của mình, tốt nhất là chỉ nên mở một câu hỏi mới. –

Trả lời

4

Magic là xấu. Nó làm cho mã của bạn khó hiểu hơn và duy trì. Bạn hầu như không bao giờ cần metaclasses hoặc __new__.

Dường như trường hợp sử dụng của bạn có thể được thực hiện với mã khá đơn giản (chỉ với một gợi ý nhỏ của ma thuật):

class Test(object): 
    def calculate_attr(self, attr): 
     return something 

    def __getattr__(self, name): 
     return self.calculate_attr(name) 
+1

@ Bạn hầu như không bao giờ cần metaclasses hoặc '__new__': Tôi rất không đồng ý. Tại công ty của tôi, chúng tôi đã có hai lần, khi chúng tôi có động cơ tốt để sử dụng metaclasses. Đầu tiên là tạo lớp trừu tượng cho một cơ sở dữ liệu tùy chỉnh mà chúng tôi đã sử dụng và lớp kia đang tạo hệ thống Mô hình của riêng chúng ta cho ldap. Tôi thực sự không thể hiểu được, nơi mà sự oán giận này đối với metaclasses. Đó là một khái niệm dễ nắm bắt và thực sự hữu ích trong các tình huống nhất định. – gruszczy

+1

@gruszczy, metaclasses không khó hiểu, chúng thực sự là một ý tưởng khá dễ dàng, mặc dù cú pháp và cách sử dụng chúng trong Python khiến một số người gặp rắc rối. Tuy nhiên, chúng dễ bị lỗi do cách chúng truyền và đôi khi khó kết hợp - không thể tự động có một lớp sử dụng hai metaclasses trong việc xây dựng của nó ngay cả khi đó là một hoạt động hoàn toàn hợp lý. Vấn đề này càng trở nên trầm trọng hơn bởi thực tế metaclasses thường không bị lộ ra như là một phần của API công cộng của hệ thống. –

2

của một __new__ metaclass không trở thành __new__ cho lớp bạn make-nó được sử dụng để làm cho lớp đó. đối tượng lớp thực tế được trả về bởi metaclass. Một thể hiện mới của một lớp được trả về bởi __new__.

xem xét như sau (điên) mã:.

def MyMetaClass(name, bases, dict): 
    print "name", name 
    print "bases", bases 
    print "dict", dict 
    return 7 

class C('hello', 'world'): 
    __metaclass__ = MyMetaClass 

    foo = "bar" 

    def baz(self, qux): 
     pass 

print "C", C 

(tôi đã sử dụng một hàm thay vì một lớp học như metaclass Bất kỳ callable có thể được sử dụng như một metaclass, nhưng nhiều người chọn sang phải của họ như các lớp học mà kế thừa từ type với mới overrided. Sự khác biệt giữa một một chức năng rất tinh tế.)

Nó ra

name C 
bases ('hello', 'world') 
dict {'baz': <function baz at 0x4034c844>, '__module__': '__main__', 'foo': 'bar', '__metaclass__': <function MyMetaClass at 0x40345c34>} 
C 7 

Điều đó có giúp bạn hiểu rõ hơn về những gì metaclasses ?

Bạn sẽ rất hiếm khi cần xác định metaclass của riêng bạn.

+0

Không nên là "đối tượng lớp thực tế" thay vì "đối tượng lớp thực sự"? –

1

Metaclass được sử dụng khi lớp mới - không phải trường hợp - được tạo. Bằng cách này bạn có thể cho các lớp học đăng ký ví dụ (django hiện nó và sử dụng nó ví dụ để tạo ra các bảng trong cơ sở dữ liệu). Kể từ class là một hướng dẫn bạn có thể suy nghĩ về như một trang trí cho một lớp học.

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