Python学习笔记
程序设计思想与方法CS-902
- 陆朝俊
- 周二下午6-8节,12:55开始上课
- 3学分,平时20%大作业30%期末(开卷)50%
- 目标:学习了解计算思维,通过Python语言实现
课程安排 | 周次 |
---|---|
教学课 | 1,2,3,4,5,7,9,11,13,14,15 |
上机课 | 6,8,10,12 |
课程笔记
-
第一周
-
计算机的硬件组成,基本工作原理
-
程序设计语言:机器语言(二进制编码)、汇编语言(助忆符,需汇编器处理)、高级语言(适合人用,需编译器或解释器处理)
-
计算机解决问题步骤:先找出解决问题的方法步骤即算法,再用程序语言表达算法。关键:算法
-
算法的每一步必须是确切的,可行的,能在有限步内完成。
-
课程群名称来源CT-computational thinking(如何像计算机科学家那样思考)
-
计算思维:建立在计算机的能力(能做什么)和局限之上(不能做什么)
-
案例
- 算法:小学算术的长除法
- 查找:查黄页是顺序查找还是借助索引
- 排序:整理扑克牌
- 排队:先来先处理
- 预取与缓存:书包存放当天上课要用的书(书包相当于缓存,寝室相当于硬盘)
- 并行处理:同时烧几个菜
- …
-
计算+X,拥有广泛的应用场景
-
课程定位 :学习利用计算机解决问题的实现方法,不是程序设计语言课程,不是算法和数据结构课程Python语言介绍:荷兰人Guido Van Rossum发明,简单开源高度可读性。编译+解释。
Python版本越高反而丧失了高度可读性的初心。
IDE:Intergrated Development Environment 集成开发环境
Python程序防止一闪而过:最后添加输入语句
-
程序构件:数据
数据有不同类型,常见的有字符串,数字等
-
程序构件:变量
以字母或下划线开头,后跟字母等数字,区分大小写且有保留字(连字符、空格非法)
良好的命名风格:有意义+保持一致风格(骆驼式,匈牙利命名标记,数据类型,例iMyage)
-
程序构件:表达式
良好编程风格:用空格,括号增加表达式的可读性,不依赖于优先级
-
程序构件:语句
输出语句,赋值语句(本课程主要用模板讲解语句,专业教材用巴克莱范式表示)
-
程序构件:函数
可以理解为把一段语句序列打包命名。用def来定义函数
-
程序构件:注释
# Author:Verification-Code
# Version: 1.0.0
def main():
全书概要:信息抽象与数据表示
两种符号化表示:字面值和标识符(PI等),Python通过赋值语句来定义变量,任何变量都必须先定义后使用。
-
为了更精确的表示信息,编程语言提供不同数据类型。合法值+合法运算
180+78一定有意义吗?
-
-
Python学习语法:
-
输出语句:Print(‘XXX’)
-
变 量:
messgae="Hello World!"
print(message)
字符串:
在Python中,用引号括起的都是字符串,其中引号既可以是单引号又可以是双引号,*这种灵活性主要是为了能让你在字符串中包含引号和撇号。
-
使用函数对字符串进行操作:例如
name='ada lovelace'
print(name.title())
结果:Ada lovelaceprint(name.upper())
结果:ADA LOVELACEprint(name.lower())
结果:ada lovelace(较常用,统统先转成小写在存储) -
在字符串中使用变量
first_name="ada"
last_name="lovelace"
full_name=f"{first_name}{last_name}''
print(full_name)
要在字符串中插入变量的值,可在前引号前加入字母f,再将要插入的变量放在花括号内,这样,当Python显示字符串时,将每个变量都替换为其值。,这种字符串名为f字符串,f是format缩写。由此可以完成很多工作。(注意,f字符串是Python3.6引入的,对于之前的版本,
full_name="{}{}".format(first_name,last_name)
-
使用制表符或换行符来添加空白
在编程中,空白泛指使用任何非打印字符,如空格,制表符或换行符。
空白:\t(制表符)
换行:\n(换行符)
反斜杠:\
单引号:\ ’
双引号:\ "
-
取子串
若s=“Hello Bob”
s[0:3]是‘Hel’
s[:]是‘Hello Bob’
-
也可以用+号直接连接
-
一个字符串的重复连接,用乘*
-
字串检测,用in
-
注意,字符串不可修改
-
ord函数可以返回字符的编码
ord(‘a’)=97
ord(‘\xc4’)=196,这里\x表示16进制。
print(‘\xc4) 结果为A上带两点
-
eval()函数将字符串当作数值表达式计算
-
str()函数自动将计算结果转成字符串
-
String库内也有很多字符串函数
删除空白
自动剔除字符串末尾空白:
favorite_language.ratrip()
自动剔除字符串开头空白:
favorite_language.lstrip()
自动剔除字符串首尾空白:
frvorite_language.strip()
数
在Python中,可用**表示乘方运算,将任意两个数相除时,结果总是浮点数,即使这两个都是整数且能整除。
书写很大的数时,可使用下划线将其中的数字分组,使其更清晰已读,当你打印这种数时,Python 不会打印其中的下划线。(Python>=3.6)
同时给多个变量赋值:
x,y,z=0,0,0
常量:Python没有内置的常量类型,但Python程序员会使用全大写来指出应将某个变量视为常量,其值应该始终保持不变
MAX_CONNECTIONS=5000
注释
Python语言中使用井号做注释标识,井号后面的内容会被Python解释器自动忽略,
#向大家问好
彩蛋
Python之禅:
import this
-
第三章:列表
列表由一系列特定顺序排列的元素组成,如下
bicycles=['track','cannodale','redline','specialized']
print(bicycles)
结果如下
['track','cannodale','redline','specialized']
Python将打印列表的内部表示,包括方括号。
访问列表元素,只需告诉该元素的位置(索引),当然需要特别注意的是索引从0开始而非1开始,且Python为访问最后一个元素提供了一种方法,就是直接用-1去索引。
print(bicycles[1])
当然,也可以同时调用那几个对字符串处理的函数title()等。
你可以像使用其他变量的值一样使用列表中的各个值,例如使用f组成一个新的字符串。
如何修改列表元素呢?
修改:对特定索引元素直接进行重新赋值即可
添加:1. 列尾(对空列同样适用)例如:
motorcyles=[]
motorcyles.append('homda')
motorcyles.append('ymaha')
motorcyles.append('suzuki')
结果不言自明(注意方括号也是会输出的)
插入,使用函数insert(),如下
motorcyles.insert(0,'ducati')
删除:知道元素索引,可以使用del语句,例如 del motorcyles[0]
知道元素索引且需要将这个元素单独拿出来,用pop()即出栈的方法,如果不指定索引则默认弹出列尾元素。
popped_motorcyles=motorcyles.pop()
first_owned=motorcyles.pop(0)
根据值去删除元素,用remove函数
motorcyles.remove('ducati')
,注意函数remove()只删除第一个指定的值,如果要删除的值在表中可能出现多次,则可以 使用循环。
如何对列表进行排序
-
按照字母排列
cars=['bmw','audi','toyota','subaru']
cars.sort()
按照字母反序排列
cars.sort(reserve=True)
注意这是对列表元素顺序的永久修改
-
使用函数sorted对列表临时排序
要保留列表元素原来的排列顺序,同时以特定的顺序呈现他们,可使用函数sorted()
-
使用函数reserve来使列表倒序
cars.reserve()
注意这样是永久修改的,当然你可以随时再次用这个函数使其倒回去
-
使用函数len来确定列表的长度
cars.len()
第四章:操作列表
-
遍历整个列表
magicians=['alice','david','carolina']
for magician in magicians:
print(magician)
-
特别注意,在for循环中,只有for循环下缩进的语句才会循环执行
-
避免缩进错误!(4个空格缩进)
-
忘记缩进
-
忘记缩进额外的代码行
-
不必要的缩进
-
循环后不必要的缩进
-
for循环语句遗漏了:
-
-
创建数值列表(数组)
-
使用函数range()
for vaule in range(1,5)
print(vaule)
结果
1
2
3
4
为什么没有打印5呢?这是编程语言中常见的差一行为,函数range到达指定的第二个值时停止,因此不执行print(5)
调用函数range()时,也可只指定一个参数,这样他将从0开始。
-
使用range创建数值列表
numbers=list(range(1,6))
print(numbers)
结果如下
[1,2,3,4,5]
-
range指定步长
even_numbers=list(range(2,11,2))
print(even_numbers)
结果
[2,4,6,8,10]
-
对数值列表的初步统计
digits=[1,2,3,4,5,6,7,8,9,0]
min(digits)
max(digits)
sum(digits)
-
列表解析
squares=[value**2 for value in range(1,11)]
print(square)
结果
[1,4,16,25,36,49,64,81,100]
-
列表切片
players=['charles','martina',michael','florence','eli']
print(players[0:3])
其实可以指定三个参数,第一个起始位(可略,头),第二个终止位(可略,尾),第三个是步长
-
遍历切片
使用for循环实现
-
复制列表
方法:同时省略起始索引和终止索引
特别注意如果这样
friend_foods=my_foods
这是错的,这里将后面直接赋给前面,而不是将后面的副本赋给前面,因此这两个变量指向同一个列表。
-
元组
列表是可以变动的,而元组是不可以变动的列表,元组看起来很像列表,但是使用圆括号而非中括号来标识。
dimensions=(200,50)
遍历元组中的所有值
dimensions=(200,5)
for dimension in dimensions:
print(dimension)
虽然不能修改元组的元素,但可以给存储元素的变量赋值,即重新赋值覆盖一遍
-
第五章:if语句
示例:
`cars = ['audi','bmw','subaru','toyota']
for car in cars:
if car == 'bmw'
print(car.upper())
else:
print(car.title())`
1. 条件测试
car = 'audi'
car == 'bmw'
结果
False
当然,这是需要区分大小写的,不等为!=,>,<,>=,<=
也可以使用and和or检查多个条件
检查特定值是否表示在列表中,in
'mushrooms' in requested_toppings
当然,可以用 not in判断不在
布尔表达式
-
IF 语句
if-elif-else语句
注意可以使用多个elif语句,也可以省略else语句
-
用if语句处理列表
requested_toppings=[]
if requested_toppings:
这里if会做检查,如果是空的,返回False,非空返回True
基本就是语言的基本if操作
第六章:字典
一个简单的字典如下
alien_0={'color':'green', 'point':5}
print(alien_0['color'])
print(alien_0['points'])
大概就是查字典吧
在Python中,字典用放在花括号{}中的一系列键值对表示。
访问字典中的值,可依次指定字典名和放在方括号内的键
-
添加键值对
alien_0['x_position']=0
alien_0['y_position']=0
用花括号创建新字典
alien_0={}
-
修改字典中的值
alien_0['color']='yellow'
-
删除键值对
del alien_0['points']
-
由类似对象组成的字典
favorite_languages={
'jen': 'python',
'sarah': 'c',
'edward': 'ruby',
'phil': 'python',
}
-
使用get()来访问值
如果直接用键取访问字典而对应的键值不一样时,系统会报错。
为了避免这样,可以使用方法get()在指定键不存在时返回一个默认值。
方法get()的第一个参数用于指定键,是必不可少的;第二个参数为指定的键不存在时要返回的值,是可选的。
point_value=alien_0.get('points','No point vaule assign.')
-
遍历字典
-
用for循环去遍历
for key,value in user 0.item():
print(f"\nKey: {key}")
print(f"Value: {value}")
注意这里的循环变量名字是任意指定的,只需要保证有两个循环变量即可,如可以是name和age
-
遍历字典中的所有键
在不需要使用字典的值时,方法Keys()很有用。
for name in favorite_languages.keys():
print(name.title())
遍历字典时,如果使用
for name in favorite_languages:
输出将不变,即单变量循环默认为值,当然,显式地使用方法keys()可让代码更容易理解
方法Keys()并非只能用于遍历,实际上,它返回一个列表,其中包含字典中的所有键。
-
按照特定循序遍历字典中的所有键
从Python3.7起,遍历字典时将按插入的循序返回其中的元素。
要以特定循序返回元素,一种办法是在for循环中对返回的键进行排序,为此,可使用函数sorted()来获取对特定顺序排列的键列表副本:
for name in sorted(favorite_languages.keys()):
print(f"{name.title()}, thank you for taking the poll.")
这里就是对keys()返回的列表,并用sorted()方法进行按照首字母排序
-
遍历字典中的所有值,可以使用方法values()
最粗暴的做法是这样的
for language in favorite_languages.values():
print(language.title())
这条for语句提取字典中的所有值,并将其一次赋值给变量language,这种做法提取字典中的所有值,而没有考虑是否重复,为了剔除重复项,可以使用集合(set),集合中的每个元素都是独一无二的。
for language in set(favorite_languages.values()):
通过更深入的学习Python,你会发现它内置的功能可以帮助你以希望的方式处理数据。
-
可以用一对花括号直接创建集合,并在其中用逗号分隔元素:
>>>language = {'python', 'ruby', 'python', 'c'}
>>>languages
{'ruby','python','c'} #输出结果
集合和字典很容易混淆,因为他们都是用一对花括号定义的,当花括号中没有键值对时,定义的很可能是集合,不同于列表和字典,集合不会以特定顺序存储元素。
-
嵌套
将一系列字典存储在列表中,或将列表作为值存储在字典中,这称为嵌套
字典alien_0包含了一个外星人的各种信息,但无法存储第二个外星人的各种信息,更别说屏幕上所有外星人的基本信息了,一种办法是创建一个外星人列表,其中每个外星人都有一个字典,包含有关该外星人的所有信息,如下
aliens = [alien_0,alien_1,alien_2]
for alien in aliens:
print(alien) #结果将会将三个外星人的字典完整打印出来
进一步地,可以使用for循环等自动生成这些东西
# 创建一个用于存储外星人的空列表
aliens = []
# 创建30个绿色的外星人、
for alien_number in range(30)
new_alien = {'color': 'green', 'points': '5', 'speed': 'slow'}
aliens.append(new-alien)
# 显示前5个外星人
for alien in aliens[:5]:
print(alien)
print("...")
# 显示创建了多少外星人。
point(f"Total number of aliens: {len(aliens)}")
经常需要在列表中包含大量的字典,而其中每个字典都包含特定对象的众多信息。例如,你可能需要为网站的每个用户创建一个字典,并将这些字典存储在一个名为users的列表中,在这个列表中,所有字典的结构都相同,因此你可以遍历这个列表,并以相同的方式处理每个字典。
-
在字典中存储列表
pizza = {
'crust': 'thick',
toppings': ['mushrooms', 'extra cheese'],
}
每当字典中将一个键关联到多个值时,都可以在字典中嵌套一个列表,在本章前面有关喜欢的编程语言的示例中,如果将每个人的回答都存储在一个列表中,被调查者就可以选择多种自己喜欢的语言,在这种情况下,当我们遍历字典时,与每个被调查者相关联的都是一个语言列表。因此,在遍历该字典for循环中,我们需要再使用一个for循环来遍历与被调查者相关联的语言列表。
-
在字典中存储字典
例如,如果有多个网站用户,每个都有独特的用户名,可在字典中将用户名作为键,然后将每位用户的信息存储在一个字典中。
users = {
'asinstein': {
'first': 'albert',
'last': 'einstein',
'location': 'princeton',
},
'mcurie': {
'first': 'marie',
'last': 'curie',
'location': 'paris',
},
}
请注意,表示每位用户的字典都具有相同结构,虽然Python语言没有这样的要求,但这使得更嵌套的字典处理起来更容易。
-
第七章:用户输入和while循环
-
函数input()的工作原理
函数input()让程序暂停运行,等待用户输入一些文本,获取用户输入后,Python将其赋给一个变量,例如
message = input("Tell me something, and i will repeat in back to you: ")
每当使用函数input()时,都应指定清晰易懂的提示,准确地指出希望用户提供什么样的信息。
有时候提示可能会超过一行,此处我们给出创建多行字符串的方法
prompt = 'If you tell us who you are, we can personalize the messages you see.'
prompt += "\nWhat is your first name"
2. 使用int()来获取数值输入
使用input()时,Python将用户输入解读为字符串,例如
>>>age = intput("How old are you?")
How old are you? 21
>>> age
‘21’
如果试图将输入作为数来使用,就会引发错误
为了解决这个问题,可以用int(),函数int()将输入字符串转变为数值表示,如下
实际上是强制类型转换
3. 求模运算符%
将两个数相除并返回余数
4. 整除运算符//
将两个数执行除法,对结果舍去小数部分,注意结果可能不为整数,可能与分子相关
5. While循环简介
样例
current_number = 1
while current_number <= 5
print(current_number)
current_number +=1
人工指定是否退出循环
while message != 'quit':
message = input(prompt)
print(message)
使用标志Flag
active = True
while active:
message = input(prompt)
if message == ‘quit’:
active = False
else:
print(message)
使用break强制退出循环
在循环中使用continue跳过当前循环
避免无限循环,如果实在发生的无限循环,可以使用Ctrl+C强制停止
6. 使用While循环处理列表和字典
for循环是一种遍历列表的有限方式,但不应该在for循环中修改循环列表,否则将导致Python难以跟踪其中的元素,要在遍历列表的同时对其进行修改,可使用While循环。
-
样例,在列表中移动元素
*假设有一个列表包含新注册但还未验证的网站用户,验证这些用户后,如何将他们移到另一个已验证的用户列表中?一种方法是使用Whi了循环,在验证用户的同时将其从为验证用户列表中提取出来,再将其加入另外一个已验证用户列表中。例如
# 首先,创建一个待验证用户列表
# 和一个用户存储已验证用户的空列表
unconfirmed_users = ['alice', 'brain', 'candace']
confirmed_users = []
# 验证每个用户直至没有未验证用户为止
# 将每个经过验证用户都移动到已验证用户列表
while unconfirmed_users:
current_user = unconfirmed_user.pop()
print(f"Verifying user: {current_user.title()}"
confirmed_users.append(current_user)
# 显示所有已验证用户
print("\nThe following users have been confirmed:")
for confirmed_user in confirmed_users:
print(confirmed_user.title())
-
删除为特定值的所有列表元素
while循环+remove语句
-
使用用户输入来填充字典
# 提示输入被调查者的名字和回答
name = input("\nWhat is your name?")
response = input("Which mountain would you like to climb someday?")
# 将回答存储在字典中
responses[name] = response
-
第八章:函数
函数是带名字的代码块,用于完成具体的工作,要执行函数定义的特殊任务,可调用该函数,需要在程序中多次执行同一项任务。
-
定义函数
def greet_user()
print("Hello!")
great_user()
-
向函数传递信息(传参)
def greet_user(username)
-
实参和形参
调用函数时,将实参传给了函数,这个在调用时被赋值给了形参
-
传递实参
函数定义中可能需要包含多个形参,因此函数调用中也可能包含多个实参,向函数传递实参的方式很多,可以用位置实参,这要求实参和形参的顺序相同;也可以使用关键字实参,其中每个实参都由变量名和值组成;还可以使用列表和字典,具体如下
-
位置实参
def describe_pet(animal_type, pet_name):
# 调用如下
describe_pet('hamster', 'harry')
-
关键字实参
关键字实参是传递给函数的名称值对,因为直接在实参中将名字和值关联起来,所以向函数传递实参时不会混淆,关键字实参让你无需考虑函数调用中的实参顺序(位置实参:勿cue),还清楚地指出了函数调用中各个值的用途
describe_pet(animal_type='hamster', pet_name='harry')
-
默认值
编写函数时,可以给每个形参指定默认值,例如
def describe_pet(pet_name, animal_type='dog'):
如果显示给定了实参,Python将自动忽略形参默认值。
-
等效的函数调用
对前面那些语法进行综合使用,合法合理即可
-
避免实参错误
返回值
-
返回返回值
-
让实参变成可选的,方法是在函数接收入实参后做一个判断,如果是空的怎么怎么样,如果是非空的怎么怎么样
-
返回字典
-
结合使用函数和while循环
-
传递列表
-
在函数中修改列表
-
禁止函数列表
只让原来的列表传递副本,其实就是临时拷贝一份
function_name(list_name[:])
-
传递任意数量的实参
def make_pizza(*toppings)
:形参名*toppings中的星号让Python创建一个名为toppings的空元组,并将收集到的所有信息封装在这个空元组中。
-
结合使用位置实参和任意数量实参
def make_pizza(size,*toppings)
-
使用任意数量的关键字实参
def build_profile(first,last,**user_info):
形参名**user_info中的两个星号让Python创建一个名为user_info的字典
-
将函数存储在模块中
新建一个py文件,只写入函数的代码
在其它文件夹中导入该模块即可 import pizza
还有一种是导入特定的函数
from module_name import fuction_name
从什么模块导入什么函数
使用as给函数拟定别名
from module_name import pizza as good
使用as给模块拟定别名
import module_name as good
导入模块中的所有函数:from pizza import *(不推荐)
-
第九章:类
-
创建类和使用类
class Dog:
def _init_(self,name,age):
当然,带默认值是可以的,直接更新属性的值(或者使用方法(函数)更新))
-
继承
编写类时并非总是要从空白开始,如果要编写的类是另一个现成类的特殊版本,可以使用继承。父类和子类
class ElectricCar(Car):
与正常类的定义区别就是多了一个括号和父类名,使用继承时父类必须包含在文件中且在子类前面,然后记得加上super()./init /(make,modle,year)
先初始化父类的属性,再初始化子类特有的属性
可以在子类中重写父类的方法,也就是同函数名直接覆盖
将实例作用于属性,实际上就是组合,在一个类中包含另外一个类
模拟实物,从较高的实物层面去划分这个世界
-
导入类
专门开一个文件用来存放py代码即可,也可以在一个文件中存储多个类,一次性从一个模块中导入多个类,还可以导入整个模块,导入模块的所有类,在一个模块中导入另外一个模块,使用别名,还有必要的Python标准库
第十章: 文件和异常
-
读取文件
with open('pi_digits.txt') as file_object:
contents = file_object.read()
prints(contents)
有open()函数也有close()函数
注意,read()到达文件末尾时会多出来一个空行,可以使用rstrip()方法
注意文件路径问题
使用for循环逐行读取
with open(filename) as file_object:
注意,这里使用read()函数后每行结束后会多出来一个空格
读取文本文件时,Python将其中所有的文本都解读为字符串.
经典项目:圆周率包括你的生日吗?
for line in lines:
pi_string += line.strip()
birthday = input("Enter your birthday,in the form mmddyy: ")
if birthday in pi_string:
print ......
else:
print......
-
写入文件
要将文本写入文件,你在调用open()时需要提供另一个实参,告诉Python你要写入打开的文件
with open(filename,'w') as file_object
w写入模式,a是附加模式,r+是读写模式
写入多行需要自己准备换行符
使用附加模式添加到文件末尾
-
异常
使用try-except方法,pass语句
-
存储数据
json.load,json.jump
-
代码重构
第十一章:测试代码
-
测试函数
单元测试和测试用例
导入模块unittest和要测试的函数,再创建一个继承unittest.Testcase的类,并编写一系列方法对函数行为进行不同方面的测试
各种断言方法及其使用