Pref 逢居家懈怠,为缓解焦虑,更好利用空闲时间,启动容易上手的 python3 学习!另,我已有 C 的基础,故一些相同知识点会略过。
注释 # 注释''' """ 多行注释,文档字符串#coding=utf-8 或 #coding=gbk 中文注释
字符串 字符串连接 'a' + 'b''a' * 5
print() 返回 None 值
title() 首字母大写
istitle() 返回布尔值,字符串只包含首字母大写
isalpha() 字符串只包含字母
startswith()
join() 参数是一个字符串列表。
1 2 ' ' .join(['My' , 'name' , 'is' , 'Simon' ])'My name is Simon' 
split() 默认以空格为分隔符拆分字符串,返回一个列表
ljust() 左对齐
strip() 删除首尾空白,第二参数可选指定字符删除,字符顺序不重要
1 2 3 spam = 'SpamSpamBaconSpamEggsSpamSpam'  spam.strip('ampS' ) 'BaconSpamEggs' 
u r b f 前缀 u「Unicode」以 Unicode 格式进行编码,常用于中文字符串
1 2 3 4 first_name = "ada"  last_name = "lovelace"  full_name = f"{first_name}  {last_name} "   print(full_name) 
bytes 和 str 互相转换 1 2 str .encode('utf-8' )bytes .decode('utf-8' )
正则表达式 regex 正则表达式的函数都在 re 模块
创建对象 re.compile() 传入一个字符串值,表示正则表达式,返回一个 Regex 模式对象。
匹配对象 search() group() 方法 Regex 对象的 search(),未找到返回 None;找到返回一个 Match 对象。
Match 对象的 group(),返回被查找字符串中实际匹配的文本。
1 2 3 phoneNumRegex = re.compile (r'\d{3}-\d{3}-\d{4}' ) mo = phoneNumRegex.search('My number is 415-555-4242.' ) print('Phone number found: '  + mo.group()) 
括号分组 向 group() 传入整数 1 等,取得匹配文本的不同分组;传入 0 或无参数,返回整个匹配文本。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 phoneNumRegex = re.compile (r'(\d\d\d)-(\d\d\d-\d\d\d\d)' ) mo = phoneNumRegex.search('My number is 415-555-4242.' ) mo.group(1 ) '415' mo.groups() ('415' , '555-4242' ) areaCode, mainNumber = mo.groups() print(areaCode) 415 phoneNumRegex = re.compile (r'(\(\d\d\d\)) (\d\d\d-\d\d\d\d)' ) 
管道匹配多个分组 | 返回第一次出现的匹配文本 1 2 3 4 heroRegex = re.compile  (r'Batman|Tina Fey' ) mo1 = heroRegex.search('Batman and Tina Fey.' ) mo1.group() 'Batman' 
只指定一次前缀 1 2 3 4 5 6 7 batRegex = re.compile (r'Bat(man|mobile|bat)' ) mo = batRegex.search('Batmobile lost a wheel' ) mo.group() 'Batmobile' mo.group(1 ) 'mobile' 
问号匹配零次或一次 指代字符之前的分组,下同。
1 2 3 4 5 6 7 8 batRegex = re.compile (r'Bat(wo)?man' ) mo1 = batRegex.search('The Batman' ) mo1.group() 'Batman' mo2 = batRegex.search('The Batwoman' ) mo2.group() 'Batwoman' 
星号匹配零次或多次 1 2 3 4 batRegex = re.compile (r'Bat(wo)*man' ) mo3 = batRegex.search('The Batwowowowoman' ) mo3.group() 'Batwowowowoman' 
加号匹配一次或多次 1 2 3 4 batRegex = re.compile (r'Bat(wo)+man' ) mo3 = batRegex.search('The Batman' ) mo3 == None  True 
花括号匹配特定次数 一个数字,或指定一个范围(最小值,最大值)或不限定最值之一。
(Ha){3} 匹配字符串 ‘HaHaHa’。
(Ha){3,5} 匹配 ‘HaHaHa’、’HaHaHaHa’、’HaHaHaHaHa’。
贪心和非贪心匹配 Python 的 Regex 默认是贪心的,表示在有二义的情况下,它们会尽可能匹配最长的字符串。
1 2 3 4 nongreedyHaRegex = re.compile (r'(Ha){3,5}?' ) mo = nongreedyHaRegex.search('HaHaHaHaHa' ) mo.group() 'HaHaHa 
findall() 方法 包含被查找字符串中的所有匹配。不是返回一个 Match 对象。
1 2 3 4 5 6 7 phoneNumRegex = re.compile (r'\d\d\d-\d\d\d-\d\d\d\d' ) phoneNumRegex.findall('Cell: 415-555-9999 Work: 212-555-0000' ) ['415-555-9999' , '212-555-0000' ] phoneNumRegex = re.compile (r'(\d\d\d)-(\d\d\d)-(\d\d\d\d)' ) phoneNumRegex.findall('Cell: 415-555-9999 Work: 212-555-0000' ) [('415' , '555' , '1122' ), ('212' , '555' , '0000' )] 
字符分类 
缩写字符 
表示 
 
 
\d 
任何一位数字 
 
\D 
除 0-9 以外的任何字符 
 
\w 
任何字母、数字或下划线字符 
 
\W 
除字母、数字和下划线以外的任何字符 
 
\s 
空格、制表符或换行符「匹配空白」 
 
\S 
除空格、制表符和换行符以外的任何字符 
 
自定义字符分类 [] [a-zA-Z0-9] 匹配所有小写、大写字母和数字。
方括号内,普通的正则表达式符号不会被解释,不需要转义。
非字符类 ^ 匹配不在这个字符类中的所有字符。
consonantRegex = re.compile(r'[^aeiouAEIOU]')
开始字符 ^ 结束字符 $ 开始处用插入符号 ^,表明匹配必须发生在被查找文本开始处。$,表示该字符串必须以这个 Regex 的模式结束。r'^\d+$' 匹配从开始到结束都是数字的字符串。
1 2 3 4 5 6 7 beginsWithHello = re.compile (r'^Hello' ) beginsWithHello.search('Hello world!' ) <re.Match object ; span=(0 , 5 ), match='Hello' > endsWithNumber = re.compile (r'\d$' )  endsWithNumber.search('Your number is 42' ) <re.Match object ; span=(16 , 17 ), match='2' > 
通配符 . 匹配除换行外所有字符,只匹配一个字符 1 2 3 atRegex = re.compile (r'.at' ) atRegex.findall('The cat in the hat sat on the flat mat.' ) ['cat' , 'hat' , 'sat' , 'lat' , 'mat' ] 
.* 匹配除换行外所有字符 1 2 3 4 nameRegex = re.compile (r'First Name: (.*) Last Name: (.*)' ) mo = nameRegex.search('First Name: Alice Last Name: Sweigart' ) mo.group(1 ) 'Alice' 
.* 贪心模式。.*? 非贪心模式。
1 2 3 4 5 6 7 8 9 greedyRegex = re.compile (r'<.*>' ) mo = greedyRegex.search('<To serve man> for dinner.>' ) mo.group() '<To serve man> for dinner.>' nongreedyRegex = re.compile (r'<.*?>' ) mo = nongreedyRegex.search('<To serve man> for dinner.>' ) mo.group() '<To serve man>' 
re.DOTALL 匹配换行 1 2 3 NewlineRegex = re.compile ('.*' , re.DOTALL)  NewlineRegex.search('First\nSecond\nThird' ).group() 'First\nSecond\nThird' 
re.IGNORECASE 不区分大小写匹配 传入 re.IGNORECASE 或 re.I 作为 re.compile() 第二个参数。
sub() 方法替换字符串 Regex 对象的 sub() 传入两个参数。返回替换后的字符串。
1 2 3 namesRegex = re.compile (r'Agent \w+' ) namesRegex.sub('CENSORED' , 'Agent Alice gave the documents to Agent Bob.' ) 'CENSORED gave the documents to CENSORED.' 
使用匹配的文本本身,作为替换的一部分。sub() 第一个参数中输入 \1、 \2 表示输入分组 1、2 的文本。
字符串中的 \1 将由分组 1 匹配的文本所替代,即 (\w) 分组。
1 2 3 agentNamesRegex = re.compile (r'Agent (\w)\w*' )  agentNamesRegex.sub(r'\1****' , 'Agent Alice told Agent Carol.' ) A**** told C****. 
管理复杂的正则表达式 忽略正则表达式字符串中的空白符和注释。re.compile() 传入变量 re.VERBOSE,作为第二参数。
难以阅读:
1 phoneRegex = re.compile (r'((\d{3}|\(\d{3}\))?(\s|-|\.)?\d{3}(\s|-|\.)\d{4}(\s*(ext|x|ext.)\s*\d{2,5})?)' ) 
多行书写,加上注释:
1 2 3 4 5 6 7 8 phoneRegex = re.compile (r'''(  (\d{3}|\(\d{3}\))? # area code (\s|-|\.)? # separator \d{3} # first 3 digits (\s|-|\.) # separator \d{4} # last 4 digits (\s*(ext|x|ext.)\s*\d{2,5})? # extension )''' , re.VERBOSE)
1 someRegexValue = re.compile ('foo' , re.IGNORECASE | re.DOTALL | re.VERBOSE) 
数 
数学操作符 
操作「优先级从高到低」 
 
 
** 
指数 
 
% 
取模 
 
// 
整除 
 
/ 
除 
 
* 
乘 
 
- 
减 
 
+ 
加 
 
int()
类假值 0、0.0 和 ' '(空字符串)被认为是 False
大数 - 下划线分组 1 2 3 universe_age = 14_000_000_000  print(universe_age) 14000000000 
多变量赋值 变量名 
只能包含字母、数字和下划线  
不能以数字开头 
区分大小写,常用小写  
 
常量,全大写 表示(无内置常量类型)
列表 列表名用复数 
[['a','b'],'c'] 可嵌套
子列表副本 [:] 访问最后一个元素 [-1] 列表连接 + 复制 * 方法 返回值是 None,方法属于单个数据类型,只能在列表上调用。
index() 在列表中查找值
传入一个值,存在于列表中,就返回下标;不在就报 ValueError;有重复只返回第一次出现的下标。
1 2 spam = ['hello' , 'hi' , 'howdy' ] spam.index('hello' ) 
append() 列表末添加元素,只能一个
del bicycles[0] 仅删除元素
sort(reverse=True) 字母顺序排序(逆序)spam.sort(key=str.lower),sort() 将列表中所有的表项当成小写。
sorted() 临时字母顺序排序,不改变原列表
非所有元素值是小写时,按字母顺序排列列表变复杂。
 
reverse() 逆序
可变和不可变数据类型 字符串可看作是单个文本字符的列表 ,列表相关操作也用于字符串。
1 2 name = 'Zophie a cat'  newName = name[0 :7 ] + 'the'  + name[8 :12 ] 
遍历 1 2 3 cats = ['alice' , 'david' , 'carolina' ] for  cat in  cats:    print(cat) 
迭代 1 2 3 spam = ['a' , 'b' , 'c' ] for  i in  range (len (spam)):    print(str (i) + ' in spam is '  + spam[i]) 
多重赋值技巧 列表的值为多个变量赋值,变量数目和列表长度必须严格相等。
1 2 cat = ['fat' , 'black' , 'loud' ] size, color, disposition = cat 
range(5) 生成数值 0-4
list() 返回传递值的列表版本 
tuple() 返回传递值元组版本 
 
1 2 3 4 5 6 numbers = list (range (1 , 6 )) print(numbers) [1 , 2 , 3 , 4 , 5 ] list ('hello' ) ['h' , 'e' , 'l' , 'l' , 'o' ] 
列表解析 1 2 3 4 5 6 7 8 9 squares = [] for  value in  range (1 , 4 ):    squares.append(value**2 ) print(squares) squares = [value**2  for  value in  range (1 , 4 )] print(squares) 
切片 1 2 players = ['charles' , 'martina' , 'alice' ] print(players[0 :2 ])  
复制列表 1 2 my_foods = ['pizza' , 'falafel' , 'cake' ] friend_foods = my_foods[:] 
元组 tuple:值不可变的列表,可优化比列表快 
注:元组是由逗号标识的,圆括号只是方便区分;若定义只包含一个元素的元组,必须在这个元素后面加上逗号。
 
1 2 3 4 dimensions = (200 , 50 ) for  dimension in  dimensions:    print(dimension) dimensions = (400 , 100 ) 
if 语句 在所有算术、比较操作符求值后,依次求值布尔操作符 not,and,or
1 2 (age_0 >= 21 ) and  (age_1 >= 21 ) 
1 2 3 dogs = ['alice' , 'tom' ] 'tom'  in  dogs'jam'  not  in  dogs
1 2 3 4 5 6 7 8 9 10 11 age = 12  if  age < 4 :    price = 0  elif  age < 18 :    price = 25  else :     price = 40  print(f"Price is ${price} ." ) 
字典 1 2 3 4 5 6 7 8 9 10 11 12 13 14 alien = {}  alien = {'color' : 'red' }  aline = {     'color' : 'red' ,     'point' : '3' ,      } alien['point' ] = 5   print(alien) alien['point' ] = 3   del  alien['color' ] print(speed['fast' ])  speed_value = alien.get('speed' , 'No speed value assigned.' )  
遍历所有键值对 items() 1 2 3 for  key, value in  alien.items():     print(f"\nkey: {key} " )     print(f"value: {value} " ) 
这些数据类型(dict_keys、dict_values、dict_items)可用于 for 循环,不能被修改。
遍历所有键 keys() 1 2 3 for  key in  alien: for  key in  alien.keys():     print(key) 
按特定顺序遍历所有键 sorted() 1 for  key in  sorted (alien.key()):
遍历所有值 values() 1 2 for  value in  alien.values():     print(value) 
无重复遍历所有值 set() 1 for  value in  set (alien.values()): 
不同于列表和字典,集合不会以特定的顺序存储元素
 
多重赋值技巧 在 for 循环中将键和值赋给不同的变量
1 2 3 spam = {'color' : 'red' , 'age' : 42 } for  k, v in  spam.items():    print('Key: '  + k + ' Value: '  + str (v))  
某键设置默认值 setdefault() 两参数:检查并为字典中某键设置一个默认值;
while 循环 input() 接受一个参数做 prompt,提示输入内容,返回字符串
Ctrl + C 向程序发送 KeyboardInterrupt 错误,退出无限循环
一般循环 1 2 3 4 5 6 7 8 prompt = "\nTell me something: "  prompt += "\nEnter 'q' to quit."  msg = ""  while  msg != 'q' :    msg = input (prompt)     if  msg != 'q' :         print(msg) 
标志循环 1 2 3 4 5 6 7 8 active = True  while  active:    msg = input (prompt)     if  msg == 'q' :         active = False      else :         print(msg) 
break 1 2 3 4 5 6 while  True :    msg = input (prompt)     if  msg == 'q' :         break      else :         print(msg) 
continue 1 2 3 4 5 6 7 n = 0  while  n < 10 :    n += 1      if  n % 2  == 0 :          continue      print(n) 
在列表间移动元素 1 2 3 4 5 6 7 8 names = ['alice' , 'brian' ] new_names = [] while  names:    temp = names.pop()     new_names.append(temp) for  new_name in  new_names:    print(new_name) 
删除为特定值的所有列表元素 1 2 3 4 5 pets = ['dog' , 'cat' , 'dog' , 'cat' , 'rabbit' , 'cat' ] while  'cat'  in  pets:    pets.remove('cat' ) print(pets) 
使用用户输入来填充字典 1 2 3 4 5 6 7 8 9 10 11 responses = {} while  True :    name = input ("\nname: " )     response = input ("response: " )     responses[name] = response     repeat = input ("Enter anything to continue or 'n' to quit." )     if  repeat == 'n' :         break  for  name, response in  responses.items():    print(f"{name} : {response} " ) 
函数 形参 parameter
实参 1 2 3 4 5 6 7 8 9 10 11 12 13 def  user_age (name, age ):    print(f"{name} : {age} " ) user_age('Tom' , '18' )  user_age(name='Tom' , age='18' )  def  user_age (name, age='18'  ):def  user_age (name, age, gender=''  ):    if  gender:         user = f"{name}  {age}  {gender} "      else :         user = f"{name}  {age} "      return  user 
print() 有可选变元 end 和 sep,分别指定在参数末尾打印什么,在参数之间用什么隔开print('Hello', end='') 禁用换行
返回字典 1 2 3 4 5 6 7 8 9 def  build_person (first_name, last_name, age=None  ):    person = {'first' : first_name, 'last' : last_name}     if  age:         person['age' ] = age     return  person user = build_person('tom' , 'antonio' , age=18 ) print(user) 
传递列表 1 2 3 4 5 6 7 def  users (names ):    for  name in  names:         msg = f"Hello, {name.title()} !"          print(msg) usernames = ['hannah' , 'ty' , 'margot' ] users(usernames) 
在函数中修改列表 1 2 3 4 5 6 7 8 9 10 11 12 13 14 def  change (usernames, new_usernames ):    while  usernames:         temp = usernames.pop()         new_usernames.append(temp) def  show (new_usernames ):    for  new_username in  new_usernames:         print(new_username) usernames = ['hannah' , 'ty' , 'margot' ] new_usernames = [] change(usernames, new_usernames) show(new_usernames) 
禁止函数修改列表,[:] 创建列表副本 1 change(usernames[:], new_usernames) 
传递任意数量的实参 1 2 3 4 5 6 7 8 def  make_pizza (size, *toppings ):    print(f"size: {size} " )     for  topping in  toppings:         print(f"{topping} " ) make_pizza(6 , 'pepperoni' ) make_pizza(8 , 'mushrooms' , 'green peppers' ) 
使用任意数量的关键字实参 1 2 3 4 5 6 7 8 def  build_profile (first, last, **info ):    info['first_name' ] = first     info['last_name' ] = last     return  info profile = build_profile('albert' , 'einstein' , location='princeton' , field='physics' ) print(profile) 
函数模块化及别名 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 '''pizza.py''' def  make_pizza (size, *toppings ):    print(f"size: {size} " )     for  topping in  toppings:         print(f"{topping} " ) def  show ():    print("..." ) '''main.py''' import  pizzapizza.make_pizza(6 , 'pepperoni' ) pizza.make_pizza(8 , 'mushrooms' , 'green peppers' ) from  pizza import  make_pizza, show make_pizza(6 , 'pepperoni' ) from  pizza import  * import  pizza as  p from  pizza import  make_pizza as  mp 
作用域 
类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 ''' 类中函数称为方法,规定双下划线; 调用 __init__ 方法创建 Car 实例,自动传入实参 self, 必须有一个参数位于最前面, 方法是一个指向实例本身的引用,让实例能够访问类中的属性和方法; Car 类创建实例时,只需给其他形参提供值; 前缀为 self 的变量可供类中所有方法使用,可通过任何实例访问; 类看作是如何创建实例的说明。 ''' class  Car :    def  __init__ (self, make, model, year ):         self.make = make          self.model = model         self.year = year         self.odometer = 0       def  info (self ):         name = f"{self.year}  {self.make}  {self.model} "          return  name.title()     def  read_odometer (self ):         print(f"{self.odometer} " )     def  update_odometer (self, mileage ):                  if  mileage >= self.odometer:             self.odometer = mileage         else :             print("Don't roll back an odometer." )     def  increment_odometer (self, miles ):         self.odometer += miles car = Car('audi' , 'a4' , 2019 )  print(f"{car.make} " )  print(car.info()) car.read_odometer()  car.odometer = 20   car.update_odometer(35 )  car.increment_odometer(10 )  
继承 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ''' 创建子类时,父类必须包含在当前文件中,且位于子类前; 父类也称超类(superclass) ''' class  Car :    --snip-- class  EletricCar (Car ):    def  __init__ (self, make, model, year ):         super ().__init__(make, model, year)          self.battery = 100       def  info_battery (self ):         print(f"{self.battery} " )      el_car = EletricCar('tesla' , 'model s' , 2019 ) print(el_car.info()) 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 class  Car :    --snip-- class  Battery :    def  __init__ (self, battery=100  ):         self.battery = battery     def  info_battery (self ):         print(f"{self.battery} " )     def  get_range (self ):         if  self.battery == 100 :             range  = 315          elif  self.battery == 75 :             range  = 260          print(f"{range } " ) class  EletricCar (Car ):    def  __init__ (self, make, model, year ):         super ().__init__(make, model, year)         self.battery = Battery()  el_car = EletricCar('tesla' , 'model s' , 2019 ) print(el_car.info()) el_car.battery.info_battery() 
导入类 1 2 3 4 5 6 7 8 9 '''car.py''' class  Car :    --snip-- class  Battery :    --snip-- class  EletricCar (Car ):    --snip-- 
1 2 3 4 5 6 7 8 '''my_car.py''' from  car import  Car, EletricCar my_car = Car('audi' , 'a4' , 2019 ) print(my_car.info()) my_car.odometer = 23  my_car.read_odometer() 
文件 读取整个文件 - read() 1 2 3 4 5 6 7 8 9 10 11 ''' 函数 open() 返回一个表示文件的对象, 赋给 file_object(只在 with 内可用),用方法 read() 读取; 关键字 with 在不再需要访问文件后将其关闭; close() 关闭文件可能存在各种问题; read() 到达文件尾时返回一个空字符串,表现为空行; 文本文件内容都被解读为字符串。 ''' with  open ('demo.txt' ) as  file_object:    contents = file_object.read() print(contents.rstrip())  
逐行读取 - for 循环 1 2 3 4 5 6 7 8 9 ''' 输出可能每行中间有一个空行, print() 调用有一个换行符,文件本身有一个换行符。 ''' filename = 'demo.txt'  with  open (filename) as  file_object:    for  line in  file_object:         print(line.rstrip()) 
创建包含文件各行内容的列表 - readlines() 1 2 3 4 5 6 filename = 'demo.txt'  with  open (filename) as  file_object:    lines = file_object.readlines()  for  line in  lines:    print(line.rstrip()) 
使用文件内容 - 空字符串 1 2 3 4 5 6 7 8 9 10 filename = 'demo.txt'  with  open (filename) as  file_object:    lines = file_object.readlines() use = ''  for  line in  lines:    use += line.rstrip() print(use) 
写入文件 - write() - rwar+w 1 2 3 4 5 6 7 8 9 10 11 12 13 ''' 读取模式:r 读、w 写、a 附加、r+w 读写; 省略模式实参,默认只读模式打开文件; 写入文件不存在则自动创建,存在则覆盖重写; 只能将字符串写入文本文件。 ''' filename = 'demo.txt'  with  open (filename, 'w' ) as  file_object:    file_object.write('anything' ) with  open (filename, 'a' ) as  file_object:    file_object.write('\naddition' ) 
注:Windows 使用 \ 显示文件路径,但在代码中用 /
 
异常处理 ZeroDivisionError 异常 1 2 3 4 5 6 7 8 9 10 11 ''' python 用特殊对象「异常」来管理程序执行期间发生的错误; 避免用户看到 traceback ''' def  spam (divideBy ):    try :         return  42  / divideBy     except  ZeroDivisionError:        print("You can't divide by zero!" ) print(spam(0 )) 
FileNotFoundError 异常 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 def  count_words (filename ):    try :                           with  open (filename, encoding='utf-8' ) as  f:             contents = f.read()     except  FileNotFoundError:         print(f"Sorry, the file {filename}  does not exist." )     '''      except FileNotFoundError:         pass # 静默失败     '''          else :                  words = contents.split()         num_words = len (words)         print(f"{filename}  has about {num_words}  words." ) filename = 'alice.txt'   count_words(filename) filenames = ['alice.txt' , 'siddhartha.txt' ]  for  filename in  filenames:    count_words(filename) 
存储数据 - json JSON(JavaScript Object Notation)
dump() load() 1 2 3 4 5 6 7 8 9 10 11 12 13 import  jsonnumbers = [2 , 3 , 5 , 7 , 11 , 13 ] filename = 'numbers.json'  with  open (filename, 'w' ) as  f:         json.dump(numbers, f) with  open (filename) as  f:    numbers = json.load(f)  print(numbers) 
保存和读取用户生成的数据 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import  jsonfilename = 'username.json'  try :    with  open (filename) as  f:         username = json.load(f) except  FileNotFoundError:    username = input ("What is your name? " )     with  open (filename, 'w' ) as  f:         json.dump(username, f)         print(f"We'll remember you when you come back, {username} !" ) else :    print(f"Welcome back, {username} !" ) 
重构 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ''' 代码能正确运行,但将其划分为便于改进的一系列完成具体工作的函数,该过程称为重构。 ''' import  jsondef  greet_user ():    """问候用户,并指出其名字。"""      filename = 'username.json'      try :         with  open (filename) as  f:             username = json.load(f)     except  FileNotFoundError:         username = input ("What is your name? " )         with  open (filename, 'w' ) as  f:             json.dump(username, f)             print(f"We'll remember you when you come back, {username} !" )     else :         print(f"Welcome back, {username} !" ) greet_user() 
重构 greet_user() 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 import  jsondef  get_stored_username ():    filename = 'username.json'      try :         with  open (filename) as  f:             username = json.load(f)     except  FileNotFoundError:         return  None      else :         return  username def  get_new_username ():    username = input ("What is your name? " )     filename = 'username.json'      with  open (filename, 'w' ) as  f:         json.dump(username, f)     return  username def  greet_user ():    username = get_stored_username()     if  username:         print(f"Welcome back, {username} !" )     else :         username = get_new_username()         print(f"We'll remember you when you come back, {username} !" ) greet_user() 
测试 模块函数的定义和调用 1 2 3 4 '''name_function.py''' def  get_formatted_name (first, last ):    full_name = f"{first}  {last} "      return  full_name.title() 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 '''names.py''' import  name_functionprint("Enter 'q' at any time to quit." ) while  True :    first = input ("\nfirst name: " )     if  first == 'q' :         break      last = input ("last name: " )     if  last == 'q' :         break      formatted_name = get_formatted_name(first, last)     print(f"\tNeatly formatted name: {formatted_name} ." ) 
单元测试和测试用例 - unittest 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 ''' 运行 test_name_function.py 时, 所有以 test_ 打头的方法都将自动运行。 ''' '''test_name_function.py''' import  unittestfrom  name_function import  get_formatted_nameclass  NamesTestCase (unittest.TestCase ):    def  test_first_last_name (self ):         """能够正确地处理像 Janis Joplin 这样的姓名吗?"""          formatted_name = get_formatted_name('janis' , 'joplin' )                  self.assertEqual(formatted_name, 'Janis Joplin' ) if  __name__ == '__main__' :    unittest.main()  ''' 运行测试文件,输出如下: 第一行句点表明有一个测试通过了; OK 表明该测试用例中的所有单元测试都通过了。 ''' . ---------------------- Ran 1  test in  0.001 s OK 
未通过的测试 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 ''' 使函数能处理中间名,但无法正确处理只有名和姓的情况 ''' '''name_function.py''' def  get_formatted_name (first, middle, last ):    full_name = f"{first}  {middle}  {last} "      return  full_name.title() ''' 运行测试文件,输出如下: 第一行字母 E,指出有一个单元测试导致了错误; 第三行指出 NamesTestCase 中的 test_first_last_name() 导致了错误; Traceback 指出函数调用 get_formatted_name(...) 有问题; 最后指出整个测试用例未通过,因为发生了一个错误。 ''' E ================================ ERROR: test_first_last_name (__main__.NamesTestCase) -------------------------------- Traceback (most recent call last):   File "test_name_function.py" , line 8 , in  test_first_last_name     formatted_name = get_formatted_name('janis' , 'joplin' ) TypeError: get_formatted_name() missing 1  required positional argument: 'last'  -------------------------------- Ran 1  test in  0.001 s FAILED (errors=1 ) 
处理未通过的测试 1 2 3 4 5 6 7 '''name_function.py''' def  get_formatted_name (first, last, middle=''  ):    if  middle:         full_name = f"{first}  {middle}  {last} "      else :         full_name = f"{first}  {last} "      return  full_name.title() 
添加新测试 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 ''' 用于测试包含中间名的姓名 ''' '''test_name_function.py''' --snip-- class  NamesTestCase (unittest.TestCase ):    def  test_first_last_name (self ):         --snip--     def  test_first_last_middle_name (self ):     formatted_name = get_formatted_name('wolf' , 'mozart' , 'amadeus' )     self.assertEqual(formatted_name, 'Wolf Amadeus Mozart' ) if  __name__ == '__main__' :    unittest.main() ''' 第一行句点表明有两个测试通过了…… ''' .. ---------------------- Ran 2  test in  0.001 s OK 
断言方法 unittest 模块中的断言方法,只能在继承 unittest.TestCase 的类中使用这些方法
方法 
用途 
 
 
assertEqual(a, b) 
核实 a == b 
 
assertNotEqual(a, b) 
核实 a != b 
 
assertTrue(x) 
核实 x 为 True 
 
assertFalse(x) 
核实 x 为 False 
 
assertIn(item, list) 
核实 item 在 list 中 
 
assertNotIn(item, list) 
核实 item 不在 list 
 
模块类定义与调用 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 '''survey.py''' class  AnonymousSurvey :    """收集匿名调查问卷的答案。"""      def  __init__ (self, question ):         self.question = question         self.responses = []     def  show_question (self ):         print(self.question)     def  store_response (self, new_response ):         self.responses.append(new_response)     def  show_results (self ):         print("Survey results:" )         for  response in  self.responses:             print(f"- {response} " ) 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 '''language_survey.py''' from  survey import  AnonymousSurveyquestion = "What language did you first learn to speak?"  my_survey = AnonymousSurvey(question) my_survey.show_question() print("Enter 'q' at any time to quit." ) while  True :    response = input ("Language: " )     if  response == 'q' :         break      my_survey.store_response(response) my_survey.show_results() 
测试类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 '''test_survey.py''' import  unittestfrom  survey import  AnonymousSurveyclass  TestAnonymousSurvey (unittest.TestCase ):    def  test_store_single_response (self ):         """测试单个答案会被妥善存储。"""          question = "What language did you first learn to speak?"          my_survey = AnonymousSurvey(question)         my_survey.store_response('English' )         self.assertIn('English' , my_survey.responses)     def  test_store_three_responses (self ):         question = "What language did you first learn to speak?"          my_survey = AnonymousSurvey(question)         responses = ['English' , 'Spanish' , 'Mandarin' ]         for  response in  responses:             my_survey.store_response(response)         for  response in  responses:             self.assertIn(response, my_survey.responses) if  __name__ == '__main__' :    unittest_main() 
方法 setUp() 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 '''test_survey.py''' import  unittestfrom  survey import  AnonymousSurveyclass  TestAnonymousSurvey (unittest.TestCase ):    def  setUp (self ):         """创建一个调查对象和一组答案,供使用的测试方法使用。"""          question = "What language did you first learn to speak?"          self.my_survey = AnonymousSurvey(question)         self.responses = ['English' , 'Spanish' , 'Mandarin' ]     def  test_store_single_response (self ):         self.my_survey.store_response(self.responses[0 ])         self.assertIn(self.responses[0 ], self.my_survey.responses)     def  test_store_three_responses (self ):         for  response in  self.responses:             self.my_survey.store_response(response)         for  response in  self.responses:             self.assertIn(response, self.my_survey.responses) if  __name__ == '__main__' :    unittest_main() 
注:运行测试用例时,每完成一个单元测试,都打印一个字符:
 
关键字 
False 
await 
else 
import 
pass 
 
 
None 
break 
except 
in 
raise 
 
True 
class 
finally 
is 
return 
 
and 
continue 
for 
lambda 
try 
 
as 
def 
from 
nonlocal 
while 
 
assert 
del 
global 
not 
with 
 
async 
elif 
if 
or 
yield 
 
内置函数 
abs() 
delattr() 
hash() 
memoryview() 
set() 
 
 
all() 
dict() 
help() 
min() 
setattr() 
 
any() 
dir() 
hex() 
next() 
slice() 
 
ascii() 
divmod() 
id() 
object() 
sorted() 
 
bin() 
enumerate() 
input() 
oct() 
staticme 
 
bool() 
eval() 
int() 
open() 
str() 
 
breakpoint() 
exec() 
isinstance() 
ord() 
sum() 
 
bytearray() 
filter() 
issubclass() 
pow() 
super() 
 
bytes() 
float() 
iter() 
print() 
tuple() 
 
callable() 
format() 
len() 
property() 
type() 
 
chr() 
frozenset() 
list() 
range() 
vars() 
 
classmethod() 
getattr() 
locals() 
repr() 
zip() 
 
compile() 
globals() 
map() 
reversed() 
__import 
 
complex() 
hasattr() 
max() 
round() 
 
Git 版本控制 1. 创建文件夹 git_practice 2. 创建程序 hello_git.py 3. 忽略文件 .gitignore 
git bash: touch .gitignoreren n.txt .gitignore
 
4. 初始化仓库 git init Initialized empty Git repository in git_practice/.git/
Git 用来管理仓库的文件都存储在 .git 中,不用管它但不能删除。
 
5. 检查状态 git status 1 2 3 4 5 6 7 8 On branch main No commits yet Untracked files: # 指出未被跟踪的文件   (use "git add <file>..." to include in what will be committed)         .gitignore         hello_git.py # 当前无提交,但指出了可能需要加入仓库的未跟踪文件 nothing added to commit but untracked files present (use "git add" to track) 
6. 加入仓库 git add . 项目中未被跟踪的文件都加入仓库中,但未提交
1 2 3 4 5 6 On branch main No commits yet Changes to be committed:   (use "git rm --cached <file>..." to unstage)         new file:   .gitignore         new file:   hello_git.py 
7. 执行提交 git commit -m "Started project" 标志 -m 让后面信息记录到项目的历史记录中。
1 2 3 4 5 6 7 8 [main (root-commit) a3f6a37] Started project  2 files changed, 2 insertion(+)  create mode 100644 .gitignore  create mode 100644 hello_git.py On branch master nothing to commit, working tree clean # 工作树是干净的,若非如此,可能提交前忘记了添加文件。 
8. 查看提交历史 git log 1 2 3 4 commit b4a4af78247b33c27de89b57d4dde2369f712ab4 (HEAD -> main) Author: xxx <xxx@gmail.com> Date:   Mon Apr 24 16:34:50 2023 +0800     Started project 
每次提交 Git 都会生成唯一的引用 ID,长 40 字符。
精简版:git log --pretty=oneline
1 b4a4af78247b33c27de89b57d4dde2369f712ab4 (HEAD -> main) Started project 
9. 第二次提交 git commit -am "Extended greeting" 标志 -a 让仓库中所有修改了的文件都加入当前提交中
1 2 3 '''hello_git.py''' print("Hello Git!" ) print("Hello everyone." ) 
1 2 3 4 5 6 7 8 9 10 11 12 # 检查状态,指出所做修改未提交 On branch main Changes not staged for commit:   (use "git add <file>..." to update what will be committed)   (use "git restore <file>..." to discard changes in working directory)         modified:   hello_git.py no changes added to commit (use "git add" and/or "git commit -a") [main 35530cb] Entended greeting  1 file changed, 1 insertion(+) # 查看状态和记录,同上 
10. 撤销修改 git checkout . 1 2 3 Updated 1 path from the index # 查看状态,输出工作树干净,文件中最后一行代码被删除。 
git checkout 能恢复到以前的任意提交。提交后 所做的修改,恢复到最后一次提交 的状态。
11. 检出以前的提交 git checkout b4a4af 末尾指定该提交的引用 ID 前 6 字符。
1 2 3 4 5 6 7 Note: switching to 'b4a4af'... HEAD is now at b4a4af7 Started project git checkout main Previous HEAD position was b4a4af7 Started project Switched to branch 'main' 
检出以前的提交后,将离开分支 main,进入分离头指针(detached HEAD)状态。
12. 重置到以前的提交 git reset --hard b4a4af 13. 删除仓库 rm -rf .git 当仓库的历史记录弄乱了,无法恢复时,个人可删除历史记录,再重建仓库,不影响文件当前状态。
可直接删除 .git 或 cmd 下:
缩进规则的例外 
在源码文件中,列表可以跨越几行,直到结束方括号。\,将一条指令写成多行。
 
标准库 random 1 2 3 4 5 6 7 8 9 from  random import  randint, choicerandint(1 , 6 ) players = ['charles' , 'michael' , 'florence' , 'eli' ] choice(players) 
第三方模块 自动排版 Refer 《Python编程快速上手——让繁琐工作自动化第一版》git - Windows下创建 .gitignore 文件 Python 字符串前面加u,r,b,f的含义 python格式化代码【自动排版】 yapf、black风格选择 
PS 啃过 C/C++ 的选手,再学 python 进展之快着实超乎我的意料,晃荡大学四年,编程语言这方面总算开始有真正的基础了,汗颜啊!