本篇内容从《Python编程 从入门到实践》整理而来,供个人学习和参考。

1.列表

  1. 列表是有序的集合,访问列表元素只需要给出该元素的位置或者索引就可以了。
  2. 列表的索引是从0开始的。索引可以为负,最后一个元素的索引为-1, 类似地,倒数第二个元素索引为-2.
  3. 在列表末尾添加元素,用append()方法;
    在列表中间加入元素,用insert()方法,需要指定新元素的索引和值。
  4. 在列表末尾删除元素,用pop()方法;
    删除列表中某个元素,用del()方法,需要知道该元素的索引位置。
    del()方法删除后,被删除的元素无法再访问了;pop()方法删除的元素依然可以继续访问。
    pop()可以删除列表中任何位置的元素,只需要在括号中指定要删除元素的索引即可,括号中没有索引时,表示删除列表末尾的元素。
    知道要删除元素的值,用remove()方法。如果该值出现多次,remove()只删除第一个指定的值。
  5. 对列表永久性排序用sort()方法;
    对列表临时排序用sorted()函数。
  6. 反转打印列表元素,用reverse()方法。
  7. 获取列表长度,用len()方法
  8. 使用列表时要注意索引的正确使用(从0开始),当需要访问列表最后一个元素的时候,用索引-1。

2. 列表的操作

  1. 用for()循环遍历列表。
  2. 命名时,使用单数和复数式名称,用来区别是单个列表元素还是整个列表。
  3. 创建数字列表用函数range(), range(1,5)打印出的是数字1,2,3,4.
    range()函数从指定的第一个数字开始数,到达第二个数字后停止(不包括第二个数字)。
  4. 创建数字列表的一种方法是:先创建一个空列表,然后使用range()函数对一个数值范围进行遍历,计算后的值依次传入空列表,最后循环结束。
  5. 第二种方法是列表解析法。先指定一个列表名,然后指定一个方括号,定义一个表达式,编写一个for循环,用于给表达式提供值。
squares = [value ** 2 for value in range(1, 11)]
  1. 要对列表切片,可指定要使用的第一个元素的索引和最后一个元素索引加1。跟range()函数相同,在到达指定的第二个元素前面的元素后停止。 在编写web程序时,可以使用切片来分页显示信息。
print(squares[0: 3])
# 会输出列表的第0个、第1个和第2个元素,不会输出第3个元素
  1. 复制列表,可以创建一个包含整个列表的切片,同时省略起始索引和终止索引([:]). 如果不使用切片,直接将一个列表变量赋值给另一个变量名,那么两个变量指向的是同一个列表。
# 用切片可以全部复制
listb = lista[:]

# 直接赋值变量名不可以全部复制,两个变量指向的是同一个列表
listb = lista
  1. 列表的值是可变的,如果需要一系列不可变的元素,那么要用到元组,元组用圆括号定义。
tuple1 = (200, 50)
  1. 遍历元组的元素使用for循环,和列表类似。
  2. 元组元素不可以修改,如果要修改 ,只能重新定义整个元组。

3. if语句

  1. 相等运算符(==)返回的是布尔值,True或者False.
  2. Python中检查相等时,区分大小写。如果要检查的变量大小写不重要,只想检查变量的值,可以先转换成小写,再进行比较。
car = 'Audi'
car.lower() == 'audi'. # 返回True

如果要把小写单词转换成大写时,用title()方法。
3. 检查多个条件时,使用关键字and或or.
4. 检查特定的值是否包含在某个列表中,使用关键字in。
5. 检查特定的值是否不包含在某个列表中,使用关键字not in.
6. if-elif-else适用于只有一个条件满足的情况,只执行一个代码块;
如果想要执行多个代码块,需要使用一系列独立的if语句。
7. 在对列表进行操作前,一般会先用if语句检查列表是否为空。

4.字典

  1. 字典用放在{ }中的一系列键值对表示。
alien = {'color': 'green', 'points': 5}
  1. 获取字典中与键相关联的值,需要指定字典名和括号中的键。
alien['color']
# 返回 green
  1. 要添加键值对,需要依次指定字典名、用方括号括起的键和相关联的值。
alien['x_position'] = 0
alien['y_position'] = 10
  1. 创建空字典,要用一对空的花括号定义一个字典,再分行添加各个键值对。
  2. 要删除键值对,使用del语句,删除的时候要指定字典名和要删除的键。
    del语句删除的键值对永远消失了。
del alien['points']
  1. Python如果有较长的一行语句,需要进行拆分,在第一行的末尾加上拼接运算符(+), 拆分后的各行需要对齐和缩进一致。
  2. 遍历字典的所有键值对,用for循环来实现。
for my_key, my_value in mydict.items():
要编写用于遍历字典的for循环,可以声明两个变量,用于存储键值对中键和值,这两个变量的名称可以自己任意指定(如k和v)。
for 循环第二部分包含了字典名mydict和方法items(),返回一个键值对   列表。键值对的返回顺序和储存顺序不一定相同。
  1. 如果只需要遍历字典所有的键,不需要使用字典的值时,可以使用方法keys().方法keys()其实返回的是一个列表,这个列表中包含字典的所有键。
for name in favorite_language.keys():
  1. 普通遍历键值对,返回的顺序是不确定的,如果想要以特定的顺序返回键值对,可以在for循环中使用sorted()函数对键值对进行排序。
for name in sorted(favorite_language.keys()):
  1. 如果只需要遍历字典中所有的值,可以使用方法values().返回的是一个值列表。
  2. 遍历之后,获取的键或者值列表中,可能会有重复的元素,如果想要剔除重复项,可以使用集合set().
for language in set(favorite_languages.values()):
  1. 如果要将字典中的一个键关联到多个值时,可以在字典中嵌套一个列表。

5. 用户输入和while循环

  1. 如果需要获取用户输入的内容,可以使用函数input(),函数input()让程序暂停运行,等待用户输入一些文本,获取用户输入后,将其保存在一个变量中。input()获取的内容python将其解读为一个字符串。
msg = input("Please enter your name:")
print(msg)

这时,用户输入的名字存储在变量msg中,供后面程序的调用。
2. 要创建多行字符串,可以将前半部分保存在变量中,后半部分加在变量之后。(+=)

prompt = "If you tell us who you are, we can personalize the message you see."
prompt += "What is your first name?"
  1. 使用函数input()时,python将用户的输入解读为一个字符串,如果输入的是数字,并且要用于计算和比较,那么要在input()获取之后,用int()将它转换为数值。
  2. 求模运算符(%):它将两个数相除,返回余数。如果要判断某个数字是奇数还是偶数,可以让该数字对2求模,偶数返回0,奇数返回1.
  3. 在while循环中,通常需要设定一个标志flag来决定循环是否进行,flag初始值等于True,当需要循环结束时,flag等于False.
  4. break: 立即退出while循环,而不再运行循环中余下的代码。break语句可以用于控制程序的流程,控制哪些代码将被执行,哪些代码不执行。
  5. continue: 返回到循环开头,根据条件测试的结果判断循环是否继续执行。而不是跳出整个while循环。
  6. for循环可以用于遍历列表,但是for循环中不能修改列表,否则python无法追踪其中的元素。想要遍历列表的同时,对列表进行修改,可以使用while循环。
  7. 要删除列表中的某个特定值,可以使用remove()方法,但如果要删除的值多次出现,就需要使用while循环。
pets = ['dog', 'cat', 'fish', 'cat', 'rabbit']

while 'cat' in pets:
    pets.remove('cat')

print(pets)
  1. 使用用户的输入来填充字典
# 定义一个空字典
responses = {}

# 设置一个标志,决定循环是否继续进行
polling_active = True

while polling_active:
    # 用while循环将用户输入的内容存储到字典中
    name = input("\nWhat is your name?")
    response = input("Which mountain would you like to climb?")

    responses[name] = response

    # 确定循环是否要继续,修改flag值
    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 + '.')

6. 函数

  1. 在函数定义中的是形参,调用函数时实际传递给函数的信息是实参。
  2. 在调用函数时,python需要将函数调用中的每个实参都关联到函数定义中的每个形参,如果按照参数的位置一一关联,这种关联方式被称为位置实参。所以,位置实参的顺序很重要。
  3. 如果不考虑传递实参时的位置,可以使用关键字实参,在函数调用中准确的给出形参名。
def describe_pet(animal_type, pet_name):
    ...

describe_pet(animal_type = 'cat', pet_name = 'harry')
  1. 定义函数时,可以给每个形参指定默认值。在调用的时候,如果给函数提供了实参的值,则使用给定的实参值,否则,将使用形参的默认值。
    如果给出形参的默认值,那么一定要在形参列表中先列出没有默认值的形参,再给出有默认值的形参,这时python会将没有默认值的形参解读成位置形参。
  2. 如果需要让实参变成可选的,可以给该实参对应的形参提供默认值(默认值为空),并且把该形参放在参数列表的末尾。
  3. 如果预先不能确定函数需要多少个实参,在定义函数时,形参采用元组的形式。
def make_pizza(*toppings):
    ...

形参名中的*星号让python创建一个名为toppings的空元组,元组大小未定,可以将所有收到的实参的值存储到元组中。
7. 如果传递的参数中有多种不同类型的实参,那么,在函数的定义中,需要将位置实参放在最前,其次是关键字实参,任意数量实参放在最后,当位置实参和关键字实参全部匹配完成后,剩余的参数都被包括到任意实参中去。
8. 有的时候,需要接受任意数量的实参,但是不知道传递给函数的是什么样的信息,这时候,可以将函数编写成能够接受任意数量的键-值对。在定义时,形参采用字典的形式。

def build_profile(first, last, **user_info):
    # 在形参中,用** 两个星号创建一个字典

    profile = {}
    profile['first_name'] = first
    profile['last_name'] = last   
    # 遍历形参中的字典,加入到profile字典中
    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)
  1. 可以将函数存储在被称为模块的独立文件中,再将模块导入到主程序中。
  2. 可以导入整个模块: 用import导入,并指定模块名,就可以在程序中使用该模块中的所有函数。使用函数的方法: module_name.function_name()
import pizza
  1. 可以导入特定的函数:
    from module_name import function_name
    导入多个特定的函数:
    from module_name import function_name0, function_name1, function_name2
  2. 使用as给函数指定别名
    from module_name import function_name as fn
  3. 使用as给模块指定别名
    import module_name as mn
  4. 导入模块中的所有函数,使用(*)星号运算符
from module_name import *
  1. 编写函数时,要给函数指定描述性名称,并且只在其中使用小写字母和下划线。模块命名类似。
    给形参指定默认值时,等号的两边不要有空格,调用函数时的实参也类似。

7.类

  1. 通过类来创建对象称作实例化。
  2. 在python中,类的首字母大写。
  3. 类中的函数称为方法。
  4. 类初始化的方法为__init__(), 在__init__()方法中,形参self不能少,并且一定要在其他形参的前面。
    形参self的作用:当python调用__init__()方法来创建实例时,会自动传入实参self.每个与类相关联的方法都自动传递实参self, 它是一个指向实例本身的引用,让实例能够访问类中的属性和方法。
class Dog():
# 创建一个类,类的首字母大写

    def __init__(self, name, age):
        self.name = name
        self.age = age

    def sit(self):
        ...

    def roll_over(self):
        ...

以self为前缀的变量可以供类中的所有方法使用,可以通过类的任何实例来访问这些变量。self.name = name, 获取形参name中的值,将其存储到变量name中,然后这个变量name被关联到当前的实例中。
5. 创建完类之后,根据类来创建实例,这里要遵循python的命名规则,通常首字母大写的名称指的是类,如Dog,小写的名称如my_dog指的是实例。
6. 想要获取属性的值,可以采用句点表示法。

my_dog.name
  1. 调用类中定义的方法,可以给出实例的名称和要调用的方法。
my_dog.sit()
my_dog.roll_over()
  1. 类中的每一个属性都要有一个初始值,初始值可以是0或者空字符串。如果给某一个属性提供了初始值/默认值,则在类的初始化函数中,可以不加这个属性对应的形参。
    实例化的时候,也可以不给这个属性传值。
class Car():
    
    def __init__(self, make, model, year):
        self.make = make
        self.model = model
        self.year = year
        self.odometer_reading = 0
        # 属性odometer_reading 给出了默认值,因此可以不用在类定义列表中写形参
        
    def read_odometer(self):
        print("This car has " + str(self.odometer_reading) + " miles on it.")
        
# 形参odometer_reading已经有了默认值,所以可以不给他传值,(获取的就是默认值)       
my_car = Car('audi', 'a4', 2016)
my_car.read_odometer()
  1. 要修改属性的值,有三种方法。
    一. 通过实例直接修改属性的值; 二.通过方法进行设置;三.通过方法进行递增(增加特定的值)。
    通过实例直接修改属性的值时,用的是句点表示法。
my_car.odometer_reading = 23
class Car():

    def __init__(self, make, model, year):
        self.make = make
        self.model = model
        self.year = year
        self.odometer_reading = 0
        # 属性odometer_reading 给出了默认值,因此可以不用在类定义列表中写形参

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

    
    def update_odometer(self, mileage):
        self.odometer_reading = mileage

my_car = Car('audi', 'a4', 2016)
my_car.update_odometer(23)
my_car.read_odometer()

有的时候需要对属性的值递增特定的量,可以通过方法对属性的值递增。

class Car():

    def __init__(self, make, model, year):
        self.make = make
        self.model = model
        self.year = year
        self.odometer_reading = 0
        # 属性odometer_reading 给出了默认值,因此可以不用在类定义列表中写形参

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


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

my_car = Car('audi', 'a4', 2016)
my_car.update_odometer(23)
my_car.increment_odometer(100)
my_car.read_odometer()
  1. 继承
    (面向对象的继承,这篇文章讲的很清楚: 子类继承父类时,获得了父类的所有属性和方法,并且,子类还可以定义自己的属性和方法。
    创建子类(ElectricCar)时,父类(Car)一定要和子类定义在同一个文件中,并且定义在子类的前面。定义子类时,需要在括号内指出父类的名称。
    super()函数将父类和子类关联起来,
class ElectricCar(Car):
    # 定义了一个子类,继承父类Car

    def __init__(self, make, model, year):
        super().__init__(make, model, year)
  1. 子类继承父类之后,可以给子类添加新的属性和方法,这些属性和方法是子类特有的。子类的属性和方法可以根据需要任意的添加。
class ElectricCar(Car):
    # 定义了一个子类,继承父类Car

    def __init__(self, make, model, year):
        super().__init__(make, model, year)
        self.battery_size = 70
        # 给子类添加了一个新的属性,由于这个属性给出了默认值,因此在初始化类的时候,形参列表中可以不写
    
    # 给子类添加一个新的方法    
    def describe_battery(self):
        print("This car has a " + str(self.battery_size) + "-kwh battery.")
  1. 如果父类的方法不能满足子类的要求,可以对这个方法进行重写。重写的方法要与父类的方法重名。这样,python会忽略原来父类的方法,只关注子类中重写的方法。
  2. 有的时候,一个类下的属性和方法都越来越多,这时候,可以把类的一部分作为另一个单独的类提取出来。
# 把battery相关的属性和方法提取出来,作为一个单独的类
class Battery:
    def __init__(self, battery_size=70):
        self.battery_size = battery_size

    def describe_battery(self):
        print("This car has a " + str(self.battery_size) + "-kwh battery.")


class ElectricCar(Car):
    # 定义了一个子类,继承父类Car

    def __init__(self, make, model, year):
        # super()方法关联父类和子类
        super().__init__(make, model, year)
        self.battery = Battery()
        # 用Battery类的实例化对象,作为ElectricCar类的一个属性


my_telsa = ElectricCar('telsa', 'model s', 2016)
my_telsa.battery.describe_battery()
# 在调用describe_battery()方法时,要先寻找my_telsa的battery属性,然后再调用Battery实例的方法describe_battery()
  1. 导入类
# 导入单个类
from car import Car  # 打开模块car,导入Car类(类的首字母永远是大写的)

# 从一个模块中导入多个类
from car import Car, ElectricCar

# 导入整个模块
import car  # 导入整个模块的话,调用类的时候用句点表示法module_name.class_name

# 导入模块中的所有类,这种做法不建议使用
from car import *

# 在一个模块中导入另一个模块
# 如果发现一个模块中的类需要用到另一个模块中的类,那么提前导入所需要的类
  1. Python标准库有很多的模块,在需要使用的时候,只要在程序开头将其import导入就可以了。
  2. 类的编码风格
    类名:驼峰命名法,每个单词首字母都要大写,不使用下划线。
    实例名和模块名:小写,单词之间加上下划线。
    每个类,在类的定义后面要包含一个文档字符串。每个模块也应当包含一个文档字符串,进行简要的描述说明。
    在一个类中,分隔方法只用一个空行;在模块中,分隔类用两个空行。
    同时导入标准库模块和自己的模块的时候,先导入标准库的模块,然后添加一个空行,再导入自己编写的模块。

8. 文件和异常

  1. 读取整个文件: open()函数的参数是要打开的文件名,open()函数返回一个表示该文件的对象。
    with 关键字表示,在不需要这个文件的时候,python会自动将其关闭。
    read()方法用于读取文件的内容,并且将读取到的内容作为一个长长的字符串存储在变量contents中。
    如果文件的末尾有空白,直接print之后打印出的内容最后也有空白,可以使用rstrip()方法删除字符串末尾的空白。
with open('pi_digits.txt') as my_file:
    contents = my_file.read()
    print(contents)
    # print(contents.rstrip())
  1. 如果要读取的文件和当前程序不在同一个目录下,需要提供文件路径。文件路径分为相对文件路径和绝对文件路径。在Windows中,文件路径采用反斜杠(),在Linux和OS X中,文件路径用斜杠(/).
    相对路径的位置是相对于当前运行的程序所在的目录的。
    绝对路径一般比较长,将其存储在一个变量file_path中,再将变量file_path传递给open()函数。
  2. 如果想要逐行的读取文件,可以对文件对象采用for循环。
    for line in file_object
  3. 注意使用关键字with的时候,open()返回的文件对象只能在with代码块内部使用。如果要在with外部使用,可以在with代码块内将文件的各行存储在一个列表中。然后在with代码块的外部对列表进行处理。
with open(filename) as file_object:
    lines = file_object.readlines()
    
for line in lines:
    print(line.rstrip())
  1. 注意,在读取文本文件的时候,python将所有的文本都解读为字符串。如果读取的是数字,想要作为数值使用,需要用int()函数转换为整数,或者用float()函数转换为浮点数。
  2. 写入文件.写入文件时,open()函数需要传入两个实参,第一个实参是写入文件的名称,第二个实参是打开的模式,'w’表示写入模式,'r’表示读取模式,'a’附加模式也就是在文件的末尾添加新的内容,'r+'表示读取和写入文件的模式。如果这个参数被省略了,则默认为以只读模式打开。
    如果要写入的文件不存在,函数open()将自动创建这个文件。如果以写入’w’模式打开文件,而这个文件已经存在了,那么python将在返回文件对象前清空该文件,对于这种情况,需要注意,要是想在原有文件基础上添加的,应该用’a’附加模式。
filename = 'programming.txt'
with open(filename, 'w') as my_file:
    my_file.write("I love python.\n")
  1. 和读取文件相同,open()写入文件时也只能接受字符串形式,要是想将数值数据存储到文本文件中,需要用str()转换为字符串格式。
  2. 函数write()不会在写入的文本末尾添加换行符,因此如果写入多行文本的时候,需要在每行的write()语句中包括换行符(\n).
  3. 处理异常,使用try-except-else代码块。
    把可能导致错误的代码放在try中,except中指定可能出现的错误类型,如果try代码块顺利运行,则运行else部分的代码。
print("Give me two numbers, and I will divide them.")
print("Enter 'q' to quit.")

while True:
    first_number = input("\nFirst number: ")
    if first_number == 'q':
        break
    second_number = input("\nSecond number: ")
    try:
        answer = int(first_number) / int(second_number)
    except ZeroDivisionError:
        print("You can't divide by 0.")
    else:
        print(answer)
try-except-else代码块的工作原理如下:Python尝试执行try代码块中的代码,只有可能引发异常的代码才需要放在try代码块中。只有当try代码块成功执行时才需要运行的代码应该放在else中。except代码块告诉python,如果在运行try代码块时引发了指定的异常,应该怎么操作。
  1. 异常有:ZeroDivisionError, FileNotFoundError等。
  2. 失败时什么都不做。
    在except部分编写pass语句,在程序遇到异常时,什么都不做,不会出现traceback, 也不会有任何输出。pass语句还可以充当占位符。
print("Give me two numbers, and I will divide them.")
print("Enter 'q' to quit.")

while True:
    first_number = input("\nFirst number: ")
    if first_number == 'q':
        break
    second_number = input("\nSecond number: ")
    try:
        answer = int(first_number) / int(second_number)
    except ZeroDivisionError:
        pass
    else:
        print(answer)
  1. 程序通常将用户的信息存储在列表和字典等数据结构中,如果在程序关闭后想要存储信息,有一种简单的方法是用json模块来存储信息。
  2. json.dump()方法和json.load()方法
    json.dump()函数接受两个参数,第一个是要存储的数据,第二个是用于存储的文件。
    首先指定用来存储数据的文件名称,通常使用文件扩展名.json表示文件存储的数据为JSON格式。以写入模式’w’打开这个文件,用json.dump()函数将数据存储到文件中。
import json

numbers = [3, 4, 5, 11, 34, 6]
filename = 'numbers.json'
with open(filename, 'w') as f_obj:
    json.dump(numbers, f_obj)

json.load()函数可以用于将文件中的数据读取到内存中。
以读取方式打开文件,用json.load()函数加载存储在文件中的信息。

import json

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

print(numbers)

json.dump()和json.load()可以实现程序之间数据的共享。

9.测试代码