跳到内容

选择你自己的 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 布尔值可以取两个值 TrueFalse。这些代码片段是等效的

   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 指定了一个默认值

练习

  1. 预测这些函数调用的行为。然后试试它们。
    • grue_moody()
    • grue_moody(-1)
    • grue_moody(1)
    • grue_moody("a")
    • grue_moody([1,2,3])
  2. 修复代码,以便如果 n 超出区间 (0,1),则打印一条愤怒消息并返回 None
  3. 尝试 help(grue_moody)。你看到了什么?
  4. randomrandom.randomrandom.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


练习

  1. 如写,location_grue 有一些 bug,并且不符合规范。识别并修复它们。
    1. 尝试:location_grue('foyer', cutoffs=grue_fractions)
    2. 如果 'room' 不在 'cutoffs' 中会发生什么?
    3. 研究字典的 'get' 方法... help({}.get)。使用此方法来修复代码。

参考文献

[编辑 | 编辑源代码]
华夏公益教科书