2009-06-25 46 views
6

Tôi có hai lớp tham chiếu đến nhau, nhưng rõ ràng trình biên dịch vẫn phàn nàn. Có cách nào để khắc phục điều này?các lớp python tham chiếu với nhau

EDIT

Thực ra mã của tôi là hơi khác so với những gì Hank Gay sử dụng. Vì vậy, python chắc chắn có thể đối phó với một số loại tài liệu tham khảo vòng tròn, nhưng nó tung ra một lỗi trong tình huống sau đây. Dưới đây là những gì tôi có và tôi nhận được 'tên không xác định lỗi'

class X(models.Model): 

     creator = Registry() 
     creator.register(Y) 

class Y(models.Model): 
    a = models.ForeignKey(X) 
    b = models.CharField(max_length=200) 

Hy vọng điều này sẽ giúp làm rõ. Bất kỳ đề xuất.

+4

Điều gì "hiển nhiên"? Nó khiếu nại ở đâu? Hiển thị mã? Tham chiếu thông tư không có vấn đề gì đối với Python, vấn đề nằm ở nơi khác. –

+0

Mã trông như thế nào? –

+0

wow ... * rolleyes * – Robbie

Trả lời

15

Trong trăn, mã trong một lớp được chạy khi lớp được tải.

Bây giờ, điều đó có nghĩa là gì? ;-)

Xét đoạn mã sau:

class x: 
    print "hello" 
    def __init__(self): print "hello again" 

Khi bạn tải các module có chứa mã, trăn sẽ in hello. Bất cứ khi nào bạn tạo một x, python sẽ in hello again.

Bạn có thể nghĩ đến số def __init__(self): ... tương đương với __init__ = lambda self: ..., ngoại trừ không có giới hạn lambda trăn nào được áp dụng. Tức là, def là một nhiệm vụ, có thể giải thích tại sao mã bên ngoài phương thức nhưng không phải bên trong phương thức được chạy.

Khi mã của bạn nói

class X(models.Model): 
    creator = Registry() 
    creator.register(Y) 

Bạn tham khảo Y khi các mô-đun được nạp, trước Y có giá trị. Bạn có thể nghĩ class X như một bài tập (nhưng tôi không thể nhớ cú pháp để tạo các lớp nặc danh off-hand; có lẽ nó là một lời khẩn cầu type?)

Những gì bạn có thể muốn làm điều này là:

class X(models.Model): 
    pass 
class Y(models.Model): 
    foo = something_that_uses_(X) 
X.bar = something_which_uses(Y) 

Tức là, tạo thuộc tính lớp là X tham chiếu Y sau Y được tạo. Hoặc ngược lại: tạo Y trước tiên, sau đó X, sau đó là các thuộc tính của Y phụ thuộc vào X, nếu điều đó dễ dàng hơn.

Hope this helps :)

2

CẬP NHẬT: Anh ấy đã thay đổi câu hỏi sau câu trả lời của tôi. Giải pháp hiện được chấp nhận là tốt hơn trong ánh sáng của câu hỏi mới.

Bạn đang nói gì là vấn đề?

class A(object): 
    def __init__(self): 
     super(A, self).__init__() 


    def b(self): 
     return B() 


class B(object): 
    def __init__(self): 
     super(B, self).__init__() 


    def a(self): 
     return A() 

Việc biên dịch này chỉ chạy tốt.

+0

Một số thông tin bổ sung: Điều này có hiệu quả. Nhưng nó đi kèm với một mức giá: Nó chỉ hoạt động nếu bạn đặt tất cả các lớp vào một tập tin duy nhất. Điều này là khá bất tiện: Nó có thể rất trầm, tôi không biết, nhưng tôi biết nó phá vỡ với thực hành OOP tốt của việc sử dụng một tập tin riêng cho mỗi lớp (public). –

2

Miễn là bạn đang làm việc trong một phương pháp, bạn có thể truy cập đối tượng lớp.

Do đó ví dụ trên không có vấn đề gì nếu creator.register(Y) được di chuyển bên trong __init__. Tuy nhiên, bạn không thể có tham chiếu vòng tròn tới các lớp bên ngoài các phương thức.

+1

Câu trả lời này không giải thích bất cứ điều gì. Nó cung cấp cho một "workaround" mà không hiểu hoặc giải thích vấn đề thực sự, được giải thích trong các câu trả lời của Jonas và John Machin. –

2

Lỗi là thực hiện creator.register(Y) đang cố gắng trong thời gian (thực thi) định nghĩa của lớp X, và ở giai đoạn đó, lớp Y không được định nghĩa. Hiểu điều này: classdef là các câu lệnh được thực hiện (thường là tại thời điểm nhập); chúng không phải là "khai báo".

Đề xuất: cho chúng tôi biết những gì bạn đang cố gắng đạt được - có lẽ là câu hỏi mới.

-2

Sự cố rất có thể không phải là Python. Tôi nghĩ rằng đó là một vấn đề SQL. Các lớp là thông qua một lớp trừu tượng được chuyển đổi thành một truy vấn SQL để tạo một bảng. Bạn đang cố gắng tham khảo từ một bảng khác mà tại thời điểm đó chưa tồn tại.

Trong SQL bạn sẽ giải quyết điều này bằng cách tạo bảng đầu tiên mà không có tài liệu tham khảo và sau đó thay đổi chúng để làm cho những tài liệu tham khảo,

Tuy nhiên tôi không chắc chắn về câu trả lời của tôi, vì vậy mang nó với rất nhiều gia vị, tôi sẽ thực sự khá ngạc nhiên nếu lớp trừu tượng cơ sở dữ liệu của Django không xử lý các tham chiếu chéo độc đáo.

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