Python3 入门笔记

为了做大一立项为了提升自身姿势水平需要在寒假先把 Python 学了...

由于会 C/C++,笔记采用对比方法辅助记忆。

操作系统:macOS 10.15

参考书籍:《Python编程:从入门到实践》,笔记目录也将参考该书目录


起步

macOS 10.15 自带 Python3,终端输入 python3 即可运行。

Sublime text 文本编辑器


变量和简单数据类型

Hello world

print("Hello world!")

注意:print 语句末尾自动换行

【与 C++ 不同】Python3 使用缩进来组织代码结构,而非大括号。

变量

命名规范:【和 C++ 类似】,不赘述。

尽量用小写变量名(下划线法),这是 Python3 的主流命名方式。

【与 C++ 不同】不用声明变量类型,Python3 解释器自己解释。

字符串

【与 C++ 不同】可以用 "" 或者 '' 括起字符串。(小心歧义)

str 是一个字符串:

  • str.title(): 返回单词首字母大写,其余字母小写(不管以前是不是大写)的字符串
  • str.upper()str.lower():返回全文大/小写的字符串
  • str1 + str2: 返回用加号拼接的字符串【和 C++ 的 string 类似】
  • 制表符 \t,换行符 \n【和 C++ 一样】
  • str.lstrip()str.rstrip()str.strip(): 返回删除开头/末尾/两端空白的字符串
  • str.replace(str1, str2):将字符串中的单词 str1 全部替换成 str2
  • str.split():以空格为分隔符把字符串拆成一个个单词,并返回包含这些单词的列表

Python3 视字符串非空为 True

数字

  • + - * / **乘方
  • str(a): 把数字(整型或浮点型) a 转换成字符串

【与 C++ 不同】在 Python3 中,输出 3/2 的值是 1.5,即 Python3 将其理解为浮点数除法而非整除。

注释

# 标识。


列表 Lists

【与 C++ 的 vector 类似】

lst 是一个列表:

访问元素

  • 定义列表:lst = [a, b, c, d] ,其中 a,b,c,d 等是列表的元素,类型可以不同

  • 打印列表:print(lst)(会将列表中的元素列出,括在方括号里)

  • 访问元素:lst[3]索引从 0 开始!!!

    【与 C++ 不同】支持负数索引,-1 表示倒数第一个,-2 倒数第二个。更具体地,设列表共 \(x\) 个元素,则索引范围是 \([-x,x)\).

修改、添加、删除元素

  • 修改:赋值就好了
  • lst.append(x): 在列表末尾添加元素 x
  • lst.insert(idx, x): 在列表索引 idx 处插入一个元素 x (插入后,x 的索引是 idx,其后的元素后移一格)
  • del lst[3]: 删除指定元素(删除后,其后元素前移一格)
  • lst.pop(): 弹出并返回最后一个元素
  • lst.pop(idx): 弹出并返回指定元素
  • lst.remove(x): 删除第一个值为 x 的元素

组织列表

  • lst.sort()lst.sort(reverse = True): 对列表排序,永久性修改顺序
  • sorted(lst)sorted(lst, reverse = True): 返回排序后的列表,但不改变列表原有顺序
  • lst.reverse(): 翻转列表,永久性修改顺序
  • len(lst): 返回列表长度

遍历列表——for 语句

从头到尾遍历列表:

1
2
for i in lst:
do something

注意最后有个冒号 :

【与 C++ 不同】i 是列表元素,不是索引;循环结束后 i 停留为最后一个元素。

数值列表

  • range(l, r): 依次生成 \([l,r)\) 中的整数【类似于 C++ 的 for(int i = l; i < r; i++)
  • range(l, r, step): 指定步长为 step【类似于 C++ 的 for(int i = l; i < r; i += step)
  • list(range(l, r)): 把 range(l, r) 转换为列表
  • min(lis)max(lis)sum(lis): 返回数值列表的最小值、最大值、和
  • 列表解析列表名 = [表达式 for循环],例如:lis = [value**2 for value in range(1,11)] (有描述法定义集合之感)

列表切片

  • lis[l:r]: 返回一个列表,元素依次是 lis 列表的索引在 \([l,r)\) 内的元素

    省略 lr 则默认从头开始或到尾结束

  • 可以循环遍历列表切片:for i in lis[l:r]:

  • 复制列表:在切片中同时省略 lr,即返回从头到尾的列表

    注意:复制列表应改写为:lis2 = lis1[:],而非 lis2=lis1,后者lis1lis2 实质是同一个列表【类似 C++ 的引用】


元组 Tuples

元组就是元素值不可更改的列表。

定义元组

tpl = (a, b, c, d): 把列表定义中的方括号 [] 改成圆括号 () 即可

遍历元组

for i in tpl: 和列表一样

修改元组

元组中元素的值不能修改,但是元组变量本身可以被赋值。

例如:

1
2
3
4
tpl = (100, 300)
print(tpl)
tpl = (300, 100)
print(tpl)

上述代码合法。


if 语句

  • 等号 ==,不等号 != 【和 C++ 一样】

  • and,或 or

  • 检查特定值是否包含在列表中:x in lst

    例如:

    1
    2
    3
    lst = [1, 3, 6]
    print(3 in lst)
    print(4 in lst)

    分别输出 TrueFalse

  • 检查特定值不在列表中:x not in lst

  • if 语句:

    1
    2
    if 条件测试:
    do something

    注意最后有个冒号 :

  • if-else 语句:

    1
    2
    3
    4
    if 条件测试:
    do something
    else:
    do something

    注意 else 后面也有一个冒号 :

  • if-elif-else 语句

    1
    2
    3
    4
    5
    6
    if 条件测试:
    do something
    elif 条件测试:
    do something
    else:
    do something
  • 检查列表是否为空:

    1
    2
    if lst:
    do something

    以列表名为条件表达式,Python3 在列表为空时返回 False,非空时返回 True


字典 Dictionaries

字典是一系列 “键-值对”,可将任何 Python 对象作为值。

【类似于更高端版本的 C++ 的 map】

定义字典

1
2
3
4
5
6
7
dic = {'color': 'green', 'points': 5}
void_dic = {}
favorite_languages = {
'jen': 'python',
'sarah': 'c',
'jason': 'c++',
}

花括号括起一系列键-值对,键与值之间冒号 : 分隔,键值对之间逗号 , 分隔。

访问字典

dic['color']: 字典名[键]

添加、修改、删除

  • 添加:直接赋值即可(即使键本来不存在)。例如:dic['x'] = 0
  • 修改:直接赋值即可
  • 删除:del dic['points']

遍历字典

  • 遍历所有键-值对:

    1
    2
    for k, v in favorite_languages.items():
    do something

    kv 是自定义的变量名,可以更换成其他名称。

    方法 items() 返回键-值对列表。

  • 遍历所有键:

    1
    2
    for k in favorite_languages.keys():
    do something

    k 是自定义的变量名。

    方法 keys() 返回键的列表,可省略(即 for k in favorite_languages:

    由于 keys() 本质是个列表,各种对列表的操作也适用,例如:

    • 按顺序遍历所有键:for k in sorted(favorite_languages.keys()):

    • 检查某值是否在键中:if 'catherine' in favorite_languages.keys():

  • 遍历所有值:

    1
    2
    for v in favorite_languages.values():
    do something

    v 是自定义的变量名。

    方法 values() 返回值的列表。

    去重:for v in set(favorite_languages.values()):

嵌套

  • 字典列表:列表的元素是字典,例如:

    1
    2
    3
    4
    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]
  • 字典中嵌套列表,例如:

    1
    2
    3
    4
    pizza = {
    'crust': 'thick',
    'toppings': ['mushrooms', 'extra cheese'],
    }
  • 字典嵌套字典,例如:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    users = {
    'aeinstein': {
    'first': 'albert',
    'last': 'einstein',
    'location': 'princeton',
    },
    'mcurie': {
    'first': 'marie',
    'last': 'curie',
    'location': 'paris',
    },
    }

用户输入

###input() 函数

1
a = input("prompt")

其中,prompt 是显示在屏幕上的提示词,input() 函数返回一个字符串存储在变量 a 中,即用户的输入内容。

数值输入

int(x) 函数将字符串 x 转换成整数值。例如:

1
2
3
4
5
a = input()
b = input()
a = int(a)
b = int(b)
print(a + b)

float(x) 函数将字符串 x 转换成浮点数值。

取模运算

a % b

例如:35 % 4 == 3-35 % 4 == 135 % -4 == -1-35 % -4 == -3

【与 C++ 不同:负数对正数取模时返回正余数,而非像 C++ 那样返回负余数】


while 语句

  • while 语句:

    1
    2
    while 循环条件:
    do something

    注意最后有个冒号 :

  • breakcontinue 【和 C++ 一样】


函数 Functions

定义与调用

1
2
3
4
5
def func():
"""文档字符串 docstring"""
do something

func()

传递实参

  • 位置实参:实参位置与形参位置对应【和 C++ 一样】

  • 关键字实参:例如:

    1
    2
    3
    4
    def pet(type, name):
    print("My " + type + "'s name is " + name.title() + ".")

    pet(name='harry', type='hamster')
  • 设定默认值:例如:

    1
    2
    3
    4
    def add(a, b=0):
    print(a + b)

    add(1)

    注意:形参列表中必须先列出无默认值的形参,再列出有默认值的形参

返回值

return 【和 C++ 一样】

可以 return 任何类型(包括列表、字典等)

传递列表

  • 把列表名作为实参传过去即可。

  • 在函数中修改列表可更改原列表【类似于 C++ 的传递数组实质是传递首地址】

  • 不想修改原列表可传递切片,例如:

    1
    2
    3
    4
    5
    6
    7
    def print_models(unprinted_designs, completed_models):
    while unprinted_designs:
    current_design = unprinted_designs.pop()
    print("Printing model: " + current_design)
    completed_models.append(current_design)

    print_models(unprinted_designs[:], completed_models)

传递任意数量的实参

  • 在形参前加星号 *,Python3 会创建一个该形参名称的元组

    1
    2
    def func(*tpl):
    do something

    例如:

    1
    2
    3
    4
    5
    def make_pizza(*toppings):
    print(toppings)

    make_pizza('pepperoni')
    make_pizza('mushrooms', 'green peppers', 'extra cheese')
  • 与位置实参结合:位置实参在前,任意数量实参在后

    例如:

    1
    2
    3
    4
    def make_pizza(size, *toppings): 
    print("\nMaking a " + str(size) + "-inch pizza with the following toppings:")
    for topping in toppings:
    print("- " + topping)
  • 任意数量的关键字实参:在形参前加 **,Python3 会创建一个该形参名称的字典

    1
    2
    def func(a, b, **c):
    do something

    例如:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    def build_profile(name, **info):
    profile = {}
    profile['name'] = name
    for key, value in info.items():
    profile[key] = value
    return profile

    user = build_profile('jason', location = 'China', university = 'HITSZ')
    print(user)

将函数存储在模块中

模块是扩展名为 .py 的文件,包含代码【类似于 C++ 的头文件】

  • 导入整个模块

    1
    import pizza

    调用时使用句点 .,例如:

    1
    pizza.make_pizza(16, 'green peppers')
  • 导入特定函数

    1
    2
    from module_name import function_name
    from module_name import function_0, function_1, function_2

    调用时无需使用句点

  • 函数别名:as

    1
    from module_name import function_name as fn

    例如:

    1
    2
    3
    from HelloWorld import say_hello as sh

    sh()
  • 模块别名:as

    1
    import module_name as mn

    例如:

    1
    2
    3
    import HelloWorld as HW

    HW.say_hello()
  • 导入模块中所有函数:星号 *

    1
    from module_name import *

    例如:

    1
    2
    3
    4
    from HelloWorld import *

    say_hello()
    say_bye()

所有 import 都放在程序开头【类似于 C++ 的 #include<>】


类 Classes

创建和使用类

  • 以举例的方式说明如何创建类:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    class Dog():
    """a dog"""
    def __init__(self, name, age):
    self.name = name
    self.age = age
    def sit(self):
    print(self.name.title() + " is now sitting.")
    def roll_over(self):
    print(self.name.title() + " rolled over!")
    • 约定类的名称采用驼峰命名法
    • """ """ 括起一段描述
    • 方法 __init__():创建实例时自动调用【类似于 C++ 的构造函数】
    • self__init__() 中必不可少的形参,且位于第一个,所有与类相关的方法都自动传入实参 self,它是一个指向实例自身的引用【类似于 C++ 的 *this】
    • __init__() 中定义的两个变量前都有 self.,表明其可供类中所有方法使用
  • 举例说明如何创建实例:

    1
    2
    3
    my_dog = Dog('willie', 6)
    print(my_dog.name.title())
    my_dog.roll_over()

    访问属性和调用方法都采用句点 .

使用类和实例

  • 给属性指定默认值:在 __init__() 中赋值即可,例如:

    1
    2
    3
    4
    5
    6
    7
    8
    class Car():
    def __init__(self, make, model, year):
    self.make = make
    self.model = model
    self.year = year
    self.odometer_reading = 0

    my_new_car = Car('audi', 'a6', 2019)
  • 修改属性值:

    • 直接修改:

      1
      2
      3
      4
      class Car():
      # omit

      my_new_car.odometer_reading = 100
    • 定义一个方法修改:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      class Car():
      # omit
      def update(self, mileage):
      self.odometer_reading = mileage
      def increase(self, mileage):
      self.odometer_reading += mileage

      my_new_car = Car('audi', 'a6', 2019)
      my_new_car.update(30)
      my_new_car.increase(100)

继承

一个类继承另一个类时,它自动获得另一个类的所有属性和方法;原有的类称为父类或超类(superclass),而新类称为子类。子类继承父类的属性和方法后,还可以定义自己的属性和方法。

  • 举例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    class Car():
    # omit

    class ElectricCar(Car):
    def __init__(self, make, model, year):
    super().__init__(make, model, year)
    self.battery_size = 70
    def print_battery(self):
    print(self.battery_size)
    def update(self, mileage):
    print("no!")

    my_tesla = ElectricCar('tesla', 'model s', 2016)
    my_tesla.increase(120)
    print(my_tesla.odometer_reading)
    my_tesla.print_battery()
    my_tesla.update(10)
    • 定义子类时,括号里指定父类名称,__init__() 接受创建父类所需的信息
    • super() 函数将父类和子类关联起来。super().__init__() 调用父类的方法 __init__(),使子类包含父类所有属性
    • battery_sizeprint_battery() 分别是子类特有的属性和方法
    • update() 是父类的函数,在子类里重写了
  • 将实例作为属性:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    class Car():
    # omit

    class Battery():
    def __init__(self, battery_size=70):
    self.battery_size = battery_size
    def print_battery(self):
    print(self.battery_size)

    class ElectricCar(Car):
    def __init__(self, make, model, year, bat):
    super().__init__(make, model, year)
    self.battery = Battery(bat)

    my_tesla = ElectricCar('tesla', 'model s', 2016, 80)
    my_tesla.battery.print_battery()

    【类似于 C++ 的 struct 或 class 的嵌套】

导入类

假设上述 Car,Battery,ElectricCar 类都存储在 car.py 中:

  • 导入单个/多个类:

    1
    2
    from car import Car
    from car import Car, ElectricCar
  • 导入整个模块:

    1
    import car

    访问模块内的类是需要使用句点 . ,例如:

    1
    my_tesla = car.Electric('tesla', 'model s', 2016, 80)
  • 导入模块内所有类:星号 *

    1
    from module_name import *

推荐用第二种方式导入并调用类。

Python 标准库

链接


文件和异常 Files and Exceptions

读取文件

  • 读取整个文件

    1
    2
    3
    with open('pi_digits.txt') as file_object:
    contents = file_object.read()
    print(contents)
    • open() 函数打开一个文件,返回表示文件的对象并存储在 as 后的变量中
    • 关键字 with 使得 Python3 能够在合适的时候关闭文件,而不必手动调用 close()
    • 方法 read() 读取整个文件的内容并返回字符串,注意末尾有一个空行(可通过 rstrip() 去掉)
  • 文件路径

    相对路径:从程序所在文件夹开始找

    绝对路径:从根目录开始

  • 逐行读取:用 for 语句

    1
    2
    3
    4
    filename = 'pi_digits.txt'
    with open(filename) as file_object:
    for line in file_object:
    print(line)

    注意每一行末尾都会有一个换行符(可通过 rstrip() 去掉)

  • 创建包含文件各行内容的列表

    1
    2
    3
    4
    5
    filename = 'pi_digits.txt'
    with open(filename) as file_object:
    lines = file_object.readlines()
    for line in lines:
    print(line.rstrip())

    方法 readlines() 从文件读取每一行,并视为字符串将其存储在列表中,返回该列表

写入文件

1
2
3
filename = 'programming.txt'
with open(filename, 'w') as file_object:
file_object.write("I love programming.")
  • open() 函数的第二个实参 w 表示写入(自动创建或覆盖原内容),r 表示只读,a 表示附加(自动创建或添加到文件末尾),r+ 表示读写。默认只读
  • 方法 write()字符串写入文件
  • write() 不会自动换行,要换行需写换行符 \n

注:要写入数值,应先用 str() 将其转化为字符串

异常

异常是一种特殊对象,当 Python3 发生错误时会创建一个异常对象,若编写了处理异常的代码,程序将继续运行,否则将停止。

异常是使用 try-except 代码块处理的,该代码块告诉 Python3 出现异常时怎么办,程序也将继续运行。

  • try-except 代码块:

    1
    2
    3
    4
    try:
    print(5/0)
    except ZeroDivisionError:
    print("You can't divide by zero!")
  • try-except-else 代码块:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    print("Give me two numbers, and I'll divide them.")
    print("Enter 'q' to quit.")
    while True:
    first_number = input("\nFirst number: ")
    if first_number == 'q':
    break
    second_number = input("Second number: ")
    try:
    answer = int(first_number) / int(second_number)
    except ZeroDivisionError:
    print("You can't divide by 0!")
    else:
    print(answer)
  • 一些异常:

    • ZeroDivisionError
    • FileNotFoundError
    • TypeError
    • ValueError
  • pass 语句:让 Python3 什么都不做

存储数据

使用模块 json 存储数据。

  • json.dump()json.load()

    1
    2
    3
    4
    5
    6
    7
    import json

    numbers = [2, 3, 5, 7, 11, 13]

    filename = 'numbers.json'
    with open(filename, 'w') as f_obj:
    json.dump(numbers, f_obj)
    1
    2
    3
    4
    5
    6
    7
    import json

    filename = 'numbers.json'

    with open(filename) as f_obj:
    numbers = json.load(f_obj)
    print(numbers)

测试 Testing

测试模块 unittest

单元测试、测试用例、全覆盖式测试

测试函数

要为函数编写测试用例,可先导入模块 unittest 以及要测试的函数,再创建一个继承 unittest.TestCase 的类,并编写一系列方法对函数行为的不同方面进行测试。

例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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()
  • NamesTestCase 是继承 unittest.TestCase 的一个类
  • 我们运行这个文件时,所有以 test_ 打头的方法都将自动运行(方法名必须以 test_ 打头!)
  • unittest.main() 让 Python3 运行这个文件的测试

unittest 的断言方法

方法 用途
assertEqual(a, b) 核实 a == b
assertNotEqual(a, b) 核实 a != b
assertTrue(x) 核实 aTrue
assertFalse(x) 核实 aFalse
assertIn(item, list) 核实 itemlist
assertNotIn(item, list) 核实 item 不在 list

测试类

  • 与测试函数类似。

    例如:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    import unittest
    from survey import AnonymousSurvey

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

    unittest.main()
  • 方法 setUp()unittest.TestCase 类包含方法 setUp(),Python3 将先运行它,再运行各个以 test_ 打头的方法。

    例如:

    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
    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()

Python3 入门笔记
https://xyfjason.github.io/blog-main/2020/02/16/Python3-入门笔记/
作者
xyfJASON
发布于
2020年2月16日
许可协议