0

我正在尝试使用 while 循环从另一个文件中的类调用函数,然后根据原始函数返回的内容更改要调用的函数。您可能会从“Learning Python the Hard Way”中认识到其中的一些内容。

我有两个文件: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。为什么是这样?

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

4

1 回答 1

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()

版本 2 只是内联调用;g被 取代Rooms()room被 取代getattr(Rooms, next)

你真的应该调用绑定的方法:

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

您的两个工作版本正在做的是Rooms直接调用方法,没有实例;方法的第一个参数总是self,但只有当您拥有该类的实际实例并通过该实例访问方法时才能自动提供。在底层,类上的函数表现为描述符对象,这意味着在尝试在类或实例上访问它们时,它们会返回一个方法对象,而不是调用你的函数。您的前两个版本必须Rooms()手动提供一个实例,而您的第三个版本省略了该实例。

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
于 2013-06-15T20:08:11.683 回答