Python 小型项目大全 21~25

二十一、DNA 可视化

原文:http://inventwithpython.com/bigbookpython/project21.html

脱氧核糖核酸是一种微小的分子,存在于我们身体的每个细胞中,包含着我们身体如何生长的蓝图。它看起来像一对核苷酸分子的双螺旋结构:鸟嘌呤、胞嘧啶、腺嘌呤和胸腺嘧啶。这些用字母 G、C、A 和 T 来表示。DNA 是一个长分子;它是微观的,但是如果把它拉长,它的 30 亿个碱基对会有 2 米长!这个程序是一个简单的 DNA 动画。

运行示例

当您运行dna.py时,输出将如下所示:

DNA Animation, by Al Sweigart email@protected
Press Ctrl-C to quit...
        #G-C#
       #C---G#
      #T-----A#
     #T------A#
    #A------T#
    #G-----C#
     #G---C#
     #C-G#
      ##
     #T-A#
     #C---G#
    #G-----C#
    #G------C#
     #T------A#
      #A-----T#
       #C---G#
        #G-C#
         ##
        #T-A#
       #T---A#
      #A-----T#
`--snip--`

工作原理

与项目 15“深坑”和项目 20“数字雨”类似,这个程序通过打印ROWS列表中的字符串来创建滚动动画。使用format()字符串方法将 AT 和 CG 对插入到每个字符串中。

"""DNA, by Al Sweigart email@protected
A simple animation of a DNA double-helix. Press Ctrl-C to stop.
Inspired by matoken https://asciinema.org/a/155441
This code is available at https://nostarch.com/big-book-small-python-programming
Tags: short, artistic, scrolling, science"""

import random, sys, time

PAUSE = 0.15  # (!) Try changing this to 0.5 or 0.0.

# These are the individual rows of the DNA animation:
ROWS = [
    #123456789 <- Use this to measure the number of spaces:
    '         ##',  # Index 0 has no {}.
    '        #{}-{}#',
    '       #{}---{}#',
    '      #{}-----{}#',
    '     #{}------{}#',
    '    #{}------{}#',
    '    #{}-----{}#',
    '     #{}---{}#',
    '     #{}-{}#',
    '      ##',  # Index 9 has no {}.
    '     #{}-{}#',
    '     #{}---{}#',
    '    #{}-----{}#',
    '    #{}------{}#',
    '     #{}------{}#',
    '      #{}-----{}#',
    '       #{}---{}#',
    '        #{}-{}#']
    #123456789 <- Use this to measure the number of spaces:

try:
    print('DNA Animation, by Al Sweigart email@protected')
    print('Press Ctrl-C to quit...')
    time.sleep(2)
    rowIndex = 0

    while True:  # Main program loop.
        # Increment rowIndex to draw next row:
        rowIndex = rowIndex + 1
        if rowIndex == len(ROWS):
            rowIndex = 0

        # Row indexes 0 and 9 don't have nucleotides:
        if rowIndex == 0 or rowIndex == 9:
            print(ROWS[rowIndex])
            continue

        # Select random nucleotide pairs, guanine-cytosine and
        # adenine-thymine:
        randomSelection = random.randint(1, 4)
        if randomSelection == 1:
            leftNucleotide, rightNucleotide = 'A', 'T'
        elif randomSelection == 2:
            leftNucleotide, rightNucleotide = 'T', 'A'
        elif randomSelection == 3:
            leftNucleotide, rightNucleotide = 'C', 'G'
        elif randomSelection == 4:
            leftNucleotide, rightNucleotide = 'G', 'C'

        # Print the row.
        print(ROWS[rowIndex].format(leftNucleotide, rightNucleotide))
        time.sleep(PAUSE)  # Add a slight pause.
except KeyboardInterrupt:
    sys.exit()  # When Ctrl-C is pressed, end the program. 

探索程序

试着找出下列问题的答案。尝试对代码进行一些修改,然后重新运行程序,看看这些修改有什么影响。

  1. 如果把第 42 行的rowIndex = rowIndex + 1改成rowIndex = rowIndex + 2会怎么样?
  2. 如果把 53 行的random.randint(1, 4)改成random.randint(1, 2)会怎么样?
  3. 如果将第 9 行的PAUSE = 0.15设置为PAUSE = -0.15,会得到什么错误信息?

二十二、小鸭子

原文:http://inventwithpython.com/bigbookpython/project22.html

这个程序创建了一个滚动的小鸭场。每只小鸭子都略有不同:它们可以面向左边或右边,有两种不同的体型,四种眼睛,两种嘴巴,三种翅膀位置。这给了我们 96 种不同的可能变异,这些变异是小鸭程序不断产生的。

运行示例

当你运行ducklings.py的时候,输出将如下所示:

Duckling Screensaver, by Al Sweigart email@protected
Press Ctrl-C to quit...
                                             =" )
=")                                          (  v)=")
( ^)                                          ^ ^ ( v) >'')
 ^^                                                ^^  (  ^)
                              >")                       ^ ^
                              ( v)      =^^)
 ("<  ("<                >")   ^^       (  >)
(^ ) (< )                ( ^)            ^ ^
 ^^   ^^             ("<  ^^                       (``<>^^)
 (^^=               (^ )                          (<  )(  ^)
(v  ) ( "<           ^^                            ^ ^  ^ ^
`--snip--`

工作原理

这个程序用一个Duckling类表示小鸭子。在这个类的__init__()方法中选择了每只鸭子的随机特征,而每只鸭子的各个身体部分由getHeadStr()getBodyStr()getFeetStr()方法返回。

"""Duckling Screensaver, by Al Sweigart email@protected
A screensaver of many many ducklings.

>" )   =^^)    (``=   ("=  >")    ("=
(  >)  (  ^)  (v  )  (^ )  ( >)  (v )
^ ^    ^ ^    ^ ^    ^^    ^^    ^^

This code is available at https://nostarch.com/big-book-small-python-programming
Tags: large, artistic, object-oriented, scrolling"""

import random, shutil, sys, time

# Set up the constants:
PAUSE = 0.2  # (!) Try changing this to 1.0 or 0.0.
DENSITY = 0.10  # (!) Try changing this to anything from 0.0 to 1.0.

DUCKLING_WIDTH = 5
LEFT = 'left'
RIGHT = 'right'
BEADY = 'beady'
WIDE = 'wide'
HAPPY = 'happy'
ALOOF = 'aloof'
CHUBBY = 'chubby'
VERY_CHUBBY = 'very chubby'
OPEN = 'open'
CLOSED = 'closed'
OUT = 'out'
DOWN = 'down'
UP = 'up'
HEAD = 'head'
BODY = 'body'
FEET = 'feet'

# Get the size of the terminal window:
WIDTH = shutil.get_terminal_size()[0]
# We can't print to the last column on Windows without it adding a
# newline automatically, so reduce the width by one:
WIDTH -= 1


def main():
   print('Duckling Screensaver, by Al Sweigart')
   print('Press Ctrl-C to quit...')
   time.sleep(2)

   ducklingLanes = [None] * (WIDTH // DUCKLING_WIDTH)

   while True:  # Main program loop.
       for laneNum, ducklingObj in enumerate(ducklingLanes):
           # See if we should create a duckling in this lane:
           if (ducklingObj == None and random.random() <= DENSITY):
                   # Place a duckling in this lane:
                   ducklingObj = Duckling()
                   ducklingLanes[laneNum] = ducklingObj

           if ducklingObj != None:
               # Draw a duckling if there is one in this lane:
               print(ducklingObj.getNextBodyPart(), end='')
               # Delete the duckling if we've finished drawing it:
               if ducklingObj.partToDisplayNext == None:
                   ducklingLanes[laneNum] = None
           else:
               # Draw five spaces since there is no duckling here.
               print(' ' * DUCKLING_WIDTH, end='')

       print()  # Print a newline.
       sys.stdout.flush()  # Make sure text appears on the screen.
       time.sleep(PAUSE)


class Duckling:
   def __init__(self):
       """Create a new duckling with random body features."""
       self.direction = random.choice([LEFT, RIGHT])
       self.body = random.choice([CHUBBY, VERY_CHUBBY])
       self.mouth = random.choice([OPEN, CLOSED])
       self.wing = random.choice([OUT, UP, DOWN])

       if self.body == CHUBBY:
           # Chubby ducklings can only have beady eyes.
           self.eyes = BEADY
       else:
           self.eyes = random.choice([BEADY, WIDE, HAPPY, ALOOF])

       self.partToDisplayNext = HEAD

   def getHeadStr(self):
       """Returns the string of the duckling's head."""
       headStr = ''
       if self.direction == LEFT:
           # Get the mouth:
           if self.mouth == OPEN:
               headStr += '>'
           elif self.mouth == CLOSED:
               headStr += '='

           # Get the eyes:
           if self.eyes == BEADY and self.body == CHUBBY:
                headStr += '"'
            elif self.eyes == BEADY and self.body == VERY_CHUBBY:
                headStr += '" '
            elif self.eyes == WIDE:
                headStr += "''"
            elif self.eyes == HAPPY:
                headStr += '^^'
            elif self.eyes == ALOOF:
                headStr += '``'

            headStr += ') '  # Get the back of the head.

        if self.direction == RIGHT:
            headStr += ' ('  # Get the back of the head.

            # Get the eyes:
            if self.eyes == BEADY and self.body == CHUBBY:
                headStr += '"'
            elif self.eyes == BEADY and self.body == VERY_CHUBBY:
                headStr += ' "'
            elif self.eyes == WIDE:
                headStr += "''"
            elif self.eyes == HAPPY:
                headStr += '^^'
            elif self.eyes == ALOOF:
                headStr += '``'

            # Get the mouth:
            if self.mouth == OPEN:
                headStr += '<'
            elif self.mouth == CLOSED:
                headStr += '='

        if self.body == CHUBBY:
            # Get an extra space so chubby ducklings are the same
            # width as very chubby ducklings.
            headStr += ' '

        return headStr

    def getBodyStr(self):
        """Returns the string of the duckling's body."""
        bodyStr = '('  # Get the left side of the body.
        if self.direction == LEFT:
            # Get the interior body space:
            if self.body == CHUBBY:
                bodyStr += ' '
            elif self.body == VERY_CHUBBY:
                bodyStr += '  '

            # Get the wing:
            if self.wing == OUT:
                bodyStr += '>'
            elif self.wing == UP:
                bodyStr += '^'
            elif self.wing == DOWN:
                bodyStr += 'v'

        if self.direction == RIGHT:
            # Get the wing:
            if self.wing == OUT:
                bodyStr += '<'
            elif self.wing == UP:
                bodyStr += '^'
            elif self.wing == DOWN:
                bodyStr += 'v'

            # Get the interior body space:
            if self.body == CHUBBY:
                bodyStr += ' '
            elif self.body == VERY_CHUBBY:
                bodyStr += '  '

        bodyStr += ')'  # Get the right side of the body.

        if self.body == CHUBBY:
            # Get an extra space so chubby ducklings are the same
            # width as very chubby ducklings.
            bodyStr += ' '

        return bodyStr

    def getFeetStr(self):
        """Returns the string of the duckling's feet."""
        if self.body == CHUBBY:
            return ' ^^  '
        elif self.body == VERY_CHUBBY:
            return ' ^ ^ '

    def getNextBodyPart(self):
        """Calls the appropriate display method for the next body
        part that needs to be displayed. Sets partToDisplayNext to
        None when finished."""
        if self.partToDisplayNext == HEAD:
            self.partToDisplayNext = BODY
            return self.getHeadStr()
        elif self.partToDisplayNext == BODY:
            self.partToDisplayNext = FEET
            return self.getBodyStr()
        elif self.partToDisplayNext == FEET:
            self.partToDisplayNext = None
            return self.getFeetStr()



# If this program was run (instead of imported), run the game:
if __name__ == '__main__':
    try:
        main()
    except KeyboardInterrupt:
        sys.exit()  # When Ctrl-C is pressed, end the program. 

在输入源代码并运行几次之后,尝试对其进行实验性的修改。标有(!)的注释对你可以做的小改变有建议。

探索程序

试着找出下列问题的答案。尝试对代码进行一些修改,然后重新运行程序,看看这些修改有什么影响。

  1. 如果将第 75 行的random.choice([LEFT, RIGHT])改为random.choice([LEFT])?会发生什么
  2. 如果把 194 行的self.partToDisplayNext = BODY改成self.partToDisplayNext = None会怎么样?
  3. 如果把 197 行的self.partToDisplayNext = FEET改成self.partToDisplayNext = BODY会怎么样?
  4. 如果把 195 行的return self.getHeadStr()改成return self.getFeetStr()会怎么样?

二十三、蚀刻绘图器

原文:http://inventwithpython.com/bigbookpython/project23.html

当您使用WASD键在屏幕上移动笔尖时,蚀刻绘图器通过描绘一条连续的线来形成一幅图片,就像蚀刻素描玩具一样。让你艺术的一面爆发出来,看看你能创造出什么形象!这个程序还可以让你把你的绘图保存到一个文本文件中,这样你以后就可以把它们打印出来。此外,你可以将其他图形的WASD运动复制粘贴到这个程序中,比如源代码第 6 到 14 行中的希尔伯特曲线分形的WASD命令。

运行示例

当你运行etchingdrawer.py时,输出将看起来像图 23-1 。

f23001

:在蚀刻绘图器程序中绘制的图

工作原理

与项目 17“骰子数学”一样,这个程序使用存储在名为canvas的变量中的字典来记录绘图的线条。关键字是(x, y)元组,值是表示要在屏幕上的 x,y 坐标处绘制的线形的字符串。附录 b 给出了可以在 Python 程序中使用的 Unicode 字符的完整列表。

第 126 行有一个对open()的函数调用,它传递了一个encoding='utf-8'参数。原因超出了本书的范围,但这是 Windows 将行字符写入文本文件所必需的。

"""Etching Drawer, by Al Sweigart email@protected
An art program that draws a continuous line around the screen using the
WASD keys. Inspired by Etch A Sketch toys.

For example, you can draw Hilbert Curve fractal with:
SDWDDSASDSAAWASSDSASSDWDSDWWAWDDDSASSDWDSDWWAWDWWASAAWDWAWDDSDW

Or an even larger Hilbert Curve fractal with:
DDSAASSDDWDDSDDWWAAWDDDDSDDWDDDDSAASDDSAAAAWAASSSDDWDDDDSAASDDSAAAAWA
ASAAAAWDDWWAASAAWAASSDDSAASSDDWDDDDSAASDDSAAAAWAASSDDSAASSDDWDDSDDWWA
AWDDDDDDSAASSDDWDDSDDWWAAWDDWWAASAAAAWDDWAAWDDDDSDDWDDSDDWDDDDSAASDDS
AAAAWAASSDDSAASSDDWDDSDDWWAAWDDDDDDSAASSDDWDDSDDWWAAWDDWWAASAAAAWDDWA
AWDDDDSDDWWAAWDDWWAASAAWAASSDDSAAAAWAASAAAAWDDWAAWDDDDSDDWWWAASAAAAWD
DWAAWDDDDSDDWDDDDSAASSDDWDDSDDWWAAWDD

This code is available at https://nostarch.com/big-book-small-python-programming
Tags: large, artistic"""

import shutil, sys

# Set up the constants for line characters:
UP_DOWN_CHAR         = chr(9474)  # Character 9474 is '│'
LEFT_RIGHT_CHAR      = chr(9472)  # Character 9472 is '─'
DOWN_RIGHT_CHAR      = chr(9484)  # Character 9484 is '┌'
DOWN_LEFT_CHAR       = chr(9488)  # Character 9488 is '┐'
UP_RIGHT_CHAR        = chr(9492)  # Character 9492 is '└'
UP_LEFT_CHAR         = chr(9496)  # Character 9496 is '┘'
UP_DOWN_RIGHT_CHAR   = chr(9500)  # Character 9500 is '├'
UP_DOWN_LEFT_CHAR    = chr(9508)  # Character 9508 is '┤'
DOWN_LEFT_RIGHT_CHAR = chr(9516)  # Character 9516 is '┬'
UP_LEFT_RIGHT_CHAR   = chr(9524)  # Character 9524 is '┴'
CROSS_CHAR           = chr(9532)  # Character 9532 is '┼'
# A list of chr() codes is at https://inventwithpython.com/chr

# Get the size of the terminal window:
CANVAS_WIDTH, CANVAS_HEIGHT = shutil.get_terminal_size()
# We can't print to the last column on Windows without it adding a
# newline automatically, so reduce the width by one:
CANVAS_WIDTH -= 1
# Leave room at the bottom few rows for the command info lines.
CANVAS_HEIGHT -= 5

"""The keys for canvas will be (x, y) integer tuples for the coordinate,
and the value is a set of letters W, A, S, D that tell what kind of line
should be drawn."""
canvas = {}
cursorX = 0
cursorY = 0


def getCanvasString(canvasData, cx, cy):
   """Returns a multiline string of the line drawn in canvasData."""
   canvasStr = ''

   """canvasData is a dictionary with (x, y) tuple keys and values that
   are sets of 'W', 'A', 'S', and/or 'D' strings to show which
   directions the lines are drawn at each xy point."""
   for rowNum in range(CANVAS_HEIGHT):
       for columnNum in range(CANVAS_WIDTH):
           if columnNum == cx and rowNum == cy:
               canvasStr += '#'
               continue

           # Add the line character for this point to canvasStr.
           cell = canvasData.get((columnNum, rowNum))
           if cell in (set(['W', 'S']), set(['W']), set(['S'])):
               canvasStr += UP_DOWN_CHAR
           elif cell in (set(['A', 'D']), set(['A']), set(['D'])):
               canvasStr += LEFT_RIGHT_CHAR
           elif cell == set(['S', 'D']):
               canvasStr += DOWN_RIGHT_CHAR
           elif cell == set(['A', 'S']):
               canvasStr += DOWN_LEFT_CHAR
           elif cell == set(['W', 'D']):
               canvasStr += UP_RIGHT_CHAR
           elif cell == set(['W', 'A']):
               canvasStr += UP_LEFT_CHAR
           elif cell == set(['W', 'S', 'D']):
               canvasStr += UP_DOWN_RIGHT_CHAR
           elif cell == set(['W', 'S', 'A']):
               canvasStr += UP_DOWN_LEFT_CHAR
           elif cell == set(['A', 'S', 'D']):
               canvasStr += DOWN_LEFT_RIGHT_CHAR
           elif cell == set(['W', 'A', 'D']):
               canvasStr += UP_LEFT_RIGHT_CHAR
           elif cell == set(['W', 'A', 'S', 'D']):
               canvasStr += CROSS_CHAR
           elif cell == None:
               canvasStr += ' '
       canvasStr += '\n'  # Add a newline at the end of each row.
   return canvasStr


moves = []
while True:  # Main program loop.
   # Draw the lines based on the data in canvas:
   print(getCanvasString(canvas, cursorX, cursorY))

   print('WASD keys to move, H for help, C to clear, '
        + 'F to save, or QUIT.')
    response = input('> ').upper()

    if response == 'QUIT':
        print('Thanks for playing!')
        sys.exit()  # Quit the program.
    elif response == 'H':
        print('Enter W, A, S, and D characters to move the cursor and')
        print('draw a line behind it as it moves. For example, ddd')
        print('draws a line going right and sssdddwwwaaa draws a box.')
        print()
        print('You can save your drawing to a text file by entering F.')
        input('Press Enter to return to the program...')
        continue
    elif response == 'C':
        canvas = {}  # Erase the canvas data.
        moves.append('C')  # Record this move.
    elif response == 'F':
        # Save the canvas string to a text file:
        try:
            print('Enter filename to save to:')
            filename = input('> ')

            # Make sure the filename ends with .txt:
            if not filename.endswith('.txt'):
                filename += '.txt'
            with open(filename, 'w', encoding='utf-8') as file:
                file.write(''.join(moves) + '\n')
                file.write(getCanvasString(canvas, None, None))
        except:
            print('ERROR: Could not save file.')

    for command in response:
        if command not in ('W', 'A', 'S', 'D'):
            continue  # Ignore this letter and continue to the next one.
        moves.append(command)  # Record this move.

        # The first line we add needs to form a full line:
        if canvas == {}:
            if command in ('W', 'S'):
                # Make the first line a horizontal one:
                canvas[(cursorX, cursorY)] = set(['W', 'S'])
            elif command in ('A', 'D'):
                # Make the first line a vertical one:
                canvas[(cursorX, cursorY)] = set(['A', 'D'])

        # Update x and y:
        if command == 'W' and cursorY > 0:
            canvas[(cursorX, cursorY)].add(command)
            cursorY = cursorY - 1
        elif command == 'S' and cursorY < CANVAS_HEIGHT - 1:
            canvas[(cursorX, cursorY)].add(command)
            cursorY = cursorY + 1
        elif command == 'A' and cursorX > 0:
            canvas[(cursorX, cursorY)].add(command)
            cursorX = cursorX - 1
        elif command == 'D' and cursorX < CANVAS_WIDTH - 1:
            canvas[(cursorX, cursorY)].add(command)
            cursorX = cursorX + 1
        else:
            # If the cursor doesn't move because it would have moved off
            # the edge of the canvas, then don't change the set at
            # canvas[(cursorX, cursorY)].
            continue

        # If there's no set for (cursorX, cursorY), add an empty set:
        if (cursorX, cursorY) not in canvas:
            canvas[(cursorX, cursorY)] = set()

        # Add the direction string to this xy point's set:
        if command == 'W':
            canvas[(cursorX, cursorY)].add('S')
        elif command == 'S':
            canvas[(cursorX, cursorY)].add('W')
        elif command == 'A':
            canvas[(cursorX, cursorY)].add('D')
        elif command == 'D':
            canvas[(cursorX, cursorY)].add('A') 

探索程序

试着找出下列问题的答案。尝试对代码进行一些修改,然后重新运行程序,看看这些修改有什么影响。

  1. 如果把 101 行的response = input('> ').upper()改成response = input('> ')会怎么样?
  2. 如果把第 61 行的canvasStr += '#'改成canvasStr += '@'会怎么样?
  3. 如果把第 89 行的canvasStr += ' '改成canvasStr += '.'会怎么样?
  4. 如果把 94 行的moves = []改成moves = list('SDWDDSASDSAAWASSDSAS')会怎么样?

二十四、因子查找器

原文:http://inventwithpython.com/bigbookpython/project24.html

一个数的因数是任何两个其它数,当它们彼此相乘时,产生该数。比如2 × 13 = 26,所以 2 和 13 是 26 的因数。还有,1 × 26 = 26,所以 1 和 26 也是 26 的因数。所以我们说 26 有四个因子:1,2,13,26。

如果一个数只有两个因子(1 和它本身),我们称之为质数。否则,我们称之为合数。使用因数查找器发现一些新的质数!(提示:质数总是以不是 5 的奇数结尾。)你也可以让计算机用项目 56“质数”来计算它们

这个程序的数学并不太重,这使它成为初学者的理想项目。

运行示例

当您运行factorfinder.py时,输出将如下所示:

Factor Finder, by Al Sweigart email@protected
`--snip--`
Enter a number to factor (or "QUIT" to quit):
> 26
1, 2, 13, 26
Enter a number to factor (or "QUIT" to quit):
> 4352784
1, 2, 3, 4, 6, 8, 12, 16, 24, 29, 48, 53, 58, 59, 87, 106, 116, 118, 159, 174, 177, 212, 232, 236, 318, 348, 354, 424, 464, 472, 636, 696, 708, 848, 944, 1272, 1392, 1416, 1537, 1711, 2544, 2832, 3074, 3127, 3422, 4611, 5133, 6148, 6254, 6844, 9222, 9381, 10266, 12296, 12508, 13688, 18444, 18762, 20532, 24592, 25016, 27376, 36888, 37524, 41064, 50032, 73776, 75048, 82128, 90683, 150096, 181366, 272049, 362732, 544098, 725464, 1088196, 1450928, 2176392, 4352784
Enter a number to factor (or "QUIT" to quit):
> 9787
1, 9787
Enter a number to factor (or "QUIT" to quit):
> quit

工作原理

我们可以通过检查第二个数是否能整除第一个数来判断一个数是否是另一个数的因数。例如,7 是 21 的因数,因为 21 ÷ 7 是 3。这也给了我们 21 的另一个因素:3。但是,8 不是 21 的因数,因为 21 ÷ 8 = 2.625。分数余数部分告诉我们这个等式没有被均匀地划分。

%模数操作符将执行除法并告诉我们是否有余数:21 % 7计算为0,意味着没有余数,7 是 21 的因数,而21 % 8计算为1,一个非零值,意味着它不是一个因数。因子查找程序在第 35 行使用这种技术来确定哪些数字是因子。

math.sqrt()函数返回传递给它的数字的平方根。例如,math.sqrt(25)返回5.0,因为 5 的倍数本身就是 25,所以它是 25 的平方根。

"""Factor Finder, by Al Sweigart email@protected
Finds all the factors of a number.
This code is available at https://nostarch.com/big-book-small-python-programming
Tags: tiny, beginner, math"""

import math, sys

print('''Factor Finder, by Al Sweigart email@protected

A number's factors are two numbers that, when multiplied with each
other, produce the number. For example, 2 x 13 = 26, so 2 and 13 are
factors of 26\. 1 x 26 = 26, so 1 and 26 are also factors of 26\. We
say that 26 has four factors: 1, 2, 13, and 26.

If a number only has two factors (1 and itself), we call that a prime
number. Otherwise, we call it a composite number.

Can you discover some prime numbers?
''')

while True:  # Main program loop.
    print('Enter a positive whole number to factor (or QUIT):')
    response = input('> ')
    if response.upper() == 'QUIT':
        sys.exit()

    if not (response.isdecimal() and int(response) > 0):
        continue
    number = int(response)

    factors = []

    # Find the factors of number:
    for i in range(1, int(math.sqrt(number)) + 1):
        if number % i == 0:  # If there's no remainder, it is a factor.
            factors.append(i)
            factors.append(number // i)

    # Convert to a set to get rid of duplicate factors:
    factors = list(set(factors))
    factors.sort()

    # Display the results:
    for i, factor in enumerate(factors):
        factors[i] = str(factor)
    print(', '.join(factors)) 

探索程序

试着找出下列问题的答案。尝试对代码进行一些修改,然后重新运行程序,看看这些修改有什么影响。

  1. 如果删除或注释掉第 36 行的factors.append(i)会发生什么?
  2. 如果删除或注释掉第 40 行的factors = list(set(factors))会发生什么?(提示:输入一个平方数,如 25 或 36 或 49。)
  3. 如果删除或注释掉第 41 行的factors.sort()会发生什么?
  4. 如果将第 31 行的factors = []改为factors = '',会得到什么错误信息?
  5. 如果把第 31 行的factors = []改成factors = [-42]会怎么样?
  6. 如果将第 31 行的factors = []改为factors = ['hello'],会得到什么错误信息?

二十五、快速反应

原文:http://inventwithpython.com/bigbookpython/project25.html

这个程序测试你的反应速度:一看到DRAW这个词就按回车。但是要小心。在DRAW出现之前按下它,你就输了。你是西方最快的键盘吗?

运行示例

当您运行fastdraw.py时,输出将如下所示:

Fast Draw, by Al Sweigart email@protected

Time to test your reflexes and see if you are the fastest
draw in the west!
When you see "DRAW", you have 0.3 seconds to press Enter.
But you lose if you press Enter before "DRAW" appears.

Press Enter to begin...

It is high noon...
DRAW!

You took 0.3485 seconds to draw. Too slow!
Enter QUIT to stop, or press Enter to play again.
> quit
Thanks for playing!

工作原理

input()函数在等待用户输入字符串时暂停程序。这个简单的行为意味着我们不能只用input()来创建实时游戏。然而,你的程序将缓冲键盘输入,这意味着如果你在input()被调用之前按下CAT键,这些字符将被保存,一旦input()执行,它们将立即出现。

通过记录第 22 行的input()调用之前的时间和第 24 行的input()调用之后的时间,我们可以确定玩家按下回车花了多长时间。然而,如果他们在调用input()之前按下回车,回车按下的缓冲会导致input()立即返回(通常在大约 3 毫秒内)。这就是为什么第 26 行检查时间是否小于 0.01 秒或 10 毫秒,以确定玩家按下回车太快。

"""Fast Draw, by Al Sweigart email@protected
Test your reflexes to see if you're the fastest draw in the west.
This code is available at https://nostarch.com/big-book-small-python-programming
Tags: tiny, beginner, game"""

import random, sys, time

print('Fast Draw, by Al Sweigart email@protected')
print()
print('Time to test your reflexes and see if you are the fastest')
print('draw in the west!')
print('When you see "DRAW", you have 0.3 seconds to press Enter.')
print('But you lose if you press Enter before "DRAW" appears.')
print()
input('Press Enter to begin...')

while True:
    print()
    print('It is high noon...')
    time.sleep(random.randint(20, 50) / 10.0)
    print('DRAW!')
    drawTime = time.time()
    input()  # This function call doesn't return until Enter is pressed.
    timeElapsed = time.time() - drawTime

    if timeElapsed < 0.01:
        # If the player pressed Enter before DRAW! appeared, the input()
        # call returns almost instantly.
        print('You drew before "DRAW" appeared! You lose.')
    elif timeElapsed > 0.3:
        timeElapsed = round(timeElapsed, 4)
        print('You took', timeElapsed, 'seconds to draw. Too slow!')
    else:
        timeElapsed = round(timeElapsed, 4)
        print('You took', timeElapsed, 'seconds to draw.')
        print('You are the fastest draw in the west! You win!')

    print('Enter QUIT to stop, or press Enter to play again.')
    response = input('> ').upper()
    if response == 'QUIT':
        print('Thanks for playing!')
        sys.exit() 

探索程序

试着找出下列问题的答案。尝试对代码进行一些修改,然后重新运行程序,看看这些修改有什么影响。

  1. 如果把第 22 行的drawTime = time.time()改成drawTime = 0会怎么样?
  2. 如果把第 30 行的timeElapsed > 0.3改成timeElapsed < 0.3会怎么样?
  3. 如果把第 24 行的time.time() - drawTime改成time.time() + drawTime会怎么样?
  4. 如果删除或注释掉第 15 行的input('Press Enter to begin...')会发生什么?

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/10402.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

计算机网络微课堂1-3节

目录 1. TCP/TP协议​编辑 2. 3.调制解调器 4.因特网的组成 5.电路交换 6.分组交换 重要常用 7.报文交换 8.总结电路交换 报文交换和分组交换 9. 1. TCP/TP协议 2. ISP 网络提供商 ISP的三层 国际 国家 和本地 3.调制解调器 什么是调制解调器&#xff0c;它存在的…

Python 小型项目大全 11~15

十一、标题党生成器 原文&#xff1a;http://inventwithpython.com/bigbookpython/project11.html 我们的网站需要欺骗人们去看广告&#xff01;但是想出有创意的原创内容太难了。幸运的是&#xff0c;有了标题党生成器&#xff0c;我们可以让一台计算机产生数百万个令人发指的…

【Linux】浅析Input子系统

文章目录1. 框架1.1 数据结构1.2 evdev_handler1.3 evdev_init1.4 input_register_handler2. 应用如何打开节点并读取到事件数据2.1 evdev_fops2.2 evdev_open2.3 evdev_release2.4 evdev_read2.5 evdev_write2.6 evdev_poll2.7 evdev_fasync2.8 evdev_ioctl2.9 evdev_ioctl_co…

[考研数据结构]第3章之栈的基本知识与操作

文章目录 栈的基本概念 栈的实现 顺序栈 共享栈 链栈 栈的基本概念 栈的定义 栈&#xff08;Stack&#xff09;是只允许在一端进行插入或删除操作的线性表 相关术语 栈顶&#xff08;Top&#xff09;线性表允许进行插入或删除的那一端称之为栈顶栈底&#xff08;Bottom&…

【计算机网络-数据链路层】集线器、网桥、交换机

本文许多文字和图片使用了湖科大教书匠&#xff08;高军老师&#xff09;的 PPT&#xff0c;在此表示感谢。正是他让非科班的我能以奇妙的方式走进网络的世界。 文章目录1 【物理层】集线器&#xff08;Hub&#xff09;——共享式以太网1.1 为什么使用集线器&#xff1f;1.2 集…

macOS Monterey 12.6.5 (21G531) Boot ISO 原版可引导镜像

本站下载的 macOS 软件包&#xff0c;既可以拖拽到 Applications&#xff08;应用程序&#xff09;下直接安装&#xff0c;也可以制作启动 U 盘安装&#xff0c;或者在虚拟机中启动安装。另外也支持在 Windows 和 Linux 中创建可引导介质。 2023 年 4 月 10 日&#xff08;北京…

ESXI 6.7全面系统教程~汇总

ESXI 6.7全面系统教程 许可证&#xff1a;0A65P-00HD0-375M1-M097M-22P7H esxi 是一个脱机系统&#xff0c;也是一个虚拟机系统与vmware 相比&#xff0c;它可以直接运行在硬件上&#xff0c;这样可以减少资源浪费&#xff0c;一般用于服务器上&#xff1b;下面是esxi 的完整…

stable-diffusion-webui-colab部署记录

stable-diffusion-webui-colab 该模型可以在网上云端部署stable-diffusion&#xff0c;减少本地部署的繁琐步骤降低配置要求的依赖。 一、进入stable-diffusion-webui-colab 1.网址&#xff1a;https://github.com/camenduru/stable-diffusion-webui-colab 在分支中选择driv…

我的创作纪念日:Unity CEO表示生成式AI将是Unity近期发展重点,发布神秘影片预告

PICK 未来的AI技术将会让人类迎来下一个生产力变革&#xff0c;这其中也包括生成型AI的突破性革新。各大公司也正在竞相推出AIGC工具&#xff0c;其中微软的Copilot、Adobe的Firefly、Github的chatGPT等引起了人们的关注。然而&#xff0c;游戏开发领域似乎还没有一款真正针对性…

Vulnhub:Digitalworld.local (Development)靶机

kali&#xff1a;192.168.111.111 靶机&#xff1a;192.168.111.130 信息收集 端口扫描 nmap -A -v -sV -T5 -p- --scripthttp-enum 192.168.111.130 查看网站首页源码 访问development目录&#xff0c;提示存在一个流量包 查看流量包发现另一个网站路径&#xff1a;/devel…

java继承类怎么写

继承类是通过把父类的方法和属性继承到一个类中&#xff0c;而子类的方法和属性是子类自己定义的。 Java中有一个很重要的概念叫做继承&#xff0c;这也是 Java语言的精髓所在。Java语言提供了一种机制&#xff0c;叫做派生类。在 Java中&#xff0c;如果没有实现了某个派生类方…

python 调用c++

python中调用c&#xff0c;函数参数用 int类型&#xff0c;返回值为类型1,且返回值为 false。 注意&#xff1a;如果你使用了C中的 false&#xff0c;则返回的是-1。 在 Python中调用C时&#xff0c;你会得到一个名为 bool的类&#xff0c;其中包含了两个成员变量&#xff1a; …

多智能体深度强化学习在移动边缘计算的联合多通道访问和任务卸载中的应用

多智能体深度强化学习在移动边缘计算的联合多通道访问和任务卸载中的应用主要贡献与相关工作比较的贡献三、系统模型&#xff08;only 2 pages&#xff09;3.1 网络模型3.2 通信模型3.3 计算模型3.3.1 本地计算3.3.2 卸载计算四、预备知识&#xff08;only 1 page&#xff09;五…

SpringCloud-Gateway网关搭建整合nacos配置中心实现动态路由整合sentinel实现服务限流熔点降级

官方文档(更多配置详情直接查看官方文档) 为什么需要服务网关 传统的单体架构中只需要开放一个服务给客户端调用&#xff0c;但是微服务架构中是将一个系统拆分成多个微服务&#xff0c;如果没有网关&#xff0c;客户端只能在本地记录每个微服务的调用地址&#xff0c;当需要调…

安全防御 --- 恶意代码、防病毒

一、恶意代码 1、按照传播方式分类 &#xff08;1&#xff09;病毒 概念&#xff1a;病毒是一种基于硬件和操作系统的程序&#xff0c;具有感染和破坏能力&#xff0c;这与病毒程序的结构有关。病毒攻击的宿主程序是病毒的栖身地&#xff0c;它是病毒传播的目的地&#xff0…

MySQL库的操作

文章目录&#xff1a;创建数据库字符集和校验规则查看系统默认字符集和校验规则查看数据库支持的字符集查看数据库支持的字符集校验规则校验规则对数据库的影响操作数据库查看数据库显示创建语句修改数据库删除数据库数据库的备份和还原表的备份和还原查看连接情况创建数据库 …

数据库基础

文章目录前言一、什么是数据库二、主流数据库三、基本使用1.连接服务器2.服务器,数据库,表关系3.使用案例4.数据逻辑存储四、MySQL架构五、SQL分类六、存储引擎1.存储引擎2.查看存储引擎3.存储引擎对比总结前言 正文开始!!! 一、什么是数据库 存储数据用文件就可以了,为什么还…

【并发编程】AQS源码

ReentrantLock 互斥锁,可重入 AQS是可以支持互斥锁和共享锁的&#xff0c;这里只分析互斥锁的源码 加锁 公平锁和非公平锁 公平锁 final void lock() {acquire(1); //抢占1把锁.}// AQS里面的方法public final void acquire(int arg) { if (!tryAcquire(arg) &&acq…

IP协议(网络层重点协议)

目录 一、IP协议报头格式 二、地址选择 1、IP地址 &#xff08;1&#xff09;格式 &#xff08;2&#xff09;组成 &#xff08;3&#xff09;分类 &#xff08;4&#xff09;子网掩码 三、路由选择 IP协议是网络层的协议&#xff0c;它主要完成两个方面的任务&#xf…

redis基础(6.0)数据结构、事务、常用组件等

1 概述 1.1 redis介绍 Redis 是互联网技术领域使用最为广泛的存储中间件&#xff0c;它是「Remote Dictionary Service」的首字母缩写&#xff0c;也就是「远程字典服务」。Redis 以其超高的性能、完美的文档、 简洁易懂的源码和丰富的客户端库支持在开源中间件领域广受好评。…