Pergunta

OK I tem dois módulos, cada um contendo uma classe, o problema é suas classes de referência entre si.

Vamos dizer, por exemplo, eu tinha um módulo de sala e um módulo de pessoa contendo Croom e CPerson.

A classe Croom contém infomation sobre o quarto, e uma lista CPerson de cada um na sala.

A classe CPerson no entanto às vezes precisa usar a classe Croom para o quarto sua em, por exemplo, para encontrar a porta, ou também ver quem está na sala.

O problema é com os dois módulos importar o outro eu apenas obter um erro de importação em que já está a ser importado segunda: (

Em c ++ eu poderia resolver este, incluindo apenas os cabeçalhos, e uma vez que em ambos os casos as aulas só tem ponteiros para a outra classe, uma declaração para a frente seria suficiente para o cabeçalho por exemplo:

class CPerson;//forward declare
class CRoom
{
    std::set<CPerson*> People;
    ...

Existe uma maneira de fazer isso em python, além de colocar ambas as classes no mesmo módulo ou algo parecido?

edit: adicionado exemplo python mostrando problema usando acima das classes

Erro:

Traceback (chamada mais recente passada):
File "C: \ Projects \ python \ test \ main.py", linha 1, em
a partir da sala de importação Croom
File "C: \ Projects \ python \ test \ room.py", linha 1, em
de pessoa importação CPerson
File "C: \ Projects \ python \ test \ person.py", linha 1, em
a partir da sala de importação Croom
ImportError: não pode nome de importação 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)
Foi útil?

Solução

Não há necessidade de importação Croom

Você não use CRoom em person.py, por isso não importá-lo. Devido à ligação dinâmica, Python não precisa "ver todas as definições de classe em tempo de compilação".

Se você realmente do uso CRoom em person.py, então a mudança from room import CRoom para import room e uso módulo qualificado forma room.CRoom. Veja Importações circulares de Effbot para mais detalhes.

Sidenote: você provavelmente tem um erro na linha Self.NextId += 1. Ele incrementa NextId de exemplo, não NextId de classe. Para CRoom.NextId += 1 contador de uso da classe incremento ou Self.__class__.NextId += 1.

Outras dicas

Você realmente precisa fazer referência as classes em tempo de definição de classe? ie.

 class CRoom(object):
     person = CPerson("a person")

Ou (mais provável), você só precisa usar CPerson nos métodos de sua classe (e vice-versa). por exemplo:

class CRoom(object):
    def getPerson(self): return CPerson("someone")

Se a segunda, não há nenhum problema - como pelo tempo que o método obtém chamado em vez de definido, o módulo será importado. Seu único problema é como se referem a ele. Provavelmente você está fazendo algo como:

from CRoom import CPerson # or even import *

Com os módulos de referenciação circularmente, você não pode fazer isso, como no ponto de um módulo de importações mais, o corpo módulos original não terá terminado a execução, de modo que o namespace será incompleta. Em vez disso, usar referências qualificadas. ou seja:

#croom.py
import cperson
class CRoom(object):
    def getPerson(self): return cperson.CPerson("someone")

Aqui, python não precisa procurar o atributo no namespace até que o método realmente é chamado, altura em que ambos os módulos deve ter concluído sua inicialização.

Em primeiro lugar, nomear seus argumentos com letras maiúsculas é confuso. Desde Python não tem formal, verificação de tipo estático, usamos o UpperCase significar uma classe e lowerCase significar um argumento.

Em segundo lugar, não se incomode com Croom e CPerson. maiúsculas é suficiente para indicar que é uma classe. A letra C não é utilizado. Room. Person.

Em terceiro lugar, não costumam colocar as coisas em uma classe por arquivo formato. Um arquivo é um módulo Python, e nós mais frequentemente importar um módulo inteiro com todas as classes e funções.

[Estou ciente esses são hábitos - você não precisa quebrá-las hoje, mas eles não torná-lo difícil de ler.]

Python não usa tipos estaticamente definidos como C ++. Quando você define uma função de método, você não definir formalmente o tipo de dados dos argumentos para essa função. Você simplesmente listar alguns nomes de variáveis. Felizmente, a classe do cliente irá fornecer argumentos do tipo correto.

Em tempo de execução, quando você faz um pedido método, então Python tem que ter certeza que o objeto tem o método. NOTA. Python não verificar para ver se o objeto é o tipo certo - isso não importa. Ele apenas verifica para ver se ele tem o método certo.

O laço entre room.Room e person.Person é um problema. Você não precisa incluir um quando definir o outro.

É mais seguro para importar todo o módulo.

Aqui 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 bem desde que Pessoa é finalmente definida no namespace onde este está em execução. Uma pessoa não tem que ser conhecido quando você definir a classe.

A pessoa não tem que ser conhecido até a execução quando o então Pessoa (...) expressão é avaliada.

Aqui está person.py

import room
class Person( object ):
    def something( self, x, y ):
        aRoom= room.Room( )
        aRoom.addPerson( self.firstName, self.lastName, self.gender )

Seus main.py olhares como este

import room
import person
r = room.Room( ... )
r.addPerson( "some", "name", "M" )
print r

Você poderia apenas o alias do segundo.

import CRoom

CPerson = CRoom.CPerson

@ S. Lott se eu fizer qualquer coisa que não a importação para o módulo de sala eu recebo um erro indefinido vez (I importou para o módulo principal como se mostrou)

Traceback (chamada mais recente passada):
File "C: \ Projects \ python \ test \ main.py", linha 6, em
Ben = Room.AddPerson ( 'Ben', 'Blacker', 'Male')
File "C: \ Projects \ python \ test \ room.py", linha 12, em AddPerson
Pessoa = CPerson (nome, SecondName, Gênero, Id)
NameError: nome global 'CPerson' não está definido

Além disso, a razão lá módulos diffrent é onde eu encontrei o problema começar com a classe recipiente (IEG quarto) é já várias centenas de linhas, então eu queria que os itens nele (por exemplo, as pessoas) em um arquivo separado.

EDIT: 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()
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top