Python classes that reference each other

I have two classes that reference each other, but obviously the compiler complains. Is there any way around this?

EDIT

Actually my code is a little different than what Hank Gay uses. Thus, python can definitely deal with some kinds of circular references, but it throws an error in the following situation. The following is what I have, and I get "name Y, no specific error"

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

Hope this helps clarify. Any suggestions.

+6
python oop django
source share
6 answers

In python, the code in the class runs when the class loads.

Now what the hell does that mean ?; -)

Consider the following code:

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

When loading a module containing the code, python will print hello . Whenever you create x , python will print hello again .

You can think of def __init__(self): ... as the equivalent with __init__ = lambda self: ... , except that none of the python lambda restrictions apply. That is, def is an assignment that can explain why methods are run outside the code, but not internal methods.

When your code says

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

You access Y when the module is loaded, before Y matters. You can think of class X as an assignment (but I can't remember the syntax for creating anonymous classes outside the field, maybe this is a type call?)

What you can do is:

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

That is, create attributes of class x , which will create a link Y after Y Or vice versa: first create Y , then x , then Y attributes, which depend on x , if it's easier.

Hope this helps :)

+15
source share

UPDATE: He changed the question after my answer. The current decision is better in light of a new issue.

What do you say is the problem?

 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() 

This compiles and runs just fine.

+2
source share

While you are working as part of a method, you can access the class object.

So the above example has no problem if creator.register(Y) moves inside __init__ . However, you cannot have circular references to classes outside of methods.

+2
source share

The error is that the execution of creator.register(Y) is executed during the (executable) definition of class X, and at this point, class Y is not defined. Understand this: class and def are statements that are executed (usually during import); they are not “declarations”.

Suggestion: tell us what you are trying to achieve - perhaps as a new question.

+2
source share

As we well know, this looks like a self-evident contradiction, which we are trying to present as two independent, but interdependent entities only from the moment they were born in the physical world. But when it comes to the field of software, we often encounter issues such as circular or reciprocal links. This may be more serious in object-oriented design, in which interacting program elements are usually defined and connected to each other in imitation of the same way as physical, but still as a purely logical existence.

In many programming languages, these problems were solved by declaring the elements to be referenced in time before their elements to be referenced, simply in the form of signatures (without body definitions) for functions or classes. However, this kind of evasive trick seems more inaccessible and useless for a script-based language such as Python.

In Python, we better approach the circular reference in terms of software development as follows:

  1. It is much better to redesign classes that are not round, if possible; There are several ways (for example, a de- or composition class, callback function, observer or subscriber patterns, etc.) so that links between elements appear in the same class, are deleted or inverted.

  2. In cases where the linearization of some circular chains between elements can cause a more serious problem in some aspect, such as quality or productivity, we can take another measure to divide their traditional construction phase into two: creation and structuring. For example, two people in friends who are destined to be born absolutely after observing another birth can do as they were born first, and then make friends just before any significant and observable events occur. Please note that if we are faced with some kind of extreme complexity or need some high degree of integrity when working with combined objects, the use of the Factory template will pay off.

+1
source share

The problem is most likely not Python. I would think this is a SQL problem. Classes, through an abstraction layer converted to an SQL query, create a table. You are trying to link from one table to another that does not yet exist.

In SQL, you would solve this by creating a table without links first and then modify them to make these links,

However, I am not sure about my answer, so bring it with a lot of seasoning, I would really be surprised if the Django database abstraction layer is not related to cross-references.

-2
source share

All Articles