简体   繁体   English

使用getattr在Python中混淆类

[英]Class confusion in Python with the getattr

A similar question was asked here . 这里也提出类似的问题。 However, the responses didn't really help me grasp how some parts of the program worked. 但是,这些回答并没有真正帮助我了解程序的某些部分是如何工作的。 The program is as follows: 该程序如下:

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

The first question is how is the following working? 第一个问题是以下工作如何进行?

def play(self):
        next_room_name = self.start

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

I know that somehow the following is generating the room name so the program can go to where it needs to. 我知道以下内容会以某种方式生成房间名称,以便程序可以转到所需的位置。 I'm just not seeing how it is happening. 我只是不知道它是如何发生的。

My second question is: 我的第二个问题是:

self.start = start

I sort of understand self.pie is doing. 我有点了解self.pie在做什么。 But I'm not sure what self.start = start is suppose to accomplish. 但是我不确定self.start = start应该完成什么。 Thanks again for your assistance. 再次感谢你的帮助。

Let's say that you have some class like this: 假设您有这样的课程:

class DummyClass(object):

    awesome = True

    def not_awesome(self):
        self.awesome=False

Using getattr on this is exactly equivalent to using the dot syntax, eg 在此使用getattr完全等同于使用点语法,例如

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

You can use this with methods too: 您也可以将其与方法一起使用:

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

So, in the code snippet you posted, the getattr(self, next_room_name) gets the method with name next_room_name and returns the function (bound to self) to be called. 因此,在您发布的代码段中, getattr(self, next_room_name)获得名称为next_room_name的方法,并返回要调用的函数(绑定到self)。 You use a variable instead of dot syntax here because you don't know the name in advance. 您在此处使用变量而不是点语法,因为您事先不知道名称。 Consider the following two snippets to get this (a bit confusing with overlaps...sorry): 考虑以下两个片段以获取此信息(重叠部分有点令人困惑……对不起):

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

First of all: object initialization. 首先:对象初始化。 When Game("rooom") is called, the string "rooom" is bound to the parameter start of __init__ . 调用Game("rooom") ,字符串"rooom"绑定到__init__的参数start The statement this.start = start simply stores the string "rooom" in the internal object dictionary, accessible through this.start . 语句this.start = start只是将字符串"rooom"存储在内部对象字典中,可通过this.start访问。

Then play() method is called: the usage of getattr in this context defines a pattern called Pluggable Selector . 然后调用play()方法:在此上下文中对getattr的使用定义了一种模式,该模式称为Pluggable Selector In other words, rather than explicitly stating which method to call, the name of the method is stored is a variable ( next_room_name in this case). 换句话说,不是显式说明要调用的方法,而是将方法的名称存储为变量(在这种情况下为next_room_name )。

The first method to be called is rooom because the local variable next_room_name (local to the scope of the method play ) is initialized to self.start before the while loop. 要调用的第一个方法是rooom因为局部变量next_room_name (本地到的方法的范围play )被初始化为self.start while循环之前。

The return value of the method call is used to update the next_room_name variable, therefore after rooom executes, the value becomes "piez" . 该方法调用的返回值被用于更新next_room_name变量,因此后rooom执行时,该值变为"piez" Hence, the next method to be called is going to be piez . 因此,下一个要调用的方法将是piez

Finally, when piez executes, a call to exit(1) is made, therefore the interpreter is terminated, with no further execution of code. 最后,当piez执行时, piez exit(1)进行调用,因此终止解释器,而无需进一步执行代码。 The reason why no more code executes, in this case, is that sys.exit raises a SystemExit exception (see documentation ), which is not caught anywhere. 在这种情况下,不再执行任何代码的原因是sys.exit引发了SystemExit异常(请参阅文档 ),该异常在任何地方都未捕获。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM