本笔记基于Eric Matthes著的 《Python编程从入门到实践》 整理而成。
书中习题答案可在 https://www.ituring.com.cn/book/1861 下载
列表由一系列按特定顺序排列的元素组成
格式:
Bicycles = ['trek', 'cannondale', 'redline', 'specialized']
Print(Bicyles)
list.append(element) 列表末尾添加元素
list.insert(location,element)
del list[location]
list.pop(location) 弹出末尾元素并且使用
list.remove(element) 删除列表中第一个该值,也可以使用
Numbers=list(range())
Squares=[]
For value in range(1,11):
Squares.append(value**2)
等同于
Squares=[value**2 for value in range(1,11)]
Players=[]
Print(players[1,3])
Print(players[:4]) # 表示从第一个元素到第五个元素
Print(players[4:]) # 表示从第5个元素到最后一个元素
遍历切片:使用for循环
复制列表:注意列表不能进行赋值,要将列表作为切片复制给列表变量名
Foods = vegetable[:]
dimension = (200,50)
print( dimension[0] )
dimension = (300, 100)
cars = ['bmw', 'audi', 'toyota']
for car in cars # cars记录了车企名字的list
if car == 'bmw'
...
elif:
...
else:
...
相等==
不相等!=
其余<, >, <=, >=
与,或:and, or
关键字in检查是否特定值是否在列表中
'suzuki' in cars
False
可以实现的功能:
alien = {'color': 'green, 'points': 5}
print(alien['color'])
print(alien['points'])
返回结果如下:
green
5
什么是字典:一系列 key - value 的对应。
由上述例子可以看出,由大括号{}表示一个字典,‘key’来给一个关键字命名,’:‘来对应key 和 value,’,'来表示并列的关键字
在引用时,我们使用"dictionary[‘key’]"来引用关键字key。
直接使用赋值,关键字将自动在字典内创建。
alien['x_position'] = 0
alien['y_position'] = 100
可以通过先创建一个空字典,再向其中添加键值对。
同样是通过赋值语句
通过del语句实现
del alien['x_position']
使用for语句,格式如下
user = {
'username' = 'Yilin',
'regist_date' = '2022.07.06',
'major' = 'physics'
for key, value in user.items():
print("\nKey" + key)
print("Value: " + value)
}
得到的输出为:
Key: username
Value: Yilin
Key: regist_date
Value: 2022.07.06
Key: major
Value: physics
可以看出,探测键值对是否在字典中,通过key和key对应的value值来进行判断,同时还需要在字典名后加上.item()。
值得注意的是,这个方法遍历输出的键值对顺序与存储顺序不一定相同,具体原因是因为python使用散列表(哈希表)来存储。
for name in user.keys():
print(name)
key()对于不需要value时能够很好地使用。在for 和 in 中间使用单个变量名,同样能够实现只输出key的效果,使用.keys()只是能够增加可读性
使用sorted()
for name in sorted(favorite_languages.keys()):
print(name.title() + ", thank you for taking the poll.")
for language in favorite_languages.values():
print(language.title())
这条语句能够提取字典中所有的值,但是不能判断是否重复,为了简便性,我们一般还使用set()来剔除重复项
for language in set(favourite_languages.values()):
print(language.title())
考虑以下情况:
这就是为什么我们需要 嵌套
for alien_number in range(30):
new_alien = {'color': 'green', 'point': 5, 'speed': 'slow'}
aliens.append(new_alien)
pizza = {
'crust': 'thick',
'toppings': ['mushrooms', 'extra cheese'],
}
这么做真的很酷hhh
users = {
'aeinstein': {
'first': 'albert',
'last': 'einstein',
'location': 'princeton',
}
'mcurie': {
'first': 'marie',
'last': 'curie',
'location': 'paris',
}
}
在括号内输入文字提示
message = input("Tell me something, and I will repeat it back to you: ")
print(message)
height = input("How tall are you, in inches?")
height = int(height)
不断运行直到不满足条件
number = 1
while number <= 5:
print(number)
number += 1
当有多个条件作为while语句停止运行的条件是,使用一长串 and 是一件很繁琐的事情。此时可以使用tag作为统一的退出条件。
active = True # 布尔变量作为tag
while active:
message = input(prompt)
if message == 'quit':
active = False
else:
print(message)
break使python立刻跳出整个循环,不在执行。可以用于while,for。
类似的表达在C里也有,此时可以不用考虑while处的条件判断语句。
while True:
message = input(prompt)
if message == 'quit':
break
else:
print(message)
continue可以使python跳出当前的循环,并且立即执行下一个循环。
current_number = 0
while current_number < 10:
current_number += 1
if current_number % 2 == 0:
continue
print(current_number)
总结上述结束循环的方式,有如下几种:
能够实现的操作:
定义函数和调用函数的基本语法
def greet_user():
"""问候"""
print("Hello!")
greet_user()
注意形参和实参的关系,比如有这么一条语句
name = 'Amy'
那么如果我们调用一个函数
show_name(name)
show_name('Amy')
那么第一行就调用了形参,第二行调用了实参。
具体关于实参和形参的定义请自行搜索。
在函数中预先定义的变量(形参)需要与实际信息(实参)进行对应,这种关联方式基于实参的顺序
比如:
def describe_pet(animal_type, pet_name):
print(pet_name.title() + " is a " + animal_type + ".")
describe_pet('dog', 'wangcai')
describe_pet('wangcai', 'dog')
你希望旺财是一只狗,而不是狗是一只旺财,因此调用函数需要采用第一种调用方式。
这体现了位置实参的顺序十分重要。
可以直接将输入的实参与形参对应起来,这样顺序就不那么重要了。
下面两行代码是等价的:
describe_pet(animal_type = 'dog', pet_name = 'wangcai')
describe_pet(pet_name = 'wangcai', animal_type = 'dog')
可以通过在定义函数时就加入形参的默认值,在没有输入指定形参时python会自动用默认值代替。
def describe_pet(animal_type = 'dog', pet_name):
print(pet_name.title() + " is a " + animal_type + ".")
describe_pet('wangcai')
基于上述的三种方式,可以实现不同的函数调用方式。
def get_formatted_name(first_name, last_name):
full_name = first_name + ' ' + last_name
return full_name.title()
musician = get_formatted_name('jimi', 'hendrix')
print(musician)
可以看出,这里函数返回了字符串full_name,同时通过调用函数将full_name赋值给了musician,因此能够通过print将该字符串输出。
如果存在中间名,我们需要输出;但是不是所有人都有中间名,因此我们将中间名的默认值设为一个空串。
def get_formatted_name(first_name, middle_name="", last_name):
full_name = first_name + ' ' + middle_name + ' ' + last_name
return full_name.title()
或者使用if语句来判断实参非默认值
def get_formatted_name(first_name, middle_name="", last_name):
if middle_name:
full_name = first_name + ' ' + middle_name + ' ' + last_name
else:
full_name = first_name + ' ' + last_name
return full_name.title()
def build_person(first_name, last_name):
person = {
'first' = first_name,
'last' = last_name,
}
return person
python能够将列表作为参数传递给函数,我们可以在函数内实现列表的遍历等操作,以此实现大量数据的处理
def greet_users(names):
for name in names:
msg = "Hello, " + name.title() + " !"
print(msg)
但是记住只有while能够对列表进行修改,此时修改其中内容需要用到最原始的 list_name[n] = xxxx 来实现
这里就不再赘述列表修改的操作了,具体操作可以看前面几章的笔记
可以在函数调用的时候使用列表的切片
print_models(unprinted_design[:], completed_models)
对于大型的列表尽量使用原始列表,这样能够节省创建切片时产生的内存和时间占用。
对于预先未知数量的实参,可以在形参名上加一个’*'。星号的作用是让python创建一个空元组,将所有输入的实参封装到 元组 里
def make_pizza(*toppings):
print(toppings)
make_pizza('pepperoni')
make_pizza('mushrooms', 'green peppers', 'extra cheese')
在同时使用位置实参和任意数量实参时,我们需要将任意数量实参放在函数的最后。
def make_pizza(size, *toppings)
在参数前面加上两个星号’**',python能够创造一个空字典,以接受关键字实参(键值对)
def occupation(**people):
"""录入人的职业"""
profile = {}
for name, career in people:
profile['name'] = career
# 调用格式
occupation(Amy='programer', david='singer')
python可以导入其他存储为.py文件的函数模块。现在假设命名为pizza.py的文件里存储了一个名为make_pizza()的函数
import pizza # 导入模块
pizza.make_pizza() # 模块中函数的调用格式
然后能够使用as给模块改名字
import pizza as p
p.make_pizza()
同样我们能够只导入模块中的单个或多个函数, 此时调用不需要模块的前缀,如:
from pizza import make_pizza(), eat_pizza()
make_pizza()
eat_pizza()
导入模块的所有函数使用’*’
from pizza import *
make_pizza()
eat_pizza()
注意:
实用类创建对象,定义的一大类对象都拥有通用的行为,然后根据需要赋予每个个体独立的特性。类传递了 面向对象编程 的理念。
class Dog():
"""狗狗模拟"""
def __init__(self, name, age):
"""初始化属性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!")
my_dog = Dog('wangcai', 4) # 初始化my_dog
my_dog.sit()
my_dog.roll_over()
添加属性的默认值,如下文中odometer_reading = 0
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):
...
def read_odometer(self):
print("This car has " + str(self.odometer_reading) + " miles on it")
my_new_car = Car('audi', 'a4', 2016)
print(my_new_car.get_descriptive_name())
my_new_car.odometer_reading = 23 # 更新里程表的公里数
my_new_car.read_odometer()
class Car():
...
def update_odometer(self, mileage):
if mileage >= self.odometer_reading:
"""防止回调"""
self.odometer_reading = mileage
else:
print("You can't roll back an odometer.")
class Car():
...
def increment_odometer(self, miles):
self.odometer_reading += miles
编写类(子类)时,可以从已有的类(父类) 继承 其所有的属性和方法,同时能够定义自己特殊的属性和方法 。
class ElectricCar(Car):
def __init__(self, make, model, year):
"""初始化父类的属性"""
super().__init__(make, model, year) # 关联父类和子类,注意没有参数self
self.battery_size = 70 # 添加ElectricCar的独特属性
def describe_battery(self):
"""属于ElectricCar的方法"""
print("This car has a " + str(self.battery_size) + "-kWh battery.")
my_tesla = ElectricCar('tesla', 'model s', 2016)
print(my_tesla.get_descriptive_name)
my_tesla.describe_battery
super()函数能够帮助python把父类和子类关联起来,让ElectricCar包含父类的所有属性。
如果父类中的方法不适用于子类,可以创建同名方法来进行覆盖。
在扩充类的属性和方法时,可以通过将某些小类将大类进行拆分。
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):
def __init__(self, make, model, year):
super().__init__(make, model, year)
self.battery = Battery() # 将电池的属性初始化为一个类Battery()
my_tesla = ElectricCar('tesla', 'model s', 2016)
print(my_tesla.get_descriptive_name())
my_tesla.battery.describe_battery() # 调用Battery()中的方法
我们假设我们将class存储到了名为file_name的模块中
from file_name import Class_name1, Class_name2
import file_name
为了防止某一个模块过大,我们可以通过在模块中导入类的方式来避免这个问题,也就是说,我们可以在模块中导入模块。
python自带的默认库
假设有一个名为pi_digit.txt的文件存储了圆周率的值,我们通过python程序能够进行以下操作:
with open('pi_digit.txt') as file_object:
contents = file_objects.read()
print(contents.rstrip())
以上代码说的是,打开一个名为pi_digit.txt的文件,将文件赋值给变量file_object。然后通过.read()函数获取文件内容。最后使用print进行输出。
这个过程需要注意以下几点:
上述方法只适用于文件存储在同一个文件夹的同一级下。方法分为绝对路径和相对路径,这里我认为绝对路径能够解决所有问题,直接把文件路径在文件资源管理器中找到并复制即可。
file_path = 'C:\user\ehmatthes\other_files\text_files\file_name'
with open(file_path) as file_object:
with open(file_name) as file_object:
for line in file_object:
print(line.rstrip())
文件内容只能够在with代码块中可用,要对于文件进行处理,可以创建一个列表来将文件存储在其中。
with open(file_name) as file_object:
lines = file_object.readlines()
for line in lines:
print(line.rstrip())
方法readlines()能够将每一行分别作为字符串存储在列表当中。
在open()中存在第二个实参:
with open(file_name, 'w') as file_object:
file_object.write("I love programming.\n") # 写入时需要手动换行
file_object.write("I love creating new games.")
在上述写入空文件的例子中,将实参改为’a’即可。
在做练习的时候,遇见了许多问题:
1.
FileNotFoundError: [Errno 2] No such file or directory: 'learning_python'
VScode使用的终端,默认文件位置是python的默认位置,而不是程序文件的位置,所以要使用绝对引用。
UnicodeDecodeError: 'gbk' codec can't decode byte 0x81 in position 89: incomplete multibyte sequence
python读取文件路径时默认使用ASCII,若是保存路径中存在中文会报错,在open时可以添加如下属性:
with open(path, encoding='utf-8') as file_object:
SyntaxError: (unicode error) 'unicodeescape' codec can't decode bytes in position 2-3: truncated \UXXXXXXXX escape
字符串中的’‘会引起转义,可在字符串前面(外面)加上’r’
path = r"C:\Users\linli\Desktop\Python_work\10.文件和异常\learning_python.txt"
file_name = input("Please enter your name: ")
path = r"C:\Users\linli\Desktop\Python_work\10.文件和异常"
path += r"\" + file_name + ".txt" # 这一行出错
with open(path, 'w', encoding='utf-8') as file_object:
file_object.write(file_name)
运行时错误如下:
SyntaxError: EOL while scanning string literal
解决:python不支持将\作为字符串最后一个字符,即使加了r。因此方法应该如下:
path += "\\" + file_name + ".txt"
为了避免程序在错误时停止,同时出现难以理解的traceback,我们可以通过try-expect-else代码块使程序继续运行,同时显示友好的提示。
例如,在进行除法运算时,可能会出现ZeroDivisionError异常,处理方式如下:
print("Give me 2 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("\nsecond number: ")
if second_number == 'q':
break
try:
answer = int(first_number) / int(second_number)
except ZeroDivisionError:
print("You can't divide by 0!")
else:
print(answer)
如果希望在出错时不进行任何操作,可以使用pass语句
try:
answer = int(first_number) / int(second_number)
except ZeroDivisionError:
pass # 跳过错误
else:
print(answer)
使用模块json(JavaScript Object Notation)来存储数据:
json能够将简单的python数据结构转存到文件中,并在程序再次运行时加载该文件中的数据。你还可以使用json在Python程序或者其他语言之间分享数据。
json.dump()存储数字列表
import json
numbers = [2, 3, 5, 7, 11, 13]
filename = 'numbers.json'
with open(filename, 'w') as f_obj:
json.dump(numbers, f_obj) # 第一个实参为存储的数据,第二个实参为存储的文件对象
使用json.load()将这个列表读取到内存中(从json文件中提取数据并进行使用)
import json
filename = 'numbers.json'
with open(filename) as f_obj:
numbers = json.load(f_obj)
print(numbers)
使用Python标准库中的模块unitest来测试函数的稳定性和各种可能的使用方式。
如果各位有书的话,书上有详尽的unitest使用方法,这里就不在赘述了。