2011-01-27 5 views
4

다음 코드가 있습니다.파이썬 : 다른 클래스의 메소드를 호출하는 가장 좋은 방법은?

class Player: 
    def __init__(self, username, trip, model): 
     self.username = username 
     self.trip = trip 
     self.hp = 100 


    #### For player moving location/room #### 
    def Move(self, dest): 
     if dest == self.loc: 
      return True 

     # Check destination room is accessible from current room 
     for room in aGame['rooms']: 
      if room['ref'] == self.loc: 
       for acsroom in room['acs']: 
        if acsroom == dest: 
         self.loc = dest 
         return True 
     return False 

aGame은이 클래스 외부에서 정의 된 배열이므로이 코드는 작동하지 않습니다. 이 클래스 내에서 aGame 배열을 사용할 수있는 다른 많은 함수가 있기 때문에 다음과 같이해야합니다.

class Player: 
    def __init__(self, username, trip, model, aGame): 
     self.username = username 
     self.trip = trip 
     self.hp = 100 
     self.aGame = aGame    

    #### For player moving location/room #### 
    def Move(self, dest): 
     if dest == self.loc: 
      return True 

     # Check destination room is accessible from current room 
     for room in self.aGame['rooms']: 
      if room['ref'] == self.loc: 
       for acsroom in room['acs']: 
        if acsroom == dest: 
         self.loc = dest 
         return True 
     return False 

아니면 이렇게하는 것이 좋습니다 :

class Player: 
    def __init__(self, username, trip, model): 
     self.username = username 
     self.trip = trip 
     self.hp = 100   

    #### For player moving location/room #### 
    def Move(self, dest, aGame): 
     if dest == self.loc: 
      return True 

     # Check destination room is accessible from current room 
     for room in aGame['rooms']: 
      if room['ref'] == self.loc: 
       for acsroom in room['acs']: 
        if acsroom == dest: 
         self.loc = dest 
         return True 
     return False 

또는 aGame을 전역 변수로 만들어야합니까? 그렇다면이 클래스는 다른 파일에 있습니다.

aGame은 그 곳 곳곳에서 사용되는 배열이기 때문에 모든 클래스 안에 그 복사본을 만들어야하는 것은 정확하지 않습니다. 내가 잘못했을 수도 있습니다. 나는 천천히 OOP를 배우므로 어떤 도움을 주셔서 감사합니다.

+3

'aGame' 사전을 각 클래스에 실제로 복사하지 않습니다 - 인수는 "참조로"전달됩니다. – miku

답변

3

내 의견으로는, 첫 번째 옵션은 좋은 이유없이 전역을 사용하기 때문에 적절합니다. 그래서 선택은 두 번째와 세 번째 사이에 있습니다.

하나 이상의 aGame 값에 동일한 Player 인스턴스를 사용하려는 경우 결정적인 기능입니다. 하나의 값만 있으면, 생성자 (옵션 2)에 전달하거나 gnibbler의 생각을 사용하여 클래스 변수로 만듭니다. 아마도 테스트를 쉽게하기 위해 생성자에 전달하는 것이 좋을 것입니다.

동일한 Player 인스턴스를 복수 aGame 값으로 사용할 수있게하려면 옵션 3이이를 달성하는 가장 쉬운 방법 일 수 있습니다.

+0

감사합니다 :) 플레이어의 인스턴스는 여러 개 있지만 게임의 버전은 하나입니다. aGame은 파일에서로드 된 값을 가진 dict이므로 항상 파일에서 해당 값을 다시로드하지 않으면 비효율적입니다. 나는 자기와 함께 클래스에 aGame을 설정하는 옵션 2를 사용해야 할 것 같아요. 그리고 내가 나중에 응용 프로그램에서 어떤 이유로 든 aGame dict를 업데이트하지 않아도되기를 바란다. – Tommo

+0

@ Tommo, 모든 인스턴스에 동일한 인스턴스를 전달하면 모든 인스턴스에서 변경 사항을 볼 수 있습니다. 파이썬은 단지 새로운 참조를 생성하는 사전을 복사하지 않습니다. 또한 파일을 읽는 중이면 클래스 메소드로 Walter Mundt의 아이디어를 사용하여 배열을 채울 수 있습니다. – aaronasterling

0

첫 번째 선택 사항 만 작동합니다. 두 번째 예에서, for room in self.aGame['rooms']은 아무데도 자신에게 연결된 aGame이 없기 때문에 오류가 발생합니다. for room in aGame['rooms']이면 작동하지만 move()을 호출 할 때마다 불필요하게 aGame을 전달해야합니다.

전역 변수로 만들 수도 있지만 각 플레이어가 aGame 인스턴스를 보유하는 것이 가장 좋습니다. 게임을 변경하고 여러 플레이어가 필요한 경우 전역 변수로 정의해야합니다.

또한 nitpicking하지만 aGame은 배열이 아니며 사전입니다. 파이썬 언어는 배열을 가지고 있지 않습니다 (일부 확장 기능이 있지만).

+0

죄송합니다. '자기'를 삭제하는 것을 잊어 버렸습니다. 왜냐하면 두 번째 예제에서 aGame 변수가 메소드에 전달 되었기 때문입니다. – Tommo

+0

Player 클래스에 aGame을 추가 한 경우 현재 aGame의 복사본을 만들어 Player 인스턴스에 적용하는 것이 아닙니까? 따라서 클래스가 초기화 된 후에 aGame이 변경되면 player1.aGame이 달라질 수 있습니까? – Tommo

+0

@ 토모, 그럼, 내 대답은 여전히 ​​유효하다. 각 Player가 인스턴스를 소유 할 수있을 때마다 move()를 호출 할 때마다 왜'aGame'을 전달합니까? 첫 번째 솔루션은 더 이해하기 쉬우 며 필요한 부분을 덜 필요로합니다. 게임을 변경하고 여러 플레이어가 필요한 경우 전역 변수로 정의해야합니다. –

0

aGame은 모든 인스턴스에 대해 동일합니까? 그런 다음 당신이 클래스 내에서이

class Player: 
    aGame={'rooms':...} 
    ... 

또는

Class Player: 
    ... 

Player.aGame={'rooms':...} 

같은 클래스 속성 중 하나를 만들 수 있습니다, 당신은 아직도 내가 약간의 변화를에 사용하십시오 self.aGame

0

를 통해 액세스 할 수 있습니다 글로벌 :

# in game.py or whatever 
class Game(object): 
    instance = {} # this is your aGame array 

# in player.py or whatever: 
from game import Game 

class Player(object): 
    # ... 
    def Move(self, dest): 
     # ... 
     for room in Game.instance['rooms']: 
      # ... 

또는 게임을 적절하게 만들 수 있습니다 클래스에서 Game.instance = Game (...)을 초기화 단계에서 어딘가에 할당하고 더 많은 실제 싱글 톤 패턴을 얻습니다.

+0

이 회선의 이점은 무엇입니까? – aaronasterling

+0

글쎄, 전 세계가 별도의 모듈에 있어야한다고 생각합니다. 이 경우 가져 오기 시간에 전역 값이있는 종속성을 제거합니다. 컨테이너 클래스가 없으면 플레이어 모듈은 게임 가져 오기에서 게임을해야합니다. 만약 초기화 모듈이 플레이어 모듈을 로딩 한 후'aGame' 글로벌에 할당한다면, 플레이어 모듈의 aGame 값은 더 이상 올바르지 않습니다. 이 버전에서는 문제가되지 않습니다. 두 번째로, 게임 전반에 걸친 게임 클래스를 더 분명하게하는 것으로 전환하는 것이 더 쉬운 일이라고 생각합니다. –

관련 문제