2009-06-19 27 views
19

có cách nào để tham chiếu tên lớp từ trong khai báo lớp không? một ví dụ sau:Định nghĩa lớp tham chiếu tự trong python

class Plan(SiloBase): 
    cost = DataField(int) 
    start = DataField(System.DateTime) 
    name = DataField(str) 
    items = DataCollection(int) 
    subPlan = ReferenceField(Plan) 

tôi đã có một metaclass mà đọc thông tin này và thực hiện một số thiết lập, và các lớp cơ sở thực hiện một số nội dung tiết kiệm thông thường. tôi rất thích có thể tạo ra các định nghĩa đệ quy như thế này, nhưng cho đến nay trong thử nghiệm của tôi tôi đã không thể có được hiệu ứng tôi mong muốn, thường chạy vào một lỗi "Kế hoạch không được xác định". Tôi hiểu những gì đang xảy ra, tên của lớp không nằm trong phạm vi của lớp.

Trả lời

8

tôi đã có một metaclass mà đọc thông tin này và thực hiện một số thiết lập

Hầu hết các khuôn khổ mà sử dụng metaclasses cung cấp một cách để giải quyết này. Ví dụ, Django:

subplan = ForeignKey('self') 

Google App Engine:

subplan = SelfReferenceProperty() 

Vấn đề với các giải pháp như tacking một tài sản bổ sung về sau hoặc sử dụng __new__ là hầu hết metaclasses ORM mong đợi các thuộc tính lớp để tồn tại vào thời điểm đó khi lớp được tạo ra.

+1

Tuyệt vời mà bạn đã đề cập đến Google App Engine! +1 –

+1

Trong Google App Engine - DB có điều này, nhưng NDB thì không. Để xem cách thực hiện việc này trong NDB, hãy xem tại đây: http://stackoverflow.com/questions/3531936/selfreferenceproperty-question – Brad

22

Hãy thử điều này:

class Plan(SiloBase): 
    cost = DataField(int) 
    start = DataField(System.DateTime) 
    name = DataField(str) 
    items = DataCollection(int) 

Plan.subPlan = ReferenceField(Plan) 

OR dùng __new__ như thế này:

class Plan(SiloBase): 

    def __new__(cls, *args, **kwargs): 
     cls.cost = DataField(int) 
     cls.start = DataField(System.DateTime) 
     cls.name = DataField(str) 
     cls.items = DataCollection(int) 
     cls.subPlan = ReferenceField(cls) 
     return object.__new__(cls, *args, **kwargs) 
+0

tuyệt vời, điều này thực hiện chính xác những gì tôi muốn, và nó không phải là một hack khổng lồ. vẫn cố gắng để quấn đầu của tôi xung quanh toàn bộ điều năng động này, haha ​​ – pedlar

0

Không, bạn không thể làm điều đó. Hãy suy nghĩ về những gì sẽ xảy ra nếu bạn đã làm điều này:

OtherPlan = Plan 
other_plan = OtherPlan() 

Tại instantiation của other_plan, tên của lớp là gì?

Dù sao, loại điều này được thực hiện tốt nhất theo phương pháp __new__, có tham số cls đề cập đến lớp.

1

Tôi hiểu điều gì đang xảy ra, tên của lớp học không nằm trong phạm vi bên trong lớp học.

Không chính xác. Tên của lớp chưa được xác định khi xác định nội dung của nó (ví dụ: phạm vi).

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