Python:类“init”内的 If-else;这有用吗?
我是另一个正在经历“艰难学习Python”的编程新手,并且遇到了一些我不完全理解的事情。
我首先要说的是,虽然我真的很喜欢他的课程计划,但一个不幸的副作用似乎是我不明白编程世界中涉及的很多技术演讲。我花了两天时间才弄清楚什么是“实例化”,到现在我也只是觉得我明白了,呵呵。因此,希望我的查询的答案尚未以更具技术描述性的方式提出,如果有的话,我很抱歉是多余的。
不管怎样,我在这里想做的是完成一次文本冒险,使用类来描述每个房间。我实际上正在做的是将我的旧工作导入到这种更新的、更“OOP”的做事方式中——转换一个本质上有 980 行函数调用的程序。
因此,之前我在每个功能中都有这些“房间”,它们会检查您是否达到了某些游戏目标,以便向您描述房间。示例:
def room_one():
if "flashlight" in pack:
print "You see an exit to the NORTH and a bear to the EAST."
elif "flashlight" not in pack:
print "It's too dark to see."
无聊的房间,但描述恰当。因此,在尝试使用类来做到这一点时,我似乎碰壁了。我将向您展示我用来定义游戏“跑步者”和房间类的代码。
class Runner(object):
def __init___(self):
self.goals = [] #an array for game achievements (talked_to_king, etc)
self.pack = [] #an array for game items (flask, key, etc)
def play(self, currentroom, gamestate):
while True:
print "\n--------"
print currentroom.desc #this line prints the room description, could
cmd = raw_input("> ") #it also be part of the problem?
gamestate.state = currentroom.actions(cmd)
if gamestate.state != "SAME":
currentroom = gamestate.state
else:
pass
class Room(object):
def __init__(self):
self.desc = "null" #short room description
self.lookdesc = "super null" #longer room description for the LOOK command
def actions(self, cmd):
if 'help' in cmd:
print """
'look' -- see your surroundings, including exits.
'get' -- to pick up an item (if it can be picked up).
'inventory' -- displays your collected items
'throw' -- some objects can be thrown
'talk' -- speak to someone
Other commands, or objects to interact with, will tend to
show up IN UPPERCASE. (but still type them in lowercase!)
Cardinal directions (north, south, east, west) for movement.
"""
return "SAME"
elif 'inv' in cmd:
print "--Inventory--\n"
for items in game.pack:
print items
print "-------------\n"
return "SAME"
elif 'look' in cmd:
print self.lookdesc
return "SAME"
elif 'goals' in cmd:
for goal in game.goals:
print goal
return "SAME"
else:
print "That won't work here."
return "SAME"
class Office(Room):
def __init__(self):
super(Office, self).__init__()
# here's the part that doesn't work
if 'principal' in game.goals:
self.desc = "You're in the principal's office, and there's a zombie in here!"
else:
self.desc = "You're in the principal's office."
self.lookdesc = "The walls in here are dingy from decades of smoking.\nA door to the WEST leads back to the foyer."
def actions(self, cmd):
if "west" in cmd and not "principal" in game.goals:
print "Buck up and talk to the old prune."
return "SAME"
elif "talk" in cmd:
print "You call to the principal."
game.goals.append('principal')
next = raw_input("--Mr. Friiiiinkseseeees...--")
print "But OH MY DAMN he's actually a zombie now."
next = raw_input("--Aww weak--")
return "SAME"
return super(Office, self).actions(cmd)
为了检查以确保附加了“goals”数组,我在 Room 父类中放置了一个简单的目标检查函数,并且果然 game.goals 被附加了。但我的 if-else 语句似乎实际上没有做任何事情;无论目标数组中有什么,当我回到房间时,我总是会得到其他的描述。
公平地说,像那样将 if-else 放在 room init 中有点像在黑暗中射击,事实上,我很惊讶我没有收到一条错误消息告诉我那不是那些东西所在的地方!但事实上,它似乎并不关心 game.goals 数组的内容,这告诉我这不是最好的方法。我应该如何实施这个?
作为一个子问题 - 对于这样的程序,如果游戏状态变化足够大,以至于房间的内容发生了巨大的改变,那么为改变的房间设置一个完整的其他类是否会被认为更好?维护“地图”并说 RoomThree(Room) 始终是 RoomThree 是否更重要,无论游戏状态发生什么变化,或者当游戏返回到 RoomThree 时,该地方已被毁坏、被抢劫、着火,充满了吸血鬼和生菜的味道,这应该是一个完全不同的 RoomThree 吗?我有点希望不是,因为让每个房间“成为那个房间”并让 game.goals 和 game.pack 之类的内容改变类的实例似乎更合理只在满足某些条件时创建一个新类。
无论如何,这很冗长。 tl;dr - 我这样做很奇怪吗?
再次编辑:清理了主要问题的代码以满足此处人们建议的新代码,还添加了父类“Room”以查看这是否不是问题的一部分。仍然没有解决方案,但我确实相信代码的质量已经提高了:)
最终编辑(我希望):啊哈,斯通的回答再次是最有帮助的。由于我向跑步者返回“相同”,因此它使用的是旧的 Office 实例。我需要创建一个全新的实例以使其识别更改;通过返回“Office()”而不是“SAME”我完成了这一点。感谢大家的帮助,不仅解决了手头的问题,而且使代码更易于阅读,并帮助我改变了我对冗长的 if-else 语句的想法。哇:D
I'm yet another programming newb going through "Learn Python the Hard Way" and have come up against something that I don't fully understand.
I'll preface this by saying that while I'm really enjoying his lesson plan, one unfortunate side-effect seems to be that I don't understand a lot of the technical talk involved in the programming world. It took me two days to figure out what 'instantiating' is, and even now I only think I get it, heh. So hopefully the answer to my query hasn't already been asked in a more technically descriptive way, if it has I sorry for being redundant.
Anyway, what I'm trying to do here is complete a text adventure, using classes to describe each room. What I'm actually doing is importing an old work of mine to this newer, more "OOP"ish way of doing things - converting a program which was essentially 980 lines of function calls.
So previously I had these 'rooms' inside each function that would check to see if you'd met certain game goals to describe the room to you. Example:
def room_one():
if "flashlight" in pack:
print "You see an exit to the NORTH and a bear to the EAST."
elif "flashlight" not in pack:
print "It's too dark to see."
Boring room, but apt description. So in trying to do this using classes, I seem to have hit a wall. I'll show you the code I'm using to define the game 'runner' and the room classes.
class Runner(object):
def __init___(self):
self.goals = [] #an array for game achievements (talked_to_king, etc)
self.pack = [] #an array for game items (flask, key, etc)
def play(self, currentroom, gamestate):
while True:
print "\n--------"
print currentroom.desc #this line prints the room description, could
cmd = raw_input("> ") #it also be part of the problem?
gamestate.state = currentroom.actions(cmd)
if gamestate.state != "SAME":
currentroom = gamestate.state
else:
pass
class Room(object):
def __init__(self):
self.desc = "null" #short room description
self.lookdesc = "super null" #longer room description for the LOOK command
def actions(self, cmd):
if 'help' in cmd:
print """
'look' -- see your surroundings, including exits.
'get' -- to pick up an item (if it can be picked up).
'inventory' -- displays your collected items
'throw' -- some objects can be thrown
'talk' -- speak to someone
Other commands, or objects to interact with, will tend to
show up IN UPPERCASE. (but still type them in lowercase!)
Cardinal directions (north, south, east, west) for movement.
"""
return "SAME"
elif 'inv' in cmd:
print "--Inventory--\n"
for items in game.pack:
print items
print "-------------\n"
return "SAME"
elif 'look' in cmd:
print self.lookdesc
return "SAME"
elif 'goals' in cmd:
for goal in game.goals:
print goal
return "SAME"
else:
print "That won't work here."
return "SAME"
class Office(Room):
def __init__(self):
super(Office, self).__init__()
# here's the part that doesn't work
if 'principal' in game.goals:
self.desc = "You're in the principal's office, and there's a zombie in here!"
else:
self.desc = "You're in the principal's office."
self.lookdesc = "The walls in here are dingy from decades of smoking.\nA door to the WEST leads back to the foyer."
def actions(self, cmd):
if "west" in cmd and not "principal" in game.goals:
print "Buck up and talk to the old prune."
return "SAME"
elif "talk" in cmd:
print "You call to the principal."
game.goals.append('principal')
next = raw_input("--Mr. Friiiiinkseseeees...--")
print "But OH MY DAMN he's actually a zombie now."
next = raw_input("--Aww weak--")
return "SAME"
return super(Office, self).actions(cmd)
To check to make sure the "goals" array was being appended I did put a simple goal checking function in the Room parent class, and sure enough the game.goals gets appended. But my if-else statement doesn't seem to actually do anything; no matter what's in the goals array, I always get the else' desc when I come back to the room.
In fairness putting the if-else in the room init like that was sort of a shot in the dark, in fact I was surprised that I didn't get an error message back telling me that's not where those go! But the fact that it doesn't seem to care about the contents of game.goals array tells me that this isn't the best way to do this. How should I be implementing this?
As a subquestion - with a program like this, if the gamestate changes enough that a room's contents are dramatically altered, is it considered better to just have a whole other class for the altered room? Is it more important to maintain the "map" and to say that RoomThree(Room) is always RoomThree no matter what gamestate changes have occurred, or if by the time the game comes back to RoomThree the place is trashed, looted, on fire, full of vampires and smells of lettuce, should that just be a different RoomThree altogether? I kind of hope not, because it just seems more reasonable to have each room just 'be that room' and let the contents of things like game.goals and game.pack change the instance of the class instead of just making a new class for when certain conditions are met.
Anyway, this was longwinded. tl;dr - Am I doing it weird??
EDIT AGAIN: Cleaned up the main question's code to meet the new code as suggested by people here, also added the parent class "Room" to see if that isn't part of the problem. Still no solution, but I do believe the quality of the code has improved :) whee
FINAL EDIT(i hope): Aha, Stone's answer was again most helpful. Since I was returning "same" to my runner, it was using the old instance of Office. I needed to create a whole new instance to get it to recognize the change; by returning "Office()" instead of "SAME" I accomplished this. Thanks everyone for helping to not only solve the issue at hand but to make the code easier to read, and to help me change my thinking regarding my wordy if-else statements. Mwah :D
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
当你有 100 个房间时会发生什么?你的 play 函数有 100 个 if 语句,只是为了设置你所在的房间吗? (基本上再次设置)
当游戏状态发生变化时,直接将其设置为您想要的任何状态可能会更好。
编辑:我刚刚重新阅读了您的内容,现在问题似乎很明显,除非您遗漏了重要的代码。
您唯一一次向目标添加主体是在 Office 类的成员函数内部。因此,当您开始向目标添加主体时,为时已晚,Office 已经初始化,并且不会重新初始化,除非您创建一个新的 Office 实例。添加该目标后,您需要更新房间的描述。
What happens when you have 100 rooms? Will your play function have 100 if statements, just to set the room you are in? (set it again, basically)
It would probably be much better to just set the game state directly to whatever you want when it changes.
edit: I just re-read what you have an now the problem seems kind of obvious, unless you've left out vital code.
The only time that you appear to add principal to to goals is inside of a member function of class Office. Therefore, by the time that you get around to adding principal to goals, it's too late, Office has already been initialized and won't be re-initialized unless you create a new instance of Office. You'll need to update the room's description after you add that goal.
我想这样说:
你的意思是这个:
或者这个:
not 'somestring'
是False
,因为非空字符串总是True
并且你您的目标中没有False
,因此它的计算结果始终为False
。Office 对象是在哪里创建的?因为您只检查对象创建的条件,然后主体会添加到目标中,所以如果您再次使用相同的对象,描述不会改变。
I suppose by this:
you meant this:
or this:
not 'somestring'
isFalse
, because non-empty string is alwaysTrue
and you don't haveFalse
in your goals, so it always evaluates toFalse
.Where Office objects is created? Because you are only checking the condition on object creating and principal is added to the goal after that, so if you use same object again, description wouldn't change.