파이썬 모듈 종속성
-
03-07-2019 - |
문제
좋아, 각각 클래스가 포함 된 두 개의 모듈이 있습니다. 문제는 수업이 서로를 참조하는 것입니다.
예를 들어 룸 모듈과 Croom 및 Cperson이 포함 된 사람 모듈이 있다고 가정 해 봅시다.
Croom 클래스에는 방에 대한 정보와 방에있는 모든 사람의 CPERSON 목록이 포함되어 있습니다.
그러나 CPERSON 클래스는 때때로 문을 찾거나 다른 방에있는 사람을 확인하기 위해 방에 객실의 크룸 클래스를 사용해야합니다.
문제는 서로를 가져 오는 두 모듈이 두 번째로 가져 오는 수입 오류를 얻는 것입니다.
C ++에서는 헤더를 포함하여 이것을 해결할 수 있으며, 두 경우 모두 수업은 다른 클래스에 대한 포인터를 가지고 있기 때문에 앞으로 선언은 헤더에게 충분합니다.
class CPerson;//forward declare
class CRoom
{
std::set<CPerson*> People;
...
어쨌든 두 클래스를 동일한 모듈에 배치하는 것 외에는 파이썬 에서이 작업을 수행해야합니까?
편집 : 위의 클래스를 사용하여 문제를 보여주는 Python 예제 추가
오류:
Traceback (가장 최근의 호출) :
"c : projects python test main.py", 1 행,
객실 수입 크룸에서
"c : projects python test room.py", 1 행,
사람에게서 cperson을 수입합니다
"c : projects python test person.py", 1 행,
객실 수입 크룸에서
Importerror : 이름 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)
해결책
Croom을 가져올 필요가 없습니다
당신은 사용하지 않습니다 CRoom
안에 person.py
, 그것을 가져 오지 마십시오. 동적 바인딩으로 인해 Python은 "컴파일 시간에 모든 클래스 정의를 볼 필요가 없습니다".
당신이 실제로 하다 사용 CRoom
안에 person.py
, 그런 다음 변경됩니다 from room import CRoom
에게 import room
모듈 자격 양식을 사용하십시오 room.CRoom
. 보다 Effbot의 원형 수입 자세한 내용은.
사이드 노트 : 당신은 아마도 오류가있을 것입니다 Self.NextId += 1
선. 그것은 증가합니다 NextId
예를 들어 NextId
수업의. 클래스의 카운터 사용을 증분합니다 CRoom.NextId += 1
또는 Self.__class__.NextId += 1
.
다른 팁
실제로 클래스 정의 시간에 클래스를 참조해야합니까? 즉.
class CRoom(object):
person = CPerson("a person")
또는 가능성이 높습니다. 수업 방법에서 CPERSON을 사용하면됩니다 (그 반대). 예 :
class CRoom(object):
def getPerson(self): return CPerson("someone")
두 번째는 문제가 없다면 - 메소드가 얻을 때와 마찬가지로 ~라고 불리는 정의되지 않고 모듈이 가져옵니다. 당신의 유일한 문제는 그것을 참조하는 방법입니다. 아마도 당신은 다음과 같은 일을하고있을 것입니다.
from CRoom import CPerson # or even import *
원형 참조 모듈을 사용하면 하나의 모듈이 다른 모듈을 가져 오는 것처럼 원래 모듈 본체가 실행되지 않았으므로 네임 스페이스가 불완전하게됩니다. 대신 자격을 갖춘 참조를 사용하십시오. 즉:
#croom.py
import cperson
class CRoom(object):
def getPerson(self): return cperson.CPerson("someone")
여기서, 파이썬은 메소드가 실제로 호출 될 때까지 네임 스페이스의 속성을 조회 할 필요가 없으며,이 시간까지 두 모듈 모두 초기화를 완료해야합니다.
첫째, 대문자로 당신의 주장을 지명하는 것은 혼란 스럽습니다. 파이썬은 공식적인 정적 유형 확인이 없으므로 우리는 다음을 사용합니다. UpperCase
수업을 의미합니다 lowerCase
인수를 의미합니다.
둘째, 우리는 Croom과 Cperson을 귀찮게하지 않습니다. 어퍼 케이스는 그것이 클래스임을 나타 내기에 충분합니다. 문자 C는 사용되지 않습니다. Room
. Person
.
셋째, 우리는 일반적으로 물건을 넣지 않습니다 파일 당 하나의 클래스 체재. 파일은 파이썬 모듈이며 모든 클래스와 기능으로 전체 모듈을 더 자주 가져옵니다.
나는 이것이 습관이라는 것을 알고 있습니다. 오늘은 습관을 깰 필요는 없지만 읽기가 어렵습니다.
Python은 C ++와 같은 정적으로 정의 된 유형을 사용하지 않습니다. 메소드 함수를 정의 할 때 해당 기능에 대한 인수의 데이터 유형을 공식적으로 정의하지 않습니다. 당신은 단지 변수 이름을 나열합니다. 바라건대, 클라이언트 클래스는 올바른 유형의 인수를 제공하기를 바랍니다.
실행 시간에 메소드 요청을 할 때 Python은 객체에 메소드가 있는지 확인해야합니다. 노트. 파이썬은 객체가 올바른 유형인지 확인하지 않습니다. 올바른 방법이 있는지 확인합니다.
사이의 루프 room.Room
그리고 person.Person
문제입니다. 다른 것을 정의 할 때 하나를 포함 할 필요가 없습니다.
전체 모듈을 가져 오는 것이 가장 안전합니다.
여기에 있습니다 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
사람이 결국 실행중인 네임 스페이스에서 정의되는 한 잘 작동합니다. 수업을 정의 할 때 사람을 알 필요가 없습니다.
사람 (...) 표현이 평가 될 때 런타임까지 사람을 알 필요는 없습니다.
여기에 있습니다 person.py
import room
class Person( object ):
def something( self, x, y ):
aRoom= room.Room( )
aRoom.addPerson( self.firstName, self.lastName, self.gender )
당신의 main.py
이렇게 보인다
import room
import person
r = room.Room( ... )
r.addPerson( "some", "name", "M" )
print r
두 번째는 별칭을 할 수 있습니다.
import CRoom
CPerson = CRoom.CPerson
@s.lott 룸 모듈로 아무것도 가져 오지 않으면 정의되지 않은 오류가 나타납니다 (내가 보여준 것처럼 기본 모듈로 가져 왔습니다)
Traceback (가장 최근의 호출) :
"c : projects python test main.py", 6 행,
Ben = room.addperson ( 'Ben', 'Blacker', 'Male')
"C : Projects Python Test Room.py", 12 행, AddPerson에서 파일
person = cperson (FirstName, SecondName, Gender, ID)
nameerror : 글로벌 이름 'cperson'은 정의되지 않았습니다.
또한, 다른 모듈이있는 이유는 컨테이너 클래스 (IEG 객실)부터 시작하는 문제가 이미 수백 줄이므로 분리 된 파일의 항목 (예 : 사람들)을 원했습니다.
편집 : 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()