我正在尝试使用while循环从另一个文件中的类调用函数,然后根据原始函数返回的内容更改要调用的函数。您可能会从“以艰难的方式学习Python”中认识到这一点。
我有两个文件:engine.py和rooms.py。 Engine.py包含while循环,它调用来自rooms.py中名为'Rooms'的类的函数。
来自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?有没有更好的方法来完成我想做的事情?
此外,从engine.py运行Rooms时,不会导入randint和exit。这是为什么?
感谢您的帮助!我愿意接受所有建议和批评,而不仅仅是我感兴趣的问题。
答案 0 :(得分:0)
1和3最接近,不同之处在于你在1中创建了Rooms
类的实例,而在3中你没有;您试图使用类的未绑定方法而不传入实例:
while True:
g = Rooms()
room = getattr(Rooms, next)
next = room(g)
VS
while True:
room = getattr(Rooms, next)
next = room()
版本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