【问题标题】:Class confusion in Python with the getattrPython 中的类混淆与 getattr
【发布时间】:2012-08-20 00:39:10
【问题描述】:

here 提出了类似的问题。然而,这些回答并没有真正帮助我理解程序的某些部分是如何工作的。程序如下:

from sys import exit
from random import randint

class Game(object):

    def __init__(self, start):
        self.pie = [ 'pie test']

        self.start = start

    def play(self):
        next_room_name = self.start
        while True:
            print "\n--------"
            room = getattr(self, next_room_name)
            next_room_name = room()

    def rooom(self):
        print "Test worked. good job"
        return "piez"

    def piez(self):
        print "pie room"
        exit(1)


a_game = Game("rooom")
a_game.play()

第一个问题是下面是如何工作的?

def play(self):
        next_room_name = self.start

        while True:
            print "\n--------"
            room = getattr(self, next_room_name)
            next_room_name = room()

我知道以某种方式生成房间名称,因此程序可以转到它需要的位置。我只是不知道它是如何发生的。

我的第二个问题是:

self.start = start

我有点理解 self.pie 在做什么。但我不确定 self.start = start 应该完成什么。再次感谢您的帮助。

【问题讨论】:

    标签: python class python-2.7 self getattr


    【解决方案1】:

    假设你有这样的类:

    class DummyClass(object):
    
        awesome = True
    
        def not_awesome(self):
            self.awesome=False
    

    在此使用 getattr 完全等同于使用点语法,例如

    dumb = DummyClass()
    print getattr(dummy, "awesome") # True
    print dummy.awesome # True
    

    您也可以将其与方法一起使用:

    dumb = DummyClass()
    no_more_awesome = getattr(dummy, "not_awesome") # returns the not_awesome method of dummy
    print dummy.awesome # True
    no_more_awesome()
    print dummy.awesome # False
    

    因此,在您发布的代码 sn-p 中,getattr(self, next_room_name) 获取名称为 next_room_name 的方法并返回要调用的函数(绑定到 self)。您在这里使用变量而不是点语法,因为您事先不知道名称。考虑以下两个 sn-ps 来得到这个(与重叠有点混淆......对不起):

    dummy = DummyClass()
    awesome = "not_awesome"
    print dummy.awesome # True
    print getattr(dummy, awesome) # string with something like <bound method ... >
    

    【讨论】:

      【解决方案2】:

      首先:对象初始化。调用Game("rooom")时,字符串"rooom"绑定到__init__的参数start。语句this.start = start 只是将字符串"rooom" 存储在内部对象字典中,可通过this.start 访问。

      然后调用play() 方法:getattr 在此上下文中的使用定义了一个名为Pluggable Selector 的模式。换句话说,不是显式说明要调用哪个方法,而是存储方法的名称是一个变量(在这种情况下为next_room_name)。

      第一个被调用的方法是rooom,因为局部变量next_room_name(在方法play的范围内是局部的)在while循环之前被初始化为self.start

      方法调用的返回值用于更新next_room_name变量,因此rooom执行后,值变为"piez"。因此,下一个要调用的方法将是piez

      最后,当piez 执行时,调用exit(1),因此解释器终止,不再执行代码。在这种情况下,没有更多代码执行的原因是sys.exit 引发了一个SystemExit 异常(请参阅documentation),该异常在任何地方都没有被捕获。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-05-29
        • 2022-01-17
        • 2014-07-09
        • 1970-01-01
        相关资源
        最近更新 更多