paquetes - lista de modulos de python
Dependencia del módulo Python (5)
¿De verdad necesita hacer referencia a las clases en el tiempo de definición de clase? es decir.
class CRoom(object):
person = CPerson("a person")
O (más probable), solo necesita usar CPerson en los métodos de su clase (y viceversa). p.ej:
class CRoom(object):
def getPerson(self): return CPerson("someone")
Si es el segundo, no hay problema, ya que para cuando se llama al método en lugar de definirse, el módulo se importará. Su único problema es cómo referirse a él. Es probable que estés haciendo algo como:
from CRoom import CPerson # or even import *
Con los módulos de referencia circular, no puede hacer esto, ya que en el punto en que un módulo importa otro, el cuerpo de los módulos originales no habrá terminado de ejecutarse, por lo que el espacio de nombres estará incompleto. En su lugar, use referencias calificadas. es decir:
#croom.py
import cperson
class CRoom(object):
def getPerson(self): return cperson.CPerson("someone")
Aquí, python no necesita buscar el atributo en el espacio de nombres hasta que realmente se llame al método, momento en el cual ambos módulos deberían haber completado su inicialización.
Ok, tengo dos módulos, cada uno contiene una clase, el problema es que sus clases se referencian entre sí.
Digamos, por ejemplo, que tenía un módulo de sala y un módulo de persona que contenía CRoom y CPerson.
La clase CRoom contiene información sobre la sala y una lista CPerson de cada uno en la sala.
La clase CPerson, sin embargo, a veces necesita usar la clase CRoom para la sala, por ejemplo para encontrar la puerta, o también para ver quién más está en la sala.
El problema es que los dos módulos se importan entre sí. Acabo de recibir un error de importación que se está importando en segundo lugar :(
En c ++ podría resolver esto al solo incluir los encabezados, y dado que en ambos casos las clases solo tienen punteros a la otra clase, una declaración directa sería suficiente para el encabezado, por ejemplo:
class CPerson;//forward declare
class CRoom
{
std::set<CPerson*> People;
...
¿Hay alguna forma de hacer esto en Python, aparte de colocar ambas clases en el mismo módulo o algo así?
editar: ejemplo agregado de python que muestra un problema al usar las clases anteriores
error:
Rastreo (llamadas recientes más última):
Archivo "C: / Projects / python / test / main.py", línea 1, en
desde la sala de importación CRoom
Archivo "C: / Projects / python / test / room.py", línea 1, en
de la persona que importa CPerson
Archivo "C: / Projects / python / test / person.py", línea 1, en
desde la sala de importación CRoom
ImportError: no se puede importar el nombre CRoom
room.py
from person import CPerson
class CRoom:
def __init__(Self):
Self.People = {}
Self.NextId = 0
def AddPerson(Self, FirstName, SecondName, Gender):
Id = Self.NextId
Self.NextId += 1#
Person = CPerson(FirstName,SecondName,Gender,Id)
Self.People[Id] = Person
return Person
def FindDoorAndLeave(Self, PersonId):
del Self.People[PeopleId]
person.py
from room import CRoom
class CPerson:
def __init__(Self, Room, FirstName, SecondName, Gender, Id):
Self.Room = Room
Self.FirstName = FirstName
Self.SecondName = SecondName
Self.Gender = Gender
Self.Id = Id
def Leave(Self):
Self.Room.FindDoorAndLeave(Self.Id)
@ S.Lott, si no importo nada en el módulo de la sala, en su lugar obtengo un error indefinido (lo importé en el módulo principal como lo mostraste)
Rastreo (llamadas recientes más última):
Archivo "C: / Projects / python / test / main.py", línea 6, en
Ben = Room.AddPerson (''Ben'', ''Blacker'', ''Hombre'')
Archivo "C: / Projects / python / test / room.py", línea 12, en AddPerson
Person = CPerson (FirstName, SecondName, Gender, Id)
NameError: el nombre global ''CPerson'' no está definido
Además, la razón por la que hay diferentes módulos es donde encontré el problema para comenzar con la clase contenedora (por ejemplo, la sala) ya es de varios cientos de líneas, así que quería los elementos en ella (por ejemplo, las personas) en un archivo separado.
EDITAR: main.py
from room import CRoom
from person import CPerson
Room = CRoom()
Ben = Room.AddPerson(''Ben'', ''Blacker'', ''Male'')
Tom = Room.AddPerson(''Tom'', ''Smith'', ''Male'')
Ben.Leave()
Podrías alias el segundo.
importar CRoom
CPerson = CRoom.CPerson
Primero, nombrar tus argumentos con letras mayúsculas es confuso. Como Python no tiene una comprobación de tipo estática formal, utilizamos UpperCase
para UpperCase
a una clase y lowerCase
para lowerCase
a un argumento.
En segundo lugar, no nos molestamos con CRoom y CPerson. La mayúscula es suficiente para indicar que es una clase. La letra C no se usa. Room
Person
.
En tercer lugar, generalmente no ponemos cosas en el formato de una clase por archivo . Un archivo es un módulo de Python, y con mayor frecuencia importamos un módulo completo con todas las clases y funciones.
[Soy consciente de que esos son hábitos; no es necesario que los rompa hoy, pero dificultan la lectura].
Python no utiliza tipos definidos estáticamente como C ++. Cuando define una función de método, no define formalmente el tipo de datos de los argumentos para esa función. Simplemente enumera algunos nombres de variables. Con suerte, la clase del cliente proporcionará argumentos del tipo correcto.
En tiempo de ejecución, cuando realiza una solicitud de método, Python debe asegurarse de que el objeto tenga el método. NOTA. Python no verifica si el objeto es del tipo correcto, eso no importa. Solo verifica si tiene el método correcto.
El bucle entre la habitación. room.Room
y person.Person
es un problema. No necesita incluir uno al definir el otro.
Es más seguro importar todo el módulo.
Aquí está room.py
import person
class Room( object ):
def __init__( self ):
self.nextId= 0
self.people= {}
def addPerson(self, firstName, secondName, gender):
id= self.NextId
self.nextId += 1
thePerson = person.Person(firstName,secondName,gender,id)
self.people[id] = thePerson
return thePerson
Funciona bien siempre que la Persona se defina finalmente en el espacio de nombres donde se está ejecutando. La persona no tiene que ser conocida cuando define la clase.
La persona no tiene que ser conocida hasta el tiempo de ejecución cuando se evalúa la expresión Persona (...).
Aquí está person.py
import room
class Person( object ):
def something( self, x, y ):
aRoom= room.Room( )
aRoom.addPerson( self.firstName, self.lastName, self.gender )
Tu main.py
parece a esto
import room
import person
r = room.Room( ... )
r.addPerson( "some", "name", "M" )
print r
No es necesario importar CRoom
No utiliza CRoom
en person.py
, así que no lo importe. Debido a la vinculación dinámica, Python no necesita "ver todas las definiciones de clase en tiempo de compilación".
Si realmente usa CRoom
en person.py
, cambie from room import CRoom
a la import room
y use la import room
de formulario calificada por room.CRoom
. Ver Effbot''s Circular Imports para más detalles.
Nota: probablemente tengas un error en Self.NextId += 1
línea. Incrementa NextId
de instancia, no NextId
de clase. Para incrementar el contador de la clase use CRoom.NextId += 1
o Self.__class__.NextId += 1
.