选择你自己的 Python 冒险 / 徘徊的格鲁
外观
函数案例研究:徘徊的格鲁
假设你想要在你神秘的房子里放一个徘徊的格鲁,它会随机出现在一个房间(或多个房间)里。
一种方法是创建一个函数,它决定格鲁是否在房间里。
测试框架
在我们的完整代码中,我们将看到类似的代码
eaten=grue()
if eaten:
print "Sadly, you were torn limb-from-limb by the Grue and suffered a slow, painful death."
else:
print "Congratulations, you have not been eaten by the Grue! May you have a long happy life."
这里我们介绍了一种新的 Python 数据类型:布尔值
。Python 布尔值可以取两个值 True
和 False
。这些代码片段是等效的
if x > 3: print "yep!" if x > 3 is True: print "yep!" if bool(x>3) is True: print "yep!"
“if” 语法隐含 如果谓词为 True。在 Python 中,大多数东西都评估为 True
,除了:None、False、0(0.0 等)、空字符串、零长度列表、字典,以及其他一些奇特的东西 [1].
变体 1:不太随机
def grue_always():
''' this grue always appears. returns true'''
return True
我们不太随机的格鲁总是出现。
练习:创建相反情况——一个永远不出现的格鲁。函数的签名应该是 grue_never() -> False
变体 2:50/50 格鲁
import random
## random is a Python module, as mentioned above.
## We need to import it to access the random() function.
## now to begin the function definition
## Everything inside the function definition is indented! Remember, white space matters!
def random_grue():
''' boolean. a grue that appears 50% of the time '''
## we want something that will return True 50% of the time.
## one method: get a random float between (0,1), and return True if it's over .5
## now we need a random number. random() will give us one between 0 and 1
n=random.random() ## the random before the dot tells Python what module to look in for the function, which is the one we imported above
if n > 0.5:
grue=1 ## 1 == True
else:
grue=0 ## 0 == False
return grue ## returning allows us to capture the value
那么 random_grue() 函数做了什么?让我们试试它。在 Python 解释器中
>>> import random >>> def random_grue(): n=random.random() if n>0/5: grue = 1 else: grue = 0 return grue >>> random_grue() 1
第一个命令是导入 random 模块,第二个是定义函数,第三个是实际调用函数。1 是函数的返回值。你可能会得到 1 或 0,具体取决于 random() 生成的数字。(提示:尝试运行多次)
变体 2:情绪化的格鲁
import random
def grue_moody(cutoff=.5):
''' boolean. a grue that appears (100*cutoff)% of the time '''
n=random.random()
above_cutoff = n < cutoff
return above_cutoff
def grue_moody2(cutoff=.5):
''' boolean. a grue that appears (100*cutoff)% of the time '''
return random.random() < cutoff
注意我们通过直接返回布尔值(尤其是在 'grue_moody2' 中)简化了函数,而不是做任何条件逻辑来获得 1 或 0。此外,我们还为参数 cutoff
指定了一个默认值。
练习
- 预测这些函数调用的行为。然后试试它们。
- grue_moody()
- grue_moody(-1)
- grue_moody(1)
- grue_moody("a")
- grue_moody([1,2,3])
- 修复代码,以便如果 n 超出区间 (0,1),则打印一条愤怒消息并返回
None
。 - 尝试
help(grue_moody)
。你看到了什么? random
、random.random
、random.random()
的类型是什么?
变体 3:位置,位置,位置格鲁
在我们最终的变体中,我们想要一个格鲁
- 根据页面的不同,出现百分比不同
- 在主房间“门厅”中应该没有出现的可能性
- 在没有其他描述的房间里,应该有一个默认的 5% 的出现几率
import random
grue_fractions = { 'foyer':0, 'thedark': 1.0, 'nocake': .2 }
def location_grue(room=None, base=.05, cutoffs=dict()):
''' (boolean), does a grue appear in the room?
room : str room name
base : 'cutoff', float between (0,1), for base (room not found)
cutoffs: dict of room_name: cutoff (float between 0,1)
'''
cutoff = cutoffs[room]
return random.random() < cutoff
练习
- 如写,
location_grue
有一些 bug,并且不符合规范。识别并修复它们。- 尝试:location_grue('foyer', cutoffs=grue_fractions)
- 如果 'room' 不在 'cutoffs' 中会发生什么?
- 研究字典的 'get' 方法...
help({}.get)
。使用此方法来修复代码。