在歌曲“九十九瓶”的这个版本中,该程序通过删除一个字母、交换一个字母的大小写、调换两个字母或重叠一个字母,在每个小节中引入了一些小的不完美。
随着歌曲继续播放,这些突变累积起来,产生了一首非常傻的歌曲。在尝试这个项目之前,尝试项目 50“九十九瓶”是个好主意。
当您运行999bottles2.py时,输出将如下所示:
niNety-nniinE BoOttels, by Al Sweigart email@protected
`--snip--`
99 bottles of milk on the wall,
99 bottles of milk,
Take one down, pass it around,
98 bottles of milk on the wall!
98 bottles of milk on the wall,
98 bottles of milk,
Take one d wn, pass it around,
97 bottles of milk on the wall!
97 bottles of milk on the wall,
97 bottels of milk,
Take one d wn, pass it around,
96 bottles of milk on the wall!
`--snip--`
75b otlte of mIl on teh wall,
75 ottels f miLk,
Take one d wn, pass it ar und,
74 bbOttles of milk on t e wall!
`--snip--`
1 otlE t of iml oo nteh lall,
1 o Tle FF FmMLIIkk,
Taake on d wn, pAasSs itt au nn d,
No more bottles of milk on the wall!Python 中的字符串值是不可变的,意味着它们不能被改变。如果字符串'Hello'存储在名为greeting的变量中,代码greeting = greeting + ' world!'实际上不会改变'Hello'字符串。相反,它创建了一个新的字符串'Hello world!',来替换greeting中的'Hello'字符串。这方面的技术原因超出了本书的范围,但是理解其中的区别是很重要的,因为这意味着像greeting[0] = 'h'这样的代码是不允许的,因为字符串是不可变的。然而,由于列表是可变的,我们可以创建一个单字符字符串列表(如第 62 行),改变列表中的字符,然后从列表中创建一个字符串(第 85 行)。这就是我们的程序看起来如何改变,或者说突变,包含歌词的字符串。
"""niNety-nniinE BoOttels of Mlik On teh waLl
By Al Sweigart email@protected
Print the full lyrics to one of the longest songs ever! The song
gets sillier and sillier with each verse. Press Ctrl-C to stop.
This code is available at https://nostarch.com/big-book-small-python-programming
Tags: short, scrolling, word"""
import random, sys, time
# Set up the constants:
# (!) Try changing both of these to 0 to print all the lyrics at once.
SPEED = 0.01 # The pause in between printing letters.
LINE_PAUSE = 1.5 # The pause at the end of each line.
def slowPrint(text, pauseAmount=0.1):
"""Slowly print out the characters in text one at a time."""
for character in text:
# Set flush=True here so the text is immediately printed:
print(character, flush=True, end='') # end='' means no newline.
time.sleep(pauseAmount) # Pause in between each character.
print() # Print a newline.
print('niNety-nniinE BoOttels, by Al Sweigart email@protected')
print()
print('(Press Ctrl-C to quit.)')
time.sleep(2)
bottles = 99 # This is the starting number of bottles.
# This list holds the string used for the lyrics:
lines = [' bottles of milk on the wall,',
' bottles of milk,',
'Take one down, pass it around,',
' bottles of milk on the wall!']
try:
while bottles > 0: # Keep looping and display the lyrics.
slowPrint(str(bottles) + lines[0], SPEED)
time.sleep(LINE_PAUSE)
slowPrint(str(bottles) + lines[1], SPEED)
time.sleep(LINE_PAUSE)
slowPrint(lines[2], SPEED)
time.sleep(LINE_PAUSE)
bottles = bottles - 1 # Decrease the number of bottles by one.
if bottles > 0: # Print the last line of the current stanza.
slowPrint(str(bottles) + lines[3], SPEED)
else: # Print the last line of the entire song.
slowPrint('No more bottles of milk on the wall!', SPEED)
time.sleep(LINE_PAUSE)
print() # Print a newline.
# Choose a random line to make "sillier":
lineNum = random.randint(0, 3)
# Make a list from the line string so we can edit it. (Strings
# in Python are immutable.)
line = list(lines[lineNum])
effect = random.randint(0, 3)
if effect == 0: # Replace a character with a space.
charIndex = random.randint(0, len(line) - 1)
line[charIndex] = ' '
elif effect == 1: # Change the casing of a character.
charIndex = random.randint(0, len(line) - 1)
if line[charIndex].isupper():
line[charIndex] = line[charIndex].lower()
elif line[charIndex].islower():
line[charIndex] = line[charIndex].upper()
elif effect == 2: # Transpose two characters.
charIndex = random.randint(0, len(line) - 2)
firstChar = line[charIndex]
secondChar = line[charIndex + 1]
line[charIndex] = secondChar
line[charIndex + 1] = firstChar
elif effect == 3: # Double a character.
charIndex = random.randint(0, len(line) - 2)
line.insert(charIndex, line[charIndex])
# Convert the line list back to a string and put it in lines:
lines[lineNum] = ''.join(line)
except KeyboardInterrupt:
sys.exit() # When Ctrl-C is pressed, end the program. 在输入源代码并运行几次之后,尝试对其进行实验性的修改。标有(!)的注释对你可以做的小改变有建议。你也可以自己想办法做到以下几点:
- 交换两个相邻单词的顺序,其中“单词”是由空格分隔的文本。
- 在极少数情况下,让歌曲开始向上计数几个迭代。
- 改变整个单词的大小写。
试着找出下列问题的答案。尝试对代码进行一些修改,然后重新运行程序,看看这些修改有什么影响。
- 如果把第 47 行的
bottles = bottles - 1改成bottles = bottles - 2会怎么样? - 如果您将第 64 行的
effect = random.randint(0, 3)更改为effect = 0会发生什么? - 如果删除或注释掉第 62 行的
line = list(lines[lineNum]),会出现什么错误?
