2013-06-15 3 views
0

Я пытаюсь использовать цикл while для вызова функций из класса в другом файле, а затем изменить функцию, которая будет вызываться следующей, в зависимости от возвращаемой исходной функции. Вы можете признать некоторые из этого из «Learning Python Hard Way».Как правильно вызвать функции из другого класса с изменяющейся переменной?

У меня есть два файла: engine.py и rooms.py. Engine.py содержит цикл while, который вызывает функции из класса в комнатах.py, называемые «Номера».

Пример из rooms.py:

class Rooms(object):  
    def __init__(self): #add start as arg for one class game 
     from random import randint 
     from sys import exit 

    def princess_lives_here(self): 
     print "Cake" 

     eat_it = raw_input("1\n2\n3\?> ") 

     if eat_it == "1": 
      return 'death' 

     elif eat_it == "2": 
      return 'death' 

     elif eat_it == "3": 
      return 'gold_koi_pond' 

     else: 
      return 'death' 

Это простой макет реальной игры, чтобы убедиться, что я могу получить механизм для правильной работы. «death» и «gold_koi_pond» - это все функции, содержащиеся в классе «Комнаты».

У меня есть три образца двигателя, которые я хочу сравнить. Я буду называть их 1, 2 и 3 соответственно.

# 1 работы:

class Engine(object): 
    def __init__(self, start): 
     self.start = start 

    def play(self): 
     next = self.start 

     while True: 
      g = Rooms() 
      room = getattr(Rooms, next) 
      next = room(g) 


from rooms import Rooms 

a = Engine("princess_lives_here") 
a.play() 

# 2 работы:

class Engine(object): 
    def __init__(self, start): 
     self.start = start 

    def play(self): 
     next = self.start 

     while True: 
      next = getattr(Rooms, next)(Rooms()) 


from rooms import Rooms 

a = Engine("princess_lives_here") 
a.play() 

# 3 не работает:

class Engine(object): 
    def __init__(self, start): 
     self.start = start 

    def play(self): 
     next = self.start 

     while True: 
      room = getattr(Rooms, next) 
      next = room() 


from rooms import Rooms 

a = Engine("princess_lives_here") 
a.play() 

У меня трудно понять разницу между три варианта. Лучше другого? Что именно происходит в python, что делает работу 1 и 2, но не 3? Есть ли лучший способ выполнить то, что я хочу сделать?

Кроме того, randint и exit не импортируются, когда Room запущен с engine.py. Почему это?

Спасибо за помощь! Я открыт для всех советов и критики, а не только о вопросах, я интересуюсь.

ответ

0

1 и 3 являются самыми близкими, а разница в том, что в 1 вы создаете экземпляр из Rooms класса, в 3 вы этого не сделаете; Вы пытаетесь использовать несвязанные методы класса без прохождения в экземпляре:

while True: 
    g = Rooms() 
    room = getattr(Rooms, next) 
    next = room(g) 

против

while True: 
    room = getattr(Rooms, next) 
    next = room() 

Version 2 просто встраивают вызовы; g заменен на Rooms() и room заменен на getattr(Rooms, next).

Вы действительно должны быть вызовом связанных метод вместо:

g = Rooms() 
while True: 
    room = getattr(g, next) 
    next = room() 

Каков ваши две рабочих версии делают это вызов Rooms методы напрямую, без экземпляра; первый аргумент метода всегда равен self, но это может быть предоставлено автоматически только при наличии фактического экземпляра класса и доступа к методам через этот экземпляр. Под капотом функции на классе ведут себя как descriptor objects, а это значит, что при попытке получить к ним доступ в классе или экземпляре они возвращают объект метода, а не вызовут функцию на вашем пользователе. Ваши первые две версии должны предоставить экземпляр Rooms() вручную, а ваша 3-я версия будет опущена.

Вместо этого моя версия получает связанные методы, обратившись к методам только в одном экземпляре Rooms().

Вы можете увидеть разницу, когда вы играете с классами в интерактивной сессии:

>>> class Foo(object): 
...  def bar(self): print 'baz' 
... 
>>> Foo 
<class '__main__.Foo'> 
>>> Foo.bar 
<unbound method Foo.bar> 
>>> Foo() 
<__main__.Foo object at 0x10fa53d10> 
>>> Foo().bar 
<bound method Foo.bar of <__main__.Foo object at 0x10fa53dd0>> 
>>> Foo.__dict__['bar'] 
<function bar at 0x10fa46398> 
>>> Foo.__dict__['bar'].__get__(None, Foo) 
<unbound method Foo.bar> 
>>> Foo.__dict__['bar'].__get__(Foo(), Foo) 
<bound method Foo.bar of <__main__.Foo object at 0x10fa53dd0>> 
>>> Foo.bar(Foo()) 
baz 
>>> Foo().bar() 
baz