Pregunta

Tengo una serie de clases de Python en un archivo. Algunas clases Referencia otros.

Mi código es algo como esto:

class A():
    pass

class B():
    c = C()

class C():
    pass

Tratando de correr que, consigo NameError: name 'C' is not defined. Muy bien, pero ¿hay alguna manera de hacer que funcione, o tengo que manualmente volver a ordenar mis clases para acomodar? En C ++, puedo crear un prototipo de clase. Python no tiene un equivalente?

(En realidad estoy jugando con modelos de Django, pero no intentado complicar las cosas).

¿Fue útil?

Solución

En Python no se crea un prototipo per se, pero sí es necesario para entender la diferencia entre "atributos de clase" y atributos a nivel de instancia. En el ejemplo que has demostrado anteriormente, que está declarando un atributo de clase de la clase B, no un atributo de instancia.

Esto es lo que busca:

class B():
    def __init__(self):
        self.c = C()

Otros consejos

En realidad, todo lo anterior son grandes observaciones sobre Python, pero ninguno de ellos va a resolver su problema.

Django necesita una introspección cosas.

La forma derecho para hacer lo que quiere es la siguiente:

class Car(models.Model):
    manufacturer = models.ForeignKey('Manufacturer')
    # ...

class Manufacturer(models.Model):
    # ...

Tenga en cuenta el uso del nombre de la clase como un cadena en lugar de la referencia de clase literal. Django ofrece esta alternativa para hacer frente a exactamente el problema que Python no proporciona declaraciones adelantadas.

Esta pregunta me recuerda a la pregunta de soporte clásico que siempre se debe pedir a cualquier cliente con un problema: "¿Qué estás realmente tratando de hacer"

Esto resolvería el problema que se presenta (pero creo que usted está realmente en busca de un atributo de instancia como jholloway7 respondió):

class A:
    pass

class B:
    pass

class C:
    pass

B.c = C()

Python no tiene prototipos o clases abiertas de estilo Ruby. Pero si realmente los necesita, puede escribir una metaclase que sobrecarga nueva para que se realiza una búsqueda en el espacio de nombres actual para ver si la clase ya existe, y si lo hace devuelve el tipo de objeto existente en lugar de crear una nueva. Hice algo como esto en un ORM que escribo un tiempo atrás y que ha funcionado muy bien.

Todas las respuestas correctas sobre la clase vs atributos de instancia. Sin embargo, la razón por la que tiene un error es sólo el fin de definir sus clases. Por supuesto clase C aún no ha sido definida (como el código de nivel de clase se ejecuta inmediatamente en la importación):

class A():
    pass

class C():
    pass

class B():
    c = C()

funcionará.

Se le pide una década después de la pregunta, me he encontrado con el mismo problema. Mientras que las personas sugieren que la referencia debe hacerse dentro de la Método init, hay momentos en los que necesite acceder a los datos como un "atributo de clase" antes de la clase es en realidad una instancia. Por esa razón, he llegado a una solución sencilla utilizando un descriptor.

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>
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top