J'ai une série de classes Python dans un fichier. Certaines classes font référence à d'autres.
Mon code ressemble à ceci:
class A():
pass
class B():
c = C()
class C():
pass
En essayant de l'exécuter, j'obtiens NameError: name 'C' is not defined
. C'est assez correct, mais y a-t-il un moyen de faire en sorte que cela fonctionne ou dois-je réorganiser manuellement mes cours pour y répondre? En C++, je peux créer un prototype de classe. Est-ce que Python a un équivalent?
(Je joue en fait avec les modèles Django, mais j'ai essayé de ne pas compliquer les choses).
En Python, vous ne créez pas de prototype en tant que tel, mais vous devez comprendre la différence entre "attributs de classe" et attributs de niveau instance. Dans l'exemple que vous avez montré ci-dessus, vous déclarez un attribut de classe sur la classe B, et non un attribut de niveau instance.
C'est ce que vous recherchez:
class B():
def __init__(self):
self.c = C()
En réalité, tout ce qui précède constitue une excellente observation à propos de Python, mais aucune d’entre elles ne résoudra votre problème.
Django a besoin d'introspection.
La manière right de faire ce que vous voulez est la suivante:
class Car(models.Model):
manufacturer = models.ForeignKey('Manufacturer')
# ...
class Manufacturer(models.Model):
# ...
Notez l'utilisation du nom de classe en tant que string plutôt que la référence de classe littérale. Django offre cette alternative pour traiter exactement le problème que Python ne fournit pas de déclaration en aval.
Cette question me rappelle la question du support technique classique que vous devriez toujours demander à tout client ayant un problème: "Qu'est-ce que vous vraiment essayez de faire?"
Cela résoudrait votre problème tel que présenté (mais je pense que vous recherchez réellement un attribut d'instance auquel jholloway7 a répondu):
class A:
pass
class B:
pass
class C:
pass
B.c = C()
Python n'a pas de prototypes ni de classes ouvertes de style Ruby. Mais si vous en avez vraiment besoin, vous pouvez écrire une métaclasse qui surcharge new afin qu’elle effectue une recherche dans l’espace de nom actuel pour voir si la classe existe déjà et si elle retourne l’objet type existant au lieu de créer un objet. nouveau. J'ai fait quelque chose comme ça sur un ORM que j'ai écrit il y a un moment et cela a très bien fonctionné.
Toutes les réponses correctes concernant les attributs de classe et d'instance. Cependant, la raison pour laquelle vous avez une erreur est simplement l’ordre dans lequel vous définissez vos classes. Bien sûr, la classe C n’a pas encore été définie (car le code de niveau de classe est exécuté immédiatement à l’importation):
class A():
pass
class C():
pass
class B():
c = C()
Marchera.
Une décennie après que la question a été posée, j'ai rencontré le même problème. Bien que certaines personnes suggèrent que le référencement soit effectué dans la méthode init , il est parfois nécessaire d’accéder aux données en tant qu '"attribut de classe" avant que la classe ne soit réellement instanciée. Pour cette raison, j'ai proposé une solution simple utilisant un descripteur.
class A():
pass
class B():
class D(object):
def __init__(self):
self.c = None
def __get__(self, instance, owner):
if not self.c:
self.c = C()
return self.c
c = D()
class C():
pass
>>> B.c
>>> <__main__.C object at 0x10cc385f8>