曾经沧海难为水,除却巫山不是|

Joey-Wang

园龄:4年3个月粉丝:17关注:0

📂Python
🔖Python
2021-03-15 20:52阅读: 103评论: 0推荐: 0

Python 笔记

第二章 变量和简单数据类型

变量是可以赋予值的标签,也就是说变量指向特定的值。

2.1 变量的命名

  1. 由字母、数字、下划线组成,不能由数字开头,区分大小写

    • (目前,应用小写的变量名,虽然使用大写字母不会导致错误)
  2. 不要使用Python关键字和函数名

  3. 变量名最好简短、具有描述性(慎用小写字母l和大写字母O,容易看错)

2.2 字符串

​ ---由单引号/双引号括起

  1. 因此,可在字符串中灵活使用""和''
  2. 空白:任何非打印字符,如空格、制表符、换行符。
    • 在字符串中添加制表符:\t

    • 添加换行符:\n

    • 字符串“\n\t”表示换到下一行并在下一行开头添加制表符

2.2.1 修改字符串大小写

  1. 每个单词首字母大写:title()
  2. 字符串全大写:upper()
  3. 字符串全小写:lower()
name="ada lovelace"
print(name.title())   # Ada Lovelace
print(name.upper())   # ADA LOVELACE
print(name.lower())   # ada lovelace

⚠️ print()会自动换行。

2.2.2 在字符串中使用变量

  1. Python3.6引入f字符串:要在字符串中插入变量时,在前引号前添加字母f,将要插入的变量用花括号包起。则当Python显示该字符串时,会将变量替换为其值。

    first_name='ada'
    last_name='lovelace'
    full_name=f'{first_name} {last_name}'
    print(full_name) # ada lovelace
    
  2. Python3.5及更早的版本,要使用format()方法:在字符串中插入变量时,使用花括号代替,format()圆括号内列出具体变量。Python会按顺序将花括号替换为圆括号中变量的值。

    full_name='{} {}'.format(first_name,last_name)
    
  3. 将数值转换为字符串时在其中添加逗号标识的千位分隔符。

    score_str = "{:,}".format(score)
    

2.2.3 合并(拼接)字符串

​ ---使用加号(+)合并字符串[拼接]

2.2.4 删除空白

(空白符:空格、换行符、制表符等)

  1. 删除字符串首端空白:lstrip()
  2. 删除字符串尾端空白:rstrip()
  3. 删除字符串首尾两端空白:strip()
favorite_language='  python  '
print(favorite_language.lstrip())   # 'python  '
print(favorite_language.rstrip())   #'  python'
print(favorite_language.strip())    #'python'

2.2.5 字符替换 —— replace()

将字符串中的特定单词string1替换为另一个单词string2 —— replace(string1, string2, [count])

  • 可添加形参count,不写默认都替换;否则表示最多替换前count个
  • 函数返回一个新的copy
message = "I really like dogs. My dog names Jack."
message = message.replace('dog', 'cat')
print(message)  # I really like cats. My cat names Jack.

2.2.6 字符串分割 —— split()

str.split(str="", num=string.count(str))
# str -- 分隔符,默认为所有的空字符,包括空格、换行(\n)、制表符(\t)等。
# num -- 分割次数。默认为 -1, 即分隔所有。
# 函数返回字符串列表

2.2.7 字符串计数 —— count()

str.count(sub, start=0,end=len(string))
# sub -- 搜索的子字符串
# start -- 字符串开始搜索的索引。默认为0.
# end -- 字符串中结束搜索的索引。默认为字符串的最后一个位置。
a = 'adddaddd'
print(a.count('a', 0, 4))   # 1
print(a.count('a', 0, 5))   # 2

2.3 数字

  1. 可使用括号修改运算次序

  2. 整除运算符 //,它将两个数相除并丢弃余数。

  3. 两个乘号表示乘方,2表示平方,**3表示三次方

    3 ** 3 # 27
    
  4. 浮点数结果包含的小数位数可能是不确定的

  5. python2中整数除法结果为整数. Eg: 2/3=1,若要避免,则要保证至少有一个操作数为浮点数,Eg: 2.0/3=1.5;
    python3中整数除法结果为浮点数

  6. 将非字符串值表示为字符串:str(变量)

    age = 23
    message = "Happy "+str(age)+"rd Birthday!"
    print(message)   #Happy 23rd Birthday!
    
  7. Python3.6中,书写很大的数时,可使用下划线将其中的数字分组,从而更清晰易读。Python存储这种数时,会忽略其中的下划线。

    universe_age = 14_000_000_000
    

2.4 同时给多个变量赋值

在一行代码中可同时给多个变量赋值,需用逗号隔开。

x, y, z = 0, 0, 0

2.5 常量

Python中没有内置的常量类型,但程序员会使用全大写来将某个变量视为常量,其值应始终不变。

MAX_COUNT = 5000

2.6 注释

​ ---使用#标识,#后边的内容被python解释器忽略

第三章 列表简介

​ ---用方括号([])来表示列表,并用逗号分隔其中的元素

如果通过print函数将列表打印出来,Python将打印列表的内部表示,包括方括号。

bicycle=['trek','cannondale','redline']
print(bicycle) # ['trek','cannondale','redline']

3.1 访问列表元素

​ ---通过下标访问列表元素,索引从0开始

将索引指定为-1,返回最后一个列表元素(负数索引返回离列表末尾相应距离的元素)

bicycle=['trek','cannondale','redline']
print(bicycle[0].title())   # Trek
print(bicycle[-1])          # redline

3.2 在列表中添加元素

  1. 在列表末尾添加元素:append()
  2. 在列表中插入元素:insert() 需指定元素的索引和值。
motorcycles=[]
motorcycles.append('honda')
motorcycles.append("yamaha")
print(motorcycles)    # ['honda', 'yamaha']
motorcycles.insert(0,'uducate')
print(motorcycles)    # ['uducate', 'honda', 'yamaha']

3.3 从列表中删除元素

  1. 使用del语句

    • 要知道删除的元素的索引
    motorcycles = ['honda', 'yamaha', 'suzuki']
    print(motorcycles)   # ['honda', 'yamaha', 'suzuki']
    del motorcycles[1]
    print(motorcycles)   # ['honda', 'suzuki']
    
  2. 使用pop()方法

    • pop()可得到删除元素的值并在列表中删除它
    • 可指定索引,默认删除末尾元素
    motorcycles = ['honda', 'yamaha', 'suzuki']
    popped_m1 = motorcycles.pop()
    print(popped_m1)               # suzuki  
    print(motorcycles)             #['honda', 'yamaha']
    popped_m2 = motorcycles.pop(0)
    print(popped_m2)               # honda
    print(motorcycles)             #['yamaha']
    
  3. 根据值删除元素---remove(value)

    • 若value在列表中出现多次,只删除第一个
    motorcycles = ['honda', 'yamaha', 'suzuki', 'yamaha']
    motorcycles.remove('yamaha')
    print(motorcycles)   # ['honda', 'suzuki', 'yamaha']
    
    • 若要删除列表中所有的value,则需使用循环

3.4 组织列表

  1. 对列表进行永久性排序:sort()---默认按字母顺序排列,sort(reverse=True)按字母反向排列
  2. 对列表进行临时排序:sorted(list)---默认按字母顺序排列,也可传递参数reverse=True,返回值为列表
  3. 永久性反转列表:reverse()---若要恢复原来顺序,再次reverse即可
  4. 确定列表长度:len(list)
cars = ['bmw', 'audi', 'toyota', 'subaru']
cars.sort()
print(cars)           # ['audi', 'bmw', 'subaru', 'toyota']

cars = ['bmw', 'audi', 'toyota', 'subaru']
cars.sort(reverse=True)  
print(cars)           # ['toyota', 'subaru', 'bmw', 'audi']

cars = ['bmw', 'audi', 'toyota', 'subaru']
print(sorted(cars))   # ['audi', 'bmw', 'subaru', 'toyota']  
print(cars)           # ['bmw', 'audi', 'toyota', 'subaru']

cars = ['bmw', 'audi', 'toyota', 'subaru']
cars.reverse()
print(cars)           # ['subaru', 'toyota', 'audi', 'bmw']

print(len(cars))      # 4

第四章 操作列表

4.1 遍历列表——for循环

  • ⚠️ for首句后有冒号,用于告诉Python下一行是循环的第一行。

  • Python根据缩进来判断代码行与前一个代码行的关系。

    for循环后每个缩进的代码行都是循环的一部分。

cats = ['alice', 'david', 'carolina', 'jack']
for cat in cats:
    print(cat.title()+" is a good cat!")
    print("I love "+cat.title()+".\n")
print("That's all")

# 输出:
# Alice is a good cat!
# I love Alice.
# 
# David is a good cat!
# I love David.
# 
# Carolina is a good cat!
# I love Carolina.
# 
# Jack is a good cat!
# I love Jack.
# 
# That's all

4.2 创建数值列表

  1. 使用函数生成一系列数 range()——range(begin, end, step)

    • 从begin开始,每次增加一个步长step,到end结束(包括begin,不包括end,默认begin=0,step=1)。
    • 使用range()时,若输出不符合预期,可尝试将指定的值加1或减1。
    for value in range(1,6):
        print(value)
      
    # 输出:
    # 1
    # 2
    # 3
    # 4
    # 5
    
  2. 使用range()创建数字列表

    • 使用函数list()可将range()的结果直接转换为数字列表

      even_number = list(range(2, 10+1, 2))
      print(even_number)  #[2, 4, 6, 8, 10]
      
    • 使用range()创建任何需要的数字列表

      squares = []
      for value in range(1, 11):
          squares.append(value**2)
      print(squares)    # [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
       
      # 与以下方式等价 【列表推导式,总是放在中括号中】
      x_value = list(range(1, 11))
      squares = [x**2 for x in x_value]
      

      python中,**2表示平方,**3表示立方,**0.5表示平方根

  3. 对数字列表执行简单的统计计算

    • 最大值---max(list)
    • 最小值---min(list)
    • 总和---sum(list)
  4. 列表解析

    列表解析:将for循环和创建新元素的代码合并成一行,并自动附加新元素。

    squares = [value**2 for value in range(1, 11)]
    print(squares)      # [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
    

    ​ ⚠️ 这里for语句没有冒号!

    个人理解,for语句的冒号是为了指明循环体,但是此处无需循环体

4.3 使用列表的部分元素(切片)

4.3.1 切片

  1. 创建切片,可指定起始元素和终止元素的索引。(同样包含起始元素,不包含终止元素)

    • ⚠️ 是索引,和range中的值不同。
    • 若未指定起始索引,默认从列表开头开始;若未指定终止元素索引,默认终止于列表末尾。
    • 切片的方括号内可指定第三个值(步长),告诉Python在指定范围内每隔多少元素提取一个。
    players = ['charles', 'martina', 'michael', 'florence', 'eli']
    print(players[1:4])      # ['martina', 'michael', 'florence']
    
  2. 遍历切片:在for循环中使用切片

    players = ['charles', 'martina', 'michael', 'florence', 'eli']
    print("我们队中的前三个队员:")
    for player in players[:3]:
        print(player.title())
        
    # 输出:
    # 我们队中的前三个队员:
    # Charles
    # Martina
    # Michael
    

4.3.2 复制列表

​ ---创建一个包含整个列表的切片,即同时省略起始索引和终止索引([ : ])。

my_foods = ['pizza', 'falafel', 'carrot cake']
friend_foods = my_foods[:]
print("我喜欢的食物是:"+str(my_foods))         # 我喜欢的食物是:['pizza', 'falafel', 'carrot cake']
print("我朋友喜欢的食物是:"+str(friend_foods))  # 我朋友喜欢的食物是:['pizza', 'falafel', 'carrot cake']

⚠️ 若写成:friend_foods = my_foods 则不能得到两个列表。(这种语法实际上是将新变量friend_foods关联到包含在my_foods中的列表,因此这两个变量都指向同一个列表)

使用for循环遍历列表时,Python 要求列表的长度在整个循环中需保持不变。所以不能在for循环遍历的列表中删除元素,若要删除,可遍历列表的副本。

for food in my_foods[:]:

4.4 元组

  1. 列表适合用于存储在程序运行期间可变的数据集(列表是可以修改的),使用方括号标识。

  2. 不可变的列表称为元组,使用圆括号标识。

  3. 元组的遍历于访问与列表操作相同。

  4. 试图修改元组的操作是非法的,但允许给元组重新赋值。

    Rectangle = (200, 50)
    Rectangle[0] = 250     # 报错
    Rectangle = (400, 100) # 合法
    for value in Rectangle:
        print(value)
    
  5. ⚠️ 严格来说,元组由逗号标识,圆括号只是让其看起来更清晰。故若定义只包含一个元素的元组,也必须在此元素后面加逗号。

    my_t = (3,)
    

    创建只包含一个元素的元组通常无意义,但自动生成的元组可能只有一个元素_(:з」∠)_

个人理解:
range()生成一系列数,调用 list()可将之转换为列表,列表是被方括号括起的一系列元素。
切片是列表的一部分,它指向列表,所以可通过切片改变列表中元素的值。
(复制列表则需要将切片赋值给一个新的变量)
元组是不可变的列表,用圆括号标识。

第五章 if语句

5.1 示例

cars = ['audi', 'bmw', 'subaru', 'toyota'] 
for car in cars:
    if car == 'bmw':    #注意要有冒号
        print(car.upper())
    else:
        print(car.title())

5.2 条件测试

  1. 检查是否相等:==

    • 考虑大小写,若想忽略大小写时,可将变量转换为小写再比较 Eg:car.lower() == 'audi'
  2. 检查是否不等:!=

  3. 同时满足多个条件:and

  4. 满足多个条件中的一个:or

  5. 判断列表中是否存在特定值:in

  6. 判断列表中是否不存在特定值:not in

    banned_users = ['andrew', 'carolina', 'david'] 
    user = 'marie' 
    if user not in banned_users:
        print(user.title() + ", you can post a response if you wish.")
    
  7. 布尔表达式:True、False(注意要大写!)

    game_active = True 
    can_edit = False
    

5.3 if语句多种结构

  1. if语句

  2. if-else语句

  3. if-elif-else结构

    age = 12 
    if age < 4: 
        price = 0
    elif age < 18: 
        price = 5
    elif age < 65:
        price = 10
    else:
        price = 5
    print("你的票价是 $" + str(price) + "。")
    
  4. 使用多个elif代码块

    age = 12 
    if age < 4: 
        price = 0
    elif age < 18: 
        price = 5
    elif age < 65:
        price = 10
    elif age >= 65:
        price = 5
    print("你的票价是 $" + str(price) + "。")
    

5.4 使用if语句处理列表

  1. 判定列表是否为空——if list:

    requested_toppings = [] 
    if requested_toppings:
        for requested_topping in requested_toppings:
            print("Adding " + requested_topping + ".")
            print("Finished making your pizza!")
    else:
        print("Are you sure you want a plain pizza?")
        
    # 输出:Are you sure you want a plain pizza?
    

    if list: 非空时执行 if 中的内容。

    if not list: 为空时执行 if 中的内容。

  2. 判断字符串是否为空——if string:

    (若一字符串string=“”,则 if string返回False)

  3. 使用多个列表

    available_toppings = ['mushrooms', 'olives', 'green peppers', 'pepperoni', 'pineapple', 'extra cheese']
    requested_toppings = ['mushrooms', 'french fries', 'extra cheese']
    for requested_topping in requested_toppings:
        if requested_topping in available_toppings:
            print("Adding " + requested_topping + ".")
        else:
            print("Sorry, we don't have " + requested_topping + ".")
    print("Finished making your pizza!")
    
    # 输出:
    # Adding mushrooms.
    # Sorry, we don't have french fries.
    # Adding extra cheese.
    # Finished making your pizza!
    

第六章 字典

  1. 字典是一系列键-值对,可通过键访问与之相关联的值。
  2. Python中,字典是一种动态结构,用放在花括号{}中的一系列键-值对表示,键与值之间用冒号分隔,键-值对之间用逗号分隔。

6.1 使用字典

  1. 通过键获取对应的值

    alien = {'color': 'green', 'points': 5}
    print(alien['color'])    # green
    
  2. 通过get()访问值

    若通过键获取对应值时,该键不存在,则会报错。此时应考虑使用get()方法。

    get(key, [value])——第一个参数指定键;第二个参数为指定键不存在时要返回的值,默认为None。

    alien = {'color': 'green', 'points': 5}
    print(alien.get('speed','No speed value assigned.')) 
    # No speed value assigned.
    
  3. 修改键对应的值

    alien = {'color': 'green', 'points': 5}
    alien['color']='yellow'
    
  4. 添加键-值对

    alien = {'color': 'green', 'points': 5}
    alien['x_position'] = 0
    alien['y_position'] = 25
    print(alien)       #{'color': 'green', 'points': 5, 'x_position': 0, 'y_position': 25}
    
  5. 删除键-值对——使用del语句

    alien = {'color': 'green', 'points': 5}
    del alien['points']
    print(alien)       # {'color': 'green'}
    
  6. 创建空字典

    alien={} # PS:用花括号创建的也可能是空集合set
    

6.2 遍历字典

  1. 得到字典的所有键-值对:items()——返回一个键-值对列表

    • 遍历字典:for k, v in dictionary.items():

      (items方法返回一个一个键-值对列表,Python遍历列表中的每一个键-值对,并将键、值存储在声明的两个变量k、v中。)

    # 遍历字典  for k, v in dictionary.items():
    user_0 = {
        'username': 'efermi',
        'first': 'enrico',
        'last': 'fermi',
        }
    for key, value in user_0.items():
        print("Key: " + key)
        print("Value: " + value)
    
    # 输出:
    # Key: username
    # Value: efermi
    # Key: first
    # Value: enrico
    # Key: last
    # Value: fermi
    
  2. 得到字典的所有键:keys()——返回一个键列表

    • 遍历字典所有键:for k in dictionary.keys(): 或 for k in dictionary:

      (因为遍历字典时,默认遍历所有的键,故keys()可省略)

    • keys()方法并非只用于遍历:因为它返回的是个包含所有键列表,则可使用 not in等判断元素是否在列表中。

    favorite_languages = { 
        'jen': 'python',
        'sarah': 'c',
        'edward': 'ruby',
        'phil': 'python',
        }
    for name in favorite_languages.keys():
        print(name.title())
    if 'erin' not in favorite_languages.keys():
        print("Erin, please take our poll!")
    # 输出:
    # Jen
    # Sarah
    # Edward
    # Phil
    # Erin, please take our poll!
    
  3. 得到字典的所有值:values()——返回一个值列表

    • 遍历字典的所有值:for v in dictionary.values():
    favorite_languages = { 
        'jen': 'python',
        'sarah': 'c',
        'edward': 'ruby',
        'phil': 'python',
        }
    for language in favorite_languages.values():
        print(language.title())
        
    # 输出:
    # Python
    # C
    # Ruby
    # Python
    
  4. 遍历字典时,键-值对的返回顺序与存储顺序不同(Python不关心键-值对的存储顺序,只跟踪键和值之间的关联关系)

    若以特定顺序返回元素,可在for循环中对返回的值进行排序——sorted()

    favorite_languages = { 
        'jen': 'python',
        'sarah': 'c',
        'edward': 'ruby',
        'phil': 'python',
        }
    for language in sorted(favorite_languages.values()):
        print(language.title())
        
    # 输出:
    # C
    # Python
    # Python
    # Ruby
    

    ⚠️ Python3.7中,字典中元素的排列顺序与定义时相同。

  5. 使用集合(set)可剔除列表中的重复项——set()

    集合中每个原色都是独一无二的。

    favorite_languages = { 
        'jen': 'python',
        'sarah': 'c',
        'edward': 'ruby',
        'phil': 'python',
        }
    for language in set(favorite_languages.values()):
        print(language.title())
        
    # 输出
    # C
    # Python
    # Ruby
    

    PS:可使用一对花括号直接创建集合,其中元素以逗号分隔。

    不同于列表和字典,集合不会以特定的顺序存储元素。

    languages={'python','java','c'}
    print(languages) # {'python','java','c'}
    

6.3 嵌套

将一系列字典存储在列表中,或将列表作为值存储在字典中。

(可以在列表中嵌套字典,在字典中嵌套列表,在字典中嵌套字典)

6.3.1 字典列表(在列表中嵌套字典)

​ Eg:字典alien_0包含一个外星人的各种信息,则要存储多个外星人的信息时就可以创建外星人列表。

alien_0 = {'color': 'green', 'points': 5}
alien_1 = {'color': 'yellow', 'points': 10}
alien_2 = {'color': 'red', 'points': 15}
aliens = [alien_0, alien_1, alien_2]
for alien in aliens:
    print(alien)
    
# 输出:
# {'color': 'green', 'points': 5}
# {'color': 'yellow', 'points': 10}
# {'color': 'red', 'points': 15}

​ PS:更符合现实的情形是,外星人不止三个,且每个外星人都是使用代码自动生成的:

# 创建一个用于存储外星人的空列表
aliens = []
# 创建30个绿色的外星人
for alien_number in range(30):
    new_alien = {'color': 'green', 'points': 5, 'speed': 'slow'}
    aliens.append(new_alien)
for alien in aliens[0:3]:
    if alien['color'] == 'green':
        alien['color'] = 'yellow'
        alien['speed'] = 'medium'
        alien['points'] = 10
# 显示前五个外星人
for alien in aliens[0:5]:
    print(alien)
print("...")

# 输出:
# {'color': 'yellow', 'points': 10, 'speed': 'medium'}
# color': 'yellow', 'points': 10, 'speed': 'medium'}
# {'color': 'yellow', 'points': 10, 'speed': 'medium'}
# {'color': 'green', 'points': 5, 'speed': 'slow'}
# {'color': 'green', 'points': 5, 'speed': 'slow'}
# ...

6.3.2 在字典中存储列表

当需要在字典中将一个键关联到多个值时,可在字典中嵌套一个列表。

Eg:每个人喜欢的语言存储在字典中,若一个人喜欢多种语言,则可用一个列表来存储语言信息。

favorite_languages = {
    'jen': ['python', 'ruby'],
    'sarah': ['c'],
    'edward': ['ruby', 'go'],
    'phil': ['python', 'haskell'],
}
for name, languages in favorite_languages.items():
    if len(languages) == 1:
        print(name.title()+"'s favorite language is:\n\t"+languages[0].title())
    else:
        print(name.title()+"'s favorite languages are:")
        for language in languages:
            print('\t'+language.title())

# 输出
# Jen's favorite languages are:
# 	Python
# 	Ruby
# Sarah's favorite language is:
# 	C
# Edward's favorite languages are:
# 	Ruby
# 	Go
# Phil's favorite languages are:
# 	Python
# 	Haskell

6.3.3 在字典中存储字典

Eg:某网站有多个用户,每个用户有不同的用户名,可在字典中将用户名作为键,然后将每位用户的信息存储在一个字典中,并将该字典作为与用户名相关联的值。(这种情况,也可通过在用户列表中嵌套字典实现)

⚠️ 字典中的字典结构最好相同(虽然Python没有此要求,但这使得嵌套的字典处理起来更容易,否则for循环内部代码将更复杂)

users = { 
    'aeinstein': {
        'first': 'albert',
        'last': 'einstein',
        'location': 'princeton',
    },
    'mcurie': {
        'first': 'marie',
        'last': 'curie',
        'location': 'paris',
    },
} 
for username, user_info in users.items():
    print("Username: " + username)
    full_name = user_info['first'] + " " + user_info['last']
    location = user_info['location']
    print("\tFull name: " + full_name.title())
    print("\tLocation: " + location.title())
    
# 输出:
# Username: aeinstein
# 	Full name: Albert Einstein
# 	Location: Princeton
# Username: mcurie
# 	Full name: Marie Curie
# 	Location: Paris

小结:
range()生成一系列数;列表用方括号标识,元组以圆括号标识,字典与集合以花括号标识(元素间都通过逗号分隔)。

range()通过调用 list()可将之转换为列表。
切片是列表的一部分,它指向列表,所以可通过切片改变列表中元素的值。
(复制列表则需要将切片赋值给一个新的变量)

元组是不可变的列表,其本质用逗号标识,故若定义只有一个元素的元组,也需在元素后加逗号。

字典中的元素是一系列键值对,键和值之间用冒号。

列表通过调用 set() 可转换为集合。集合中的元素都唯一,但不会以特定的顺序存储元素(不同于列表和字典)。

6.4 对字典列表进行排序

根据字典中的某个键值对字典列表进行排序—— 使用模块operator中的函数itemgetter(键值对应的键)

from operator import itemgetter
alien_0 = {'color': 'green', 'points': 5}
alien_1 = {'color': 'yellow', 'points': 10}
alien_2 = {'color': 'red', 'points': 15}
aliens = [alien_0, alien_1, alien_2]
aliens = sorted(aliens, key=itemgetter('points'), reverse=True)  
# 或 aliens.sort(key=itemgetter('points'), reverse=True)
for alien in aliens:
    print(alien)
# 输出:
# {'color': 'red', 'points': 15}
# {'color': 'yellow', 'points': 10}
# {'color': 'green', 'points': 5}

第七章 用户输入和while循环

7.1 用户输入

  1. 获取用户输入:input()

    • 函数input()可无参数,也可有一个参数,用于展示需要向用户显示的提示或说明。
    message = input("Tell me something, and I will repeat it back to you: ") 
    print(message)
    
    # Tell me something, and I will repeat it back to you: Hello everyone! 
    # Hello everyone!
    

    PS:提示可能超过一行,这时为了代码清晰,可将提示存储在一个变量中,再将该变量传递给input()

  2. 获取数值输入:int(变量)、float(变量)

    • 使用input()获取的输入都是字符串类型,可使用int()将之转换为整数,使用float()转换为浮点数
    age = input("How old are you? ")
    age = int(age)
    

    PS:字符串转数值:str(变量)

    ​ 数值转字符串:int(变量)、float(变量)

  3. 求模运算:% 返回余数

  4. 在Python 2.7中使用raw_input()提示用户输入

    (Python 2.7也有函数input(),但它将用户输入解读为Python代码,并尝试运行它们)

7.2 while循环

  1. 善用标志变量

    prompt = "\nTell me something, and I will repeat it back to you:"
    prompt += "\nEnter 'quit' to end the program. "
    active = True
    while active:
        message = input(prompt)
        if message == 'quit':
            active = False
        else:
            print(message)
    
  2. 使用break语句退出循环

    prompt = "\nTell me something, and I will repeat it back to you:"
    prompt += "\nEnter 'quit' to end the program. "
    while True:
        message = input(prompt)
        if message == 'quit':
            break
        else:
            print(message)
    
  3. 使用continue语句跳过当前循环

7.3 使用while循环处理列表和字典

  1. while list: ——列表为空时结束循环

    # 首先,创建一个待验证用户列表
    # 和一个用于存储已验证用户的空列表
    unconfirmed_users = ['alice', 'brian', 'candace']
    confirmed_users = [] 
    # 验证每个用户,直到没有未验证用户为止
    # 将每个经过验证的列表都移到已验证用户列表中
    while unconfirmed_users:
        current_user = unconfirmed_users.pop()
        print("正在验证用户: " + current_user.title())
        confirmed_users.append(current_user)
    # 显示所有已验证的用户
    print("\n下列用户已验证:")
    for confirmed_user in confirmed_users:
        print(confirmed_user.title())
        
    # 输出
    # 正在验证用户: Candace
    # 正在验证用户: Brian
    # 正在验证用户: Alice
    #
    # 下列用户已验证:
    # Candace
    # Brian
    # Alice
    
  2. 删除列表中中的所有特定值

    pets = ['dog', 'cat', 'dog', 'goldfish', 'cat', 'rabbit', 'cat']
    print(pets)
    while 'cat' in pets:
        pets.remove('cat')
    print(pets)
    
    # 输出:
    # ['dog', 'cat', 'dog', 'goldfish', 'cat', 'rabbit', 'cat']
    # ['dog', 'dog', 'goldfish', 'cat', 'rabbit', 'cat']
    
  3. 使用用户输入填充字典

    responses = {} 
    # 设置一个标志,指出调查是否继续
    polling_active = True 
    while polling_active: 
        # 提示输入被调查者的名字和回答
        name = input("\nWhat is your name? ") 
        response = input("Which mountain would you like to climb someday? ") 
        # 将答卷存储在字典中
        responses[name] = response 
        # 看看是否还有人要参与调查
        repeat = input("Would you like to let another person respond? (yes/ no) ") 
        if repeat == 'no': 
            polling_active = False 
    # 调查结束,显示结果
    print("\n--- Poll Results ---") 
    for name, response in responses.items(): 
        print(name + " would like to climb " + response + ".")
    

第八章 函数

函数是带名称的代码块,用于完成具体工作,可将代码与主程序分离,让主程序更易理解。
每个函数最好只负责一项具体的工作,不要“身兼多职”。

8.1 定义函数

  1. 函数定义格式:

    def 函数名([形参列表]):
      ["""文档字符串"""]
      函数方法体
    

    函数调用格式:

    函数名([实参列表])
    
  2. 文档字符串:用三引号括起,描述函数是做什么的,Python使用它们来生成有关程序中函数的文档。

  3. 形参:函数完成其工作所需的一项信息。

  4. 实参:调用函数时传递给函数的信息。

    def greet_user(username):
        """显示简单的问候语"""
        print('Hello,' + username.title() + '!')
    
    greet_user('jesse')
    
    #输出:Hello,Jesse!
    

8.2 传递实参

向函数传递参数的方式:位置实参、关键字实参、列表、字典。

8.2.1 位置实参

要求实参和形参的顺序相同。

def describe_pet(animal_type, pet_name):
    """显示宠物的信息"""
    print("我有一只" + animal_type + "。")
    print("我的" + animal_type + "的名字是" + pet_name.title() + "。")
    
describe_pet('金毛', '旺财')

# 输出:
# 我有一只金毛。
# 我的金毛的名字是旺财。

8.2.2 关键字实参

关键字参数传递给函数的是名称-值对,所以无需考虑函数调用中的实参顺序,这种方式更清楚地指出了函数调用中各个值的用途。

def describe_pet(animal_type, pet_name):
    """显示宠物的信息"""
    print("我有一只" + animal_type + "。")
    print("我的" + animal_type + "的名字是" + pet_name.title() + "。")
    
describe_pet(animal_type='金毛', pet_name='旺财')

# 输出:
# 我有一只金毛。
# 我的金毛的名字是旺财。

8.2.3 设置形参默认值

调用函数时若给形参提供了实参,则使用指定的实参值;否则,使用形参的默认值。(使用默认值让实参变成可选的。)

⚠️ 形参的默认值必须从右往左写。

def describe_pet(pet_name, animal_type='狗'):
    """显示宠物的信息"""
    print("我有一只" + animal_type + "。")
    print("我的" + animal_type + "的名字是" + pet_name.title() + "。")
    
describe_pet('旺财')

# 输出:
# 我有一只狗。
# 我的狗的名字是旺财。

8.2.4 传递列表

  1. 将列表传递给函数后,在函数中对此列表做出的任何修改都是永久性的。

    def print_models(unprinted_designs, completed_models):
        """
        模拟打印每个设计,直到没有未打印的设计为止
        打印每个设计后,都将其移到列表completed_models中
        """
        while unprinted_designs:
            current_design = unprinted_designs.pop()
            # 模拟根据设计制作3D打印模型的过程
            print("Printing model: " + current_design)
            completed_models.append(current_design)
    
    
    def show_completed_models(completed_models):
        """显示打印好的所有模型"""
        print("The following models have been printed:")
        for completed_model in completed_models:
            print(completed_model)
    
    
    unprinted_designs = ['iphone case', 'robot pendant', 'dodecahedron']
    completed_models = []
    print_models(unprinted_designs, completed_models)
    show_completed_models(completed_models)
    
    # 输出:
    # Printing model: dodecahedron
    # Printing model: robot pendant
    # Printing model: iphone case
    # The following models have been printed:
    # dodecahedron
    # robot pendant
    # iphone case 
    
  2. 若希望向函数传递列表的副本而不是原件,可使用切片表示法创建列表的副本。

    调用函数格式:

    函数名(列表名[:])
    

    Eg:1中若不想清空未打印的设计列表,可如下调用print_models()

    print_models(unprinted_designs[:], completed_models)
    

    PS⚠️:虽然向函数传递列表的副本可保留原始列表中的内容,但尽量不要这么做,因为让函数使用现成列表可避免花时间和内存创建副本,从而提高效率,在处理大型列表时尤其如此。

8.3 返回值

  1. 函数可以返回任何类型的值,包括是列表或字典。
  2. return None 表示返回空,做if判断时,为False。
def build_person(first_name, last_name, age=''): 
    """返回一个字典,其中包含有关一个人的信息""" 
    person = {'first': first_name, 'last': last_name} 
    if age: 
        person['age'] = age 
    return person 

musician = build_person('jimi', 'hendrix', age=27)   
print(musician)

# 输出:
# {'first': 'jimi', 'last': 'hendrix', 'age': 27}

8.4 传递任意数量的实参

  1. 传递任意数量的实参——使用*形参名

    (星号让Python创建一个名为形参名的空元组,并将收到的所有值都封装进这个元组中)

    def make_pizza(*toppings):
        """概述要制作的比萨"""
        print("使用以下材料做一个披萨:")
        for topping in toppings:
            print("- " + topping)
    
    make_pizza('pepperoni')
    make_pizza('mushrooms', 'green peppers', 'extra cheese')
    
    # 输出:
    # 使用以下材料做一个披萨:
    # - pepperoni
    # 使用以下材料做一个披萨:
    # - mushrooms
    # - green peppers
    # - extra cheese
    
  2. 结合使用位置实参和任意参数实参——注意必须将接纳任意数量实参的形参放在最后

    (Python先匹配位置参数和关键字实参,再将余下的实参都收集到最后一个形参中

    def make_pizza(size, *toppings):
        """概述要制作的比萨"""
        print("用以下材料做一个" + str(size) + "寸的披萨")
        for topping in toppings:
            print("- " + topping)
    
    make_pizza(16, 'pepperoni')
    make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese')
    
    # 输出:
    # 使用以下材料做一个16寸披萨:
    # - pepperoni
    # 使用以下材料做一个12寸披萨:
    # - mushrooms
    # - green peppers
    # - extra cheese
    
  3. 使用任意数量的关键字实参——使用**形参名

    (两个星号让Python创建一个名为形参名的空字典,并将收到的所有名称-值对都封装进此字典中)

    有时,需接受任意数量的实参,但是预先不知道传递给函数的会是什么信息,此情况下,可将函数编写成能接受任意数量的键-值对——调用语句提供了多少就接受多少。

    def build_profile(first, last, **user_info):
        """创建一个字典,其中包含我们知道的有关用户的一切"""
        profile = {}
        profile['first_name'] = first
        profile['last_name'] = last
        for key, value in user_info.items():
            profile[key] = value
        return profile
    
    user_profile = build_profile('albert', 'einstein',location='princeton',field='physics')
    print(user_profile)
    
    # 输出:
    # {'first_name': 'albert', 'last_name': 'einstein', 'location': 'princeton', 'field': 'physics'}
    

8.5 将函数存储在模块中

  • 函数的优点是将代码块与主程序分离,通过给函数指定描述性名称,让主程序更易理解。

    进一步地,可将函数存储在被称为模块的独立文件中,再将模块导入到主程序中。(模块名全小写,单词之间加下划线)

  • import语句——允许在当前运行的程序文件中使用模块中的代码。

8.5.1 导入整个模块

  1. 导入模块格式—— import module_name

    (python运行代码行import module_name时,会将其中的所有函数都复制到此程序中)

  2. 使用此模块中的任意一函数格式—— module_name.function_name()

    句点表示法——需指定模块名和函数名,中间用点号连接)

8.5.2 导入模块中的特定函数

  1. 导入模块中特定函数格式—— from module_name import function_name

    • 通过逗号分隔函数名,可导入模块中任意数量的函数—— from module_name import function_0, function_1, function_2
  2. 使用此模块中的任意一函数格式—— function_name()

    (无需指定模块名,因为在import语句中已显式导入此函数,故调用时只需指定函数名)

8.5.3 导入模块中的所有函数

  1. 导入模块格式—— from module_name import *

    • 星号运算符让Python导入模块中的所有函数

    • ⚠️ 使用非自己编写的大型模块时,最好不要用此导入方式,因为模块和本项目可能存在多个名称相同的函数或变量,进而覆盖函数。

      (故最佳的做法是——导入所需函数,或导入整个模块并使用句点表示法

  2. 使用此模块中的任意一函数格式—— function_name()

8.5.4 使用as指定别名

  1. 给模块指定别名—— import module_name as mn
  2. 给函数指定别名—— from module_name import function_name as fn
    • 若导入的函数名称与程序中现有的名称冲突,或函数名称太长,可指定函数别名。

8.6 函数编写指南

  1. 函数/模块应指定描述性名称,且只使用小写字母和下划线。(大写字母不会有错误,但是最好别用)

  2. 函数都应有简要阐述其功能的注释,此注释应采用文档字符串格式(三引号括起)并紧跟在函数定义后。

  3. 指定形参默认值时,等号两边不要有空格。

    def function_name(parameter_0, parameter_1='default name')
    
  4. 同理,调用函数时若使用关键字实参,等号两边也不要有空格。

    function_name(value_0, parameter_1='value_1')
    
  5. 若形参很多,导致函数定义时长度超过79字符,可在函数定义中输入左括号后按回车键,并在下一行按两个Tab键,将形参列表与函数体区分开,便于代码阅读。

    def function_name(
            parameter_0, parameter_1, parameter_2,
            parameter_3, parameter_4, parameter_5):
        function body...
    
  6. 若程序或模块包含多个函数,可使用 两个空行 将相邻函数分开。

  7. 所有import语句应放在文件开头,除非文件开头使用注释来描述整个程序。

第九章 类

9.1 创建和使用类

  1. 类名中每个单词首字母都需大写,不使用下划线 ——驼峰命名法

    类包含方法属性(类中的函数称为方法)

  2. __init__()是个特殊的方法(相当于java中的构造函数),此方法必须有形参self,且self必须位于其他形参前面。

    • self是一个指向实例本身的引用,让实例能访问类中的属性和方法。

      (类中编写的方法若要操作属性,一定要加形参self,使用self.property的方式得到属性值。)

    • __init__()方法中 self为前缀的变量是属性,可供类中所有方法使用,可通过实例访问(属性也可以是某个类)。

    • __init__()方法中可为属性指定默认值,但若指定了默认值,__init__()方法就不能给通过形参重新给它赋值,需要重新写一个set方法更换它的值。(所以还不如指定形参的默认值)

    class Dog(): 
        """一次模拟小狗的简单尝试""" 
        def __init__(self, name, age):  # 开头末尾各有两个下划线,旨在避免Python默认方法与普通方法发生名称冲突
            """初始化属性name和age""" 
            self.name = name 
            self.age = age 
            self.gender = '男'  # 设置性别默认值
            
        def sit(self): 
            """模拟小狗被命令时蹲下""" 
            print(self.name.title() + " is now sitting.") 
            
        def roll_over(self): 
            """模拟小狗被命令时打滚""" 
            print(self.name.title() + " rolled over!")
    

    PS:在Python2.7中创建类时,需要在括号内包含单词object:

    class ClassName(object):
      --略--
    
  3. 实例名都小写,单词之间添加下划线

    • 访问实例的属性、调用方法,都使用句点表示法
    my_dog = Dog('willie', 6)
    print("我的狗狗名字是" + my_dog.name.title() + "。")
    print("它" + str(my_dog.age) + "岁了,是个" + my_dog.gender + "孩。")
    my_dog.sit()
    
    # 输出:
    # 我的狗狗名字是Willie。
    # 它6岁了,是个男孩。
    # Willie is now sitting.
    
  4. 修改属性的值:

    • 直接通过实例访问属性进行修改;
    • 通过方法进行设置。

9.2 继承

子类继承其父类的所有属性和方法,同时还可以定义自己的属性和方法。(父类也称超类

  1. 创建子类时,父类必须包含在当前文件中,且位于子类的前面。
  2. 定义子类时,必须在括号内指定父类的名称。
  3. 子类的方法__init__()
    • 创建子类实例时,需先给父类的所有属性赋值。因此要写 super().__init__(父类属性参数列表)
    • super()是个特殊函数,通过它可调用父类的方法。
  4. 子类继承父类后,可添加新的属性和方法,也可重写父类方法。
    • 重写父类方法,要求与父类方法同名
class 子类名(父类名):
  def __init__(self,子类及父类属性列表):
    """初始化父类的属性"""
    super().__init__(父类属性列表)
    ---初始化子类的属性(略)---
# 父类
class Car():
    """一次模拟汽车的简单尝试"""
    def __init__(self, make, model, year):
        self.make = make
        self.model = model
        self.year = year
        self.odometer_reading = 0

    def get_descriptive_name(self):
        long_name = str(self.year) + ' ' + self.make + ' ' + self.model
        return long_name.title()

    def read_odometer(self):
        print("This car has " + str(self.odometer_reading) + " miles on it.")

    def update_odometer(self, mileage):
        if mileage >= self.odometer_reading:
            self.odometer_reading = mileage
        else:
            print("You can't roll back an odometer!")

    def increment_odometer(self, miles):
        self.odometer_reading += miles


# 子类
class ElectricCar(Car):
    """电动汽车的独特之处"""
    def __init__(self, make, model, year):
        """初始化父类的属性"""
        super().__init__(make, model, year)


my_tesla = ElectricCar('tesla', 'model s', 2016)
print(my_tesla.get_descriptive_name())   # 2016 Tesla Model S

PS:Python2.7中的继承——函数super()需要两个实参:子类名对象self

# 父类
class Car(object): 
    def __init__(self, make, model, year): 
        --略-- 
 
# 子类        
class ElectricCar(Car): 
    def __init__(self, make, model, year): 
        super(ElectricCar, self).__init__(make, model, year) 
        --略--

9.3 导入类

  1. 可以将类存储在模块中,然后在主程序中导入所需的模块。(一个模块可存储任意多个类)

    • 操作与导入模块中的函数相同,使用import语句
    • 可导入一个模块,使用句点表示法访问所需类 —— import module_name
    • 可导入一个模块的特定类,若导入多个类则用逗号隔开—— from module_name import class_name
    • 可导入一个模块的所有类(使用星号),但不推荐,可能导致名称冲突—— from module_name import *

    (要从一个模块中导入很多类时,推荐导入整个模块,再使用句点表示法module_name.calss_name访问类)

# car.py
"""一个可用于表示汽车的类""" 
class Car(): 
    """一次模拟汽车的简单尝试""" 
    def __init__(self, make, model, year): 
        """初始化描述汽车的属性""" 
        self.make = make 
        self.model = model 
        self.year = year 
        self.odometer_reading = 0 
        
    def get_descriptive_name(self): 
        """返回整洁的描述性名称""" 
        long_name = str(self.year) + ' ' + self.make + ' ' + self.model 
        return long_name.title() 
    
    def read_odometer(self): 
        """打印一条消息,指出汽车的里程""" 
        print("This car has " + str(self.odometer_reading) + " miles on it.") 
        
    def update_odometer(self, mileage): 
        """将里程表读数设置为指定的值,拒绝将里程表往回拨""" 
        if mileage >= self.odometer_reading: 
            self.odometer_reading = mileage 
        else: 
            print("You can't roll back an odometer!") 
            
    def increment_odometer(self, miles): 
        """将里程表读数增加指定的量""" 
        self.odometer_reading += miles
# electric_car.py
"""一组可用于表示电动汽车的类"""

from car import Car

class Battery():
    """一次模拟电动汽车电瓶的简单尝试"""
    def __init__(self, battery_size=60):
        """初始化电瓶的属性"""
        self.battery_size = battery_size

    def describe_battery(self):
        """打印一条描述电瓶容量的消息"""
        print("This car has a " + str(self.battery_size) + "-kWh battery.")

    def get_range(self):
        """打印一条描述电瓶续航里程的消息"""
        if self.battery_size == 70:
            range = 240
        elif self.battery_size == 85:
            range = 270
        message = "This car can go approximately " + str(range)
        message += " miles on a full charge."
        print(message)

class ElectricCar(Car): 
    """模拟电动汽车的独特之处"""
    def __init__(self, make, model, year):
        """初始化父类的属性,再初始化电动汽车特有的属性"""
        super().__init__(make, model, year)
        self.battery = Battery()
# my_cars.py
from car import Car 
from electric_car import ElectricCar 

my_beetle = Car('volkswagen', 'beetle', 2016) 
print(my_beetle.get_descriptive_name())    # 2016 Volkswagen Beetle
my_tesla = ElectricCar('tesla', 'roadster', 2016) 
print(my_tesla.get_descriptive_name())     # 2016 Tesla Roadster

9.4 Python标准库

  1. Python标准库是一组模块,可直接通过import使用。

  2. Eg:模块collections中的OrderedDict类

    • OrderedDict实例的行为几乎与字典相同,区别只在于记录了键-值对的添加顺序。
    • 兼具列表和字典的主要优点(将信息关联起来的同时保留原来的顺序)
    from collections import OrderedDict
    
    favorite_languages = OrderedDict()
    
    favorite_languages['jen'] = 'python'
    favorite_languages['sarah'] = 'c'
    favorite_languages['edward'] = 'ruby'
    favorite_languages['phil'] = 'python'
    
    for name, language in favorite_languages.items(): 
        print(name.title() + "s favorite language is " + language.title() + ".")
        
    # 输出:
    # Jen's favorite language is Python. 
    # Sarah's favorite language is C. 
    # Edward's favorite language is Ruby. 
    # Phil's favorite language is Python.
    
    • ⚠️ 这个在python3中没有用的必要,因为除了集合set外,列表和字典都能保留原来的顺序了。
  3. 模块random的choice函数

    from random import choice
    choice(seq)   # 参数seq ———— 列表、元组或字符串
    
    # 实例
    import random
    print("choice([1, 2, 3, 5, 9]) : ", random.choice([1, 2, 3, 5, 9])) 
    print("choice('A String') : ", random.choice('A String'))
    # 输出:
    # choice([1, 2, 3, 5, 9]) :  5
    # choice('A String') :  S
    
  4. 模块random的random函数

    random() 函数无参数;返回随机生成的一个实数,它在[0,1)范围内。

    import random
    import string
    
    # 随机整数:
    print(random.randint(1,50))     # [1,50]   
    
    # 随机选取0到100间的偶数:
    print(random.randrange(0, 101, 2)) # [0,101) 步长2 
    print(random.choice(range(0, 101, 2)))
    
    # 随机浮点数:
    print(random.random())          # [0,1)
    print(random.uniform(1, 10))    # [1,10]
    
    # 随机字符:
    print(random.choice('abcdefghijklmnopqrstuvwxyz!@#$%^&*()'))
    
    # 多个字符中生成指定数量的随机字符:
    print(random.sample('zyxwvutsrqponmlkjihgfedcba',5))
    
    # 从a-z A-Z 0-9生成指定数量的随机字符:
    ran_str = ''.join(random.sample(string.ascii_letters + string.digits, 8))
    print(ran_str)
    
    # 多个字符中选取指定数量的字符组成新字符串:
    print( ''.join(random.sample(['z','y','x','w','v','u','t','s','r','q','p','o','n','m','l','k','j','i','h','g','f','e','d','c','b','a'], 5)))
    
    # 随机选取字符串:
    print random.choice(['剪刀', '石头', '布'])
    
    # 打乱排序
    items = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
    print random.shuffle(items)
    

    PS:range(a, b)生成[a,b);list切片 list[start : stop] 也是包括start,不包括stop

  5. 模块datetime的datetime类中的函数strptime()——将日期字符串转为表示相应日期的对象

    • 参数1:日期字符串
    • 参数2:要设置的日期格式
    实参 含义
    %Y 四位的年份,Eg:2015
    %y 两位的年份,Eg:15
    %m 用数字表示的月份(01~12)
    %d 用数字表示月份中的一天(01~31)
    %A 星期的名字,Eg:Monday
    %B 月份名,Eg:January
    %H 24小时制的小时数(00~23)
    %I(是大写的i) 12小时制的小时数(01~12)
    %M 分钟数(00~59)
    %S 秒数(00~59)
    %p am或pm
    from datetime import datetime
    first_date = datetime.strptime('2014-7-1', '%Y-%m-%d')
    print(first_date)  # 2014-07-01 00:00:00
    

9.5 类编码风格

  1. 类名中每个单词首字母大写,不使用下划线;实例名和模块名都小写,单词之间加下划线。
  2. 类定义后跟文档字符串:简要描述类的功能;模块后跟文档字符串:简要描述其中的类功能;函数定义后跟文档字符串:简要描述函数的功能。
  3. 类中,使用一个空行来分隔方法;模块中,使用两个空行来分隔类。
  4. 先编写导入标准库模块中的import语句,再添加一个空行,导入自己编写的模块的import语句。

小结

变量、函数名、实例名、模块名都小写,单词间用下划线分隔。
类名采用驼峰命名法,各单词首字母大写,不用下划线。
常量名都大写,单词间用下划线分隔。

第十章 文件和异常

10.1 读取文件

Eg:pi.txt文件

image-20200420230316802
  1. 文件路径

    • 相对路径(相对于当前运行的程序所在目录)
      • 在Linux和OS X中:with open('text_files/filename.txt') as file_object:

      • 在Windows中(使用反斜杠\):with open('text_files\filename.txt' ) as file_object:

        (显示文件路径时是反斜杠,但在代码证仍可以使用斜杠,若使用反斜杠则要转义)

    • 绝对路径
  2. 读取文本文件时,Python将其中的所有文本都解读为字符串。

    • 若需转换为数值 —— int(变量)将字符串转换为整数,float(变量)将字符串转换为浮点数

10.1.1 读取整个文件——read()

  • 函数open(file_name) 会在当前执行文件所在目录中查找指定文件,返回一个表示文件的对象。

  • 使用关键词with则无需访问文件后将其关闭(调用close()函数),Python会自动在合适时将其关闭。

  • 函数read()将读取文件的全部内容,并返回一个字符串。

    PS:read()到达文件末尾时会返回一个空字符串,此空字符串显示出来是个空行。

with open('pi.txt') as file_object:
    contents = file_object.read()
    print(contents)

print(len(contents))

​ 输出:

image-20200420231942761

⚠️ 为什么有38个字符?

​ 答:content为'3.1415926535\n 8979323846\n 2643383279'(中间空的是两个字符)

​ PS:之所以最后有一个空行,是因为print语句会加上一个换行符\n

10.1.2 逐行读取

  • 要以逐行的方式检查文件,可对文件对象使用for循环:
with open('pi.txt') as file_object:
    for line in file_object:
        print(line)

​ 输出:

image-20200420232814904

⚠️ 为什么中间会出现空白行?

​ 答:因为pi.txt文件中每行后有一个换行符\n,而print语句又会加上一个换行符\n,故出现了空白行。

​ (可通过在print语句中使用rstrip()函数,消除文件每行末尾的换行符,来消除空白行)

with open('pi.txt') as file_object:
    for line in file_object:
        print(line.rstrip())

# 输出:
# 3.1415926535
#   8979323846
#   2643383279

10.1.3 将各行存储在列表中——readlines()

  • 使用关键词with时,open()返回的文件对象只能在with代码块内使用。
  • 使用函数readlines()从文件中读取每一行,最终返回一个列表。则将之存储在一个变量中,就可在with代码块外使用此列表。
with open('pi.txt') as file_object:
    lines = file_object.readlines()

pi_string = ''
for line in lines:
    pi_string += line.strip()  # strip能剔除pi.txt中每行的换行和头部空格

print(pi_string)      # 3.141592653589793238462643383279
print(len(pi_string)) # 32

10.1.4 取文件前x个字符 —— 使用切片

# pi_million_digits.txt中圆周率精确到小数点后1 000 000位
with open('pi_million_digits.txt') as file_object:
    lines = file_object.readlines()

pi_string = ''
for line in lines:
    pi_string += line.strip()
    
print(pi_string[:52] + "...") # 3.14159265358979323846264338327950288419716939937510...
print(len(pi_string)) # 1000002

10.2 写入文件

  1. 读取写入文件都使用open函数打开文件 —— open(file_name, [mode],[encoding])
    • 第一个形参 file_name:要打开的文件名称,不可省略。
    • 第二个形参mode:指定文件读打开的模式——读取模式('r'),写入模式('w'),附加模式('a'),读取写入模式('r+')。省略时默认为读取模式
    • 若要写入的文件不存在,open()函数将自动创建它;若要读入的文件不存在,则会报错FileNotFoundError异常。
    • 写入模式('w')时,若文件已存在,会清空文件内容;若不希望清空内容,使用附加模式('a')。
    • 第三个参数 encoding:在系统默认编码与要读取文件使用的编码不一致时,需填写Eg:encoding='utf-8'
  2. 写入文件 —— write()
    • 函数write()不会自动在文本末尾添加换行符,需要你自己加\n
  3. Python只能将字符串写入文本文件,若要讲数值数据存储在文本中,需先使用str(变量)将其转换为字符串格式。
filename = 'programming.txt' 
with open(filename, 'w') as file_object:
    file_object.write("I love programming.\n")
    file_object.write("I love creating new games.")
    
# programming.txt:
# I love programming. 
# I love creating new games.

10.3 异常

  1. 异常是一种特殊的对象,Python使用它来管理程序执行期间发生的错误。

    (每当发生让Python不知所措的错误时,它都会创建一个异常对象。)

  2. 若不对产生的异常进行处理,程序将停止,并显示一个trackback,其中包含有关异常的报告。

  3. 异常需使用try-except代码块 或 try-except-else代码块进行处理。

    • try代码块:存放 可能引发异常 的代码

    • except代码块:存放 发生指定异常时 需执行的代码

    • 若Python尝试运行try代码块中的代码时发生了except指定的异常,执行except代码块内容

    • 可使用pass语句,让Python在发生指定异常时什么都不做,不出现traceback也不产生任何输出。

      (pass语句也算是一种对异常的处理,还充当了占位符,提醒你程序的某个地方啥都没做,且以后也许需要在这里做些什么)

    • else代码块:存放当 try代码块成功执行时 才需要执行的代码

  4. 若程序运行不产生异常,执行完try块后会跳过except块,执行后续代码;

    否则,会直接查找except块并执行其中代码,然后执行后续代码(但try块中未执行的部分不再执行)。

    (所以try-except-else可用try-except代替,只需将else块中内容放在try快中,但是有else代码块会使代码逻辑更清晰)

# 处理 ZeroDivisionError 异常
print("输入被除数和输出,将给出二者的商。")
print("输入 'q' 可终止程序。") 
while True: 
    first_number = input("\n被除数: ")
    if first_number == 'q':
        break
    second_number = input("除数: ")
    try:
        answer = int(first_number) / int(second_number)
    except ZeroDivisionError:
        print("不能被0除!")
    else:
        print(answer)
        
# 等价程序
print("输入被除数和除数,将给出二者的商。")
print("输入 'q' 可终止程序。") 
while True: 
    first_number = input("\n被除数: ")
    if first_number == 'q':
        break
    second_number = input("除数: ")
    try:
        answer = int(first_number) / int(second_number)
        print(answer)
    except ZeroDivisionError:
        print("不能被0除!")
# 处理 FileNotFoundError 异常
def count_words(filename): 
    """计算一个文件大致包含多少个单词"""
    try:
        with open(filename, encoding='utf-8') as f_obj:
            contents = f_obj.read()
    except FileNotFoundError:
        pass
    else:
        # 计算文件大致包含多少个单词
        words = contents.split()
        num_words = len(words)
        print("文件 " + filename + " 有大约 " + str(num_words) + " 个英文单词。")

filenames = ['alice.txt', 'siddhartha.txt', 'moby_dick.txt', 'little_women.txt'] # 其中siddhartha.txt不存在
for filename in filenames: 
    count_words(filename)
    
# 输出
# 文件 alice.txt 有大约 29461 个英文单词。 
# 文件 moby_dick.txt 有大约 215136 个英文单词。  
# 文件 little_women.txt 有大约 189079 个英文单词。 

10.4 存储数据

  1. 使用模块json存储数据

    • 模块json可将给简单的Python数据结构(列表、字典)转储到文件中,并在程序加载文件时将数据加载到数据结构。

      还能与其他编程语言的人分享数据。

    • 使用文件扩展名.json来指出文件存储的数据为JSON格式。

  2. 存储数据 —— json.dump(data, file_object, indent=)

    • 接受两个实参:要存储的数据、用于存储数据的文件对象【必填】
    • 参数 indent=4:让 dump() 使用与数据结构匹配的缩进量来设置数据的格式。
  3. 读取数据 —— json.load(file_object)

    • 将数据转换为 Python 能处理的格式
    import json
    numbers = [2, 3, 5, 7, 11, 13]
    filename = 'numbers.json'
    # 存储数据
    with open(filename, 'w') as f_obj:
        json.dump(numbers, f_obj)
    
    # 读取数据
    with open(filename) as f_obj:
        numbers = json.load(f_obj)
        
    print(numbers)    # [2, 3, 5, 7, 11, 13] 
    

    实例:

    import json
    
    def get_stored_username():
        """如果存储了用户名,就获取它"""
        filename = 'username.json' 
        try: 
            with open(filename) as f_obj: 
                username = json.load(f_obj) 
        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_obj:
            json.dump(username, f_obj)
        return username
    
    def greet_user():
        """问候用户,并指出其名字"""
        username = get_stored_username()
        if username:
            print("Welcome back, " + username + "!")
        else:
            username = get_new_username()
            print("We'll remember you when you come back, " + username + "!")
            
    greet_user()
    
  4. 比较json.dumps, json.loadsjson.dump, json.load

    • json.dumps, json.loads 进行Python的数据结构和JSON格式之间的转换

      import json
      
      # Python数据结构 -> JSON
      data = {
          'name' : 'ACME',
          'shares' : 100,
          'price' : 542.23
      }
      json_str = json.dumps(data)
      
      # JSON -> Python数据结构
      data = json.loads(json_str)
      
    • json.dump, json.load 将Python的数据结构存储到JSON文件,或从JSON文件中读取数据

PS:重构——代码能正确运行,但通过将其划分为一系列完成具体工作的函数还可以改进,此过程称为重构。
(目的在于让代码更清晰、更容易扩展)

第十一章 测试代码

  1. 单元测试:用于核实函数的某个方面没有问题。

  2. 测试用例:是一组单元测试,这些单元测试一起核实函数在各种情况下的行为都符合要求。

    • 良好的测试用例应考虑函数可能收到的各种输入,包含针对所有这些情况的测试。
  3. 全覆盖式测试:用例包含一整套单元测试,涵盖了各种可能的函数使用方式。

    • 最初只需针对代码的重要行为编写测试即可,等项目被广泛使用时再考虑全覆盖。
  4. How为函数编写测试用例:

    • 导入unittest模块以及要测试的函数;

    • 创建一个继承unittest.TestCase的类,此类可随意命名但最好包含Test字样;

    • 在此类中编写一系列方法对函数行为的不同方面进行测试,测试方法必须以test_打头。

      (这样这些方法才会在运行测试代码时自动运行)

    • Python在unittest.TestCase类中提供了很多断言方法,可用于在测试方法中核实得到的结果是否与期望的结果一致。

      (测试方法中若要使用断言,要有self形参,通过self.assertEqual()方式使用断言)

    • 测试文件代码行最后执行unittest.main()让Python运行这个文件中的测试。

  5. 断言方法能检查你认为应该满足的条件是否确实满足。若满足,则对程序行为的假设得到了确认,没有错误。否则,Python将引发异常。常见的6种断言方法如下:(使用需继承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中
  6. 方法setUp()

    • 若在测试类中写了setUp()方法,则Python将先运行它,再运行各个以test_打头的方法。
    • setUp()让测试方法编写更容易:可在setUp()方法中创建一系列实例并设置它们的属性,再在测试方法中直接使用这些实例。(这些实例变量都需加上前缀self,即存储在测试类的属性中,因此可以在此类的任何地方使用)
  7. 运行测试用例时,每完成一个单元测试,Python都打印一个字符:

    • 测试通过,打印一个句点
    • 测试引发错误,打印一个E
    • 测试导致断言失败,打印一个F

11.1 测试函数

# name_function.py
def get_formatted_name(first, last, middle=''): 
    """生成整洁的姓名""" 
    if middle: 
        full_name = first + ' ' + middle + ' ' + last 
    else: 
        full_name = first + ' ' + last 
    return full_name.title()
import unittest 
from name_function import get_formatted_name 

class NamesTestCase(unittest.TestCase): 
    """测试name_function.py """ 
    
    def test_first_last_name(self): 
        """能够正确地处理像Janis Joplin这样的姓名吗?""" 
        formatted_name = get_formatted_name('janis', 'joplin') 
        self.assertEqual(formatted_name, 'Janis Joplin')
        
    def test_first_last_middle_name(self): 
        """能够正确地处理像Wolfgang Amadeus Mozart这样的姓名吗?""" 
        formatted_name = get_formatted_name( 'wolfgang', 'mozart', 'amadeus') 
        self.assertEqual(formatted_name, 'Wolfgang Amadeus Mozart') 
        
unittest.main()

11.2 测试类

# survey.py
class AnonymousSurvey(): 
    """收集匿名调查问卷的答案""" 
    
    def __init__(self, question): 
        """存储一个问题,并为存储答案做准备""" 
        self.question = question 
        self.responses = [] 

    def show_question(self): 
        """显示调查问卷""" 
        print(question) 

    def store_response(self, new_response): 
        """存储单份调查答卷""" 
        self.responses.append(new_response)
        
    def show_results(self): 
        """显示收集到的所有答卷""" 
        print("Survey results:") 
        for response in responses: 
            print('- ' + response)
import unittest 
from survey import AnonymousSurvey

class TestAnonymousSurvey(unittest.TestCase): 
    """针对AnonymousSurvey类的测试"""
    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)          

unittest.main()

此处:setUp()方法创建一个调查对象my_survey和一个答案列表responses。

存储二者的变量名都含前缀self(即存储在属性中),故可在这个类的任何地方使用。

本文作者:Joey-Wang

本文链接:https://www.cnblogs.com/joey-wang/p/14539910.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Joey-Wang  阅读(103)  评论(0编辑  收藏  举报
编辑推荐:
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
展开