如何使用变化的变量从另一个类中适当地调用函数?

时间:2013-06-15 20:03:05

标签: python python-2.7

我正在尝试使用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。这是为什么?

感谢您的帮助!我愿意接受所有建议和批评,而不仅仅是我感兴趣的问题。

1 个答案:

答案 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