Introduction to Programming Using Python——第10章 笔记

10.3 Case Study: Lotto Numbers


LISTING 10.2 LottoNumbers.py

isCovered = 99 * [False] # 初始化一个列表
endOfInput = True #设定一个跳出loop的判定值

while endOfInput:

	s = input("Enter a line of numbers separated by space:\n")  #用户输入数字并以“空格”隔开
	item = s.split()
	lst = [eval(x) for x in item]  # 注意这种语法格式convert every string in item to number

	for number in lst:
		if number == 0:
			endOfInput = False
		else:
			isCovered[number -1] = True  #将与之对应的位置标记成"True"

allCovered = True  #初始化一个值,假设所有值都覆盖了
for i in range(99):
	if isCovered[i] == False: #如果有数没有覆盖,初始值设为F
		allCovered = False
		break

if allCovered:
	print("The tickets cover all numbers")
else:
	print("The tickets don't cover all numbers")	

----------------------------小节分割线-----------------------------

10.4 Case Study: Deck of Cards

从52张扑克牌中任意抽取4张。

deck = [x for x in range(52)]

初始化deck列表,并赋值0~51,代表52张牌。注意每个数字代表特定的扑克牌,后面会有解释为什么。(利用[ ]和for语句初始化列表),或

deck = list(range(52))
使用list()函数和range()函数初始化列表

数字 0~12   spades 黑桃

数字 13~25   hearts 红心

数字 26~38   diamands 方块

数字 39~51   clubs 草花

扫描二维码关注公众号,回复: 3554063 查看本文章



52张牌的号码对应52张扑克,例如: 牌号为 3 ,3 // 3 是 0 代表 Spades(黑桃),3 % 13 是 3 代表4,所以牌号3代表黑桃4

LISTING 10.3 DeckOfCards.py

deck = [x for x in range(52)]

suits = ["Spades", "Hearts", "Diamonds", "Clubs"]
ranks = ["Ace", "2", "3", "4", "5", "6", "7", "8", "9", "10", "Jack", "Queen", "King"]

import random
random.shuffle(deck) #洗牌

for i in range(4):
	suit = suits[deck[i] // 13]
	rank = ranks[deck[i] % 13]
	print("Card number", deck[i], "is the", rank, "of", suit)

-------------------------------小节分割线----------------------------------------------

10.5 Deck of Cards GUI

跳过

----------------------------------小节分割线-------------------------------------------

10.6 Copying Lists

list2 = list1

并不是把list1的值拷贝给list2,原因看下图


只是把list1的reference value传递给了list2

>>> list1 = [1, 2]
>>> list2 = [3, 4, 5]
>>> id(list1)
36207312
>>> id(list2)
36249848
>>>
>>> list2 = list1
>>> id(list2)
36207312
>>>

真正的复制为如下:

list2 = [x for x in list[1]]

or

list2 = [] + list1
问答题:
10.15 What is the output of the following code?
list1 = list(range(1, 10, 2))
list2 = list1
list1[0] = 111
print(list1)

print(list2)

>>>

[111, 3, 5, 7, 9]

[111, 3, 5, 7, 9]

>>>

10.16 What is the output of the following code?
list1 = list(range(1, 10, 2))
list2 = [] + list1
list1[0] = 111
print(list1)

print(list2)

>>>

[111, 3, 5, 7, 9]

[1, 3, 5, 7, 9]

---------------------------------小节分割线------------------------------------------------

10.7 Passing Lists to Functions

list(列表数据类型)也能作为一个参数输入到function(函数)中

LISTING 10.5 PassListArgument.py

def main():
	x = 1 # x is an int variable
	y = [1, 2, 3] # y is a list

	m(x, y) # Invoke m with arguments x and y

	print("x is", x)
	print("y[0] is", y[0])

def m(number, numbers):
	number = 1001 # Assign a new value to number
	numbers[0] = 5555 # Assign a new value to numbers[0]

main() # Call the main function

结果如下:

x is 1

y[0] is 5555

可以看到函数m(number, numbers)被调用后,number是不可变数据类型,函数中创建了一个instance,函数结束后。函数外的original instance不变,所以x 任然是1,。但y和numbers都指向同一个list object,所以当number[0]的值被改变了,y[0]指向的值也同时变成了5555。

LISTING 10.6 DefaultListArgument.py

def add(x, lst = []):
    if x not in lst:
        lst.append(x)
        
    return lst

def main():
    list1 = add(1)
    print(list1)

    list2 = add(2)
    print(list2)

    list3 = add(3, [11, 12, 13, 14])
    print(list3)

    list4 = add(4)
    print(list4)

main()

输出结果如下

[1]
[1, 2]
[11, 12, 13, 14, 3]

[1, 2, 4]

add()函数在第一次被调用时,创建了lst[],之后再次被调用时,如果不指明新的列表,会默认把数添加到之前创建的lst[]中。

如果想每次添加一个数字到一个空的列表中。可以这样:

LISTING 10.7 DefaultNoneListArgument.py

def add(x, lst = None): # 指定函数的第二个参数默认为None
    if lst == None: # 如果没有给第二个参数,就创建一个[](空列表)
        lst = []
    if x not in lst:
        lst.append(x)
        
    return lst

def main():
    list1 = add(1)
    print(list1)

    list2 = add(2)
    print(list2)

    list3 = add(3, [11, 12, 13, 14])
    print(list3)

    list4 = add(4)
    print(list4)

main()
运行结果如下:
[1]
[2]
[11, 12, 13, 14, 3]
[4]

如此设置函数后,调用函数时,如果lst参数不给,就创建一个空列表。

-------------------------------------小节分割线------------------------------------------------------------

10.8 Returning a List from a Function

def reverse(lst):
    result = [] # 创建一个新的列表,并初初始化

    for element in lst: 
        result.insert(0, element) # 将列表中的元素逐一添加到新列表的第一位

    return result

当然list class(列表类型)的数据自带 reverse()methed


问答题:

10.17 True or false? When a list is passed to a function, a new list is created and passed to

the function.

False .    Listing 10.6已经详细说明。

10.18 Show the output of the following two programs:

def main():
    number = 0
    numbers = [10]
    m(number, numbers)
    print("number is", number, "and numbers[0] is", numbers[0])
def m(x, y):
    x = 3
    y[0] = 3
main()

number is 0 and numbers[0] is 3

def main():
    lst = [1, 2, 3, 4, 5]
    reverse(lst)
    for value in lst:
        print(value, end = ' ')
def reverse(lst):
    newLst = len(lst) * [0]
    for i in range(len(lst)):
        newLst[i] = lst[len(lst) - 1 - i]
    lst = newLst
main()

1 2 3 4 5  

这题关键是reverse函数并没能将列表逆序排列

10.19 Show the output of the following two programs:

def main():
    list1 = m(1)
    print(list1)
    list2 = m(1)
    print(list2)
def m(x, lst = [1, 1, 2, 3]):
    if x in lst:
    lst.remove(x)
    return lst
main()

[1, 2, 3]

[2, 3]

def main():
    list1 = m(1)
    print(list1)
    list2 = m(1)
    print(list2)
def m(x, lst = None):
    if lst == None:
        lst = [1, 1, 2, 3]
    if x in lst:
        lst.remove(x)
    return lst
main()

[1, 2, 3]

[1, 2, 3]

-------------------------------------小节分割线----------------------------------------------

10.9 Case Study: Counting the Occurrences of Each Letter


1.(a)为chars列表,利用导入之前第六章用过的函数随机产生100个小写字母存入列表

2.(b)建立counts列表用于计数

LISTING 10.8 CountLettersInList.py

import RandomCharacter

def main():
	chars = createList()

	print("The lowercase letters are:")
	displayList(chars)

	counts = countLetters(chars)

	print("The occurrences of each letter are:")
	displayCounts(counts)

# Create a list of characters		
def createList():
	chars = []

	for i in range(100):
		chars.append(RandomCharacter.getRandomLowerCaseLetter())

	return chars

# Display the list of characters
def displayList(chars):
	for i in range(len(chars)):
		if (i + 1) % 20 == 0:   # Display 20 chars on each line
			print(chars[i])
		else:
			print(chars[i], end = ' ')

# Create the count list
def countLetters(chars):
	counts = 26 * [0]

	# For each lowercase letter in the list, count it
	for i in range(len(chars)):
		counts[ord(chars[i]) - ord('a')] += 1  # 这里比较巧妙,将chars列表中的字幕转成ASCII码,减去‘a’的ASCII码后,正好对应count列表位置

	return counts

# Display counts
def displayCounts(counts):
	for i in range(len(counts)):
		if (i + 1) % 10 == 0:
			print(counts[i], chr(i + ord('a')))
		else:
			print(counts[i], chr(i + ord('a')),end = ' ')

main()

运行结果:

上面的代码中需要注意这里的代码,

	for i in range(len(chars)):
		counts[ord(chars[i]) - ord('a')] += 1 

比较巧妙,将chars列表中的字幕转成ASCII码,减去‘a’的ASCII码后正好好对应count列表位置。虽然解决了问题,但是不太有利于代码的阅读和理解。


做下对比,左边的代码比较有利于理解和阅读,右边的代码比较“聪明”,我感觉我写的话还是会老老实实用左边的写法。

------------------------------------小节分割线------------------------------------------------------------

10.10 Searching Lists 查询列表

list类型的数据可以用index 方式来查询元素所在的位置,如

>>>lst = [1, 2, 3]

>>>lst.index(2)

1

对于查询我们先从线性查询开始,就是从列表的第一位开始逐一查找


10.10.1 The Linear Search Approach 线性查找方法

LISTING 10.9 LinearSearch.py

按照列表index逐一查找key元素,如果找到返回index号,历遍完整个列表后没有找到,返回-1


def linearSearch(lst, key):
	for i in range(len(lst)):
		if key == lst[i]:
			return i
	return -1

lst = [1, 4, 4, 2, 5, -3, 6, 2]
i = linearSearch(lst, 4) # Returns 1
j = linearSearch(lst, -4) # Returns -1
k = linearSearch(lst, -3) # Returns 5

线性查找会随着列表变长,查找时间也会变长,线性查找效率低下。


10.10.2 The Binary Search Approach 二分查找方法

二分查找有一个前提,就是列表已经是排好序的,假设是从小到大排序的。


LISTING 10.10 BinarySearch.py

def binarySearch(lst, key):
	low = 0
	high = len(lst) - 1

	while high >= low:
		mid = (low + high) // 2
		if key > lst[mid]:
			low = mid + 1
		elif key == lst[mid]:
			return mid
		else:
			high = mid - 1

	return -1

lst = [2, 4, 7, 10, 11, 45, 50, 59, 60, 66, 69, 70, 79]
i = binarySearch(lst, 2) # Returns 0
j = binarySearch(lst, 11) # Returns 4
k = binarySearch(lst, 12) # Returns –1
l = binarySearch(lst, 1) # Returns –1
m = binarySearch(lst, 3) # Returns –1

书上函数最后是return -low -1,我不知道是为什么,觉得return -1也没问题,所以就按照自己的思路写了代码,如果有知道的朋友可以解释一下。

-------------------------------小节分割线---------------------------------------

10.11 Sorting Lists 列表排序

排序是很基础的算法问题,这里书中就简单介绍两种排序算法:

1.Selection Sorting (选择排序)

2.Insert Sorting(插入排序)

因为这方面有其他专门的教材,我自己目前只需要了解,不需要掌握,这一小节暂时跳过,等以后有精力了再来攻克。

-------------------------------小节分割线-----------------------------------------------

10.12 Case Study: Bouncing Balls 


这个例题结合Tkinter的GUI编程和Class类定义,通过界面“+”,“-”来控制小球的速度。

from tkinter import *  # Import all definitions from tkinter
from random import randint 

# Return a random color string in the form #RRGGBB
def getRandomColor():
	color = "#"
	for j in range(6):
		color += toHexChar(randint(0,15)) 
	return color

# Convert an integer to a single hex digit in a character
def toHexChar(hexValue):
	if 0 <= hexValue <= 9:
		return chr(hexValue + ord('0')) # 注意数值是如何结合到ASXII表中的数字部分,以“0”的ASCII码为“锚点”
	else:
		return chr(hexValue + ord('A') - 10) # 这里的“锚点”位置应为'A'的ASCII码-10

# Define a Ball class
class Ball:
	def __init__(self):
		self.x = 0 # Starting center position
		self.y = 0
		self.dx = 2 # Move right by default
		self.dy = 2 # Move down by default
		self.radius = 3 # The radius is fixed
		self.color = getRandomColor() # Get random color

class BounceBalls: # 将BounceBalls的图形窗口作为class来定义
	def __init__(self):
		self.ballList = []

		window = Tk() # 创建GUI窗口
		window.title("Bouncing Balls") # Set a title

		self.width = 350 # Width of the self.canvas
		self.height = 150 # Height of the self.canvas
		self.canvas = Canvas(window, bg = "white", width = self.width, height = self.height) # 在window中创建一个canvas
		self.canvas.pack() # 显示canvas

		frame = Frame(window) # 在window中创建一个frame
		frame.pack() # 显示frame
		btStop = Button(frame, text = "Stop", command = self.stop) # 在frame中创建一个button
		btStop.pack(side = LEFT)
		btResume = Button(frame, text = "Resume", command = self.resume)
		btResume.pack(side = LEFT)
		btAdd = Button(frame, text = "+", command = self.add)
		btAdd.pack(side = LEFT)
		btRemove = Button(frame, text = "-", command = self.remove)
		btRemove.pack(side = LEFT)

		self.sleepTime = 100 
		self.isStopped = False # 为什么isStopped()函数可以让动画停下来
		self.animate()
		
		window.mainloop()
		
	def stop(self):
		self.isStopped = True

	def resume(self):
		self.isStopped = False
		self.animate()

	def add(self):
		self.ballList.append(Ball()) # 添加一个Ball类到列表中

	def remove(self):
		self.ballList.pop()

	def animate(self):
		while not self.isStopped:
			self.canvas.after(self.sleepTime) # Sleep
			self.canvas.update() 
			self.canvas.delete("ball")

			for ball in self.ballList:
				self.redisplayBall(ball)

	def redisplayBall(self, ball):
		if ball.x > self.width or ball.x < 0:
			ball.dx = -ball.dx

		if ball.y > self.height or ball.y < 0:
			ball.dy = -ball.dy

		ball.x += ball.dx
		ball.y += ball.dy
		self.canvas.create_oval(ball.x - ball.radius, ball.y - ball.radius, ball.x + ball.radius, ball.y + ball.radius, fill = ball.color, tags = "ball")

BounceBalls()


本章小测验 TEST QUESTIONS

本章编程练习 PROGRAMMING EXERCISES


(本章完)




猜你喜欢

转载自blog.csdn.net/seeleday/article/details/80508689