Python 基础
0x01 变量和简单数据类型
动态类型语言
变量的命名和使用
1. 变量名只能包含大小写字母、数字和下划线,且不能以数字开头
2. 不能使用关键字和函数名作为变量名
3. 变量名应简短又具有描述性
数字
整数
浮点数
使用str()避免类型错误
字符串
字符串就是一系列字符。
在Python中,用单引号或者双引号包裹起来的都是字符串
字符串方法
修改大小写
name = " you tingwang "
# 首字母大写显示每一个单词
print(name.title())
# 全部转换为大写
print(name.upper())
# 全部转换为小写
print(name.lower())
# 删除空白
print(name.lstrip())
print(name.rstrip())
print(name.strip())
# 添加空白
print(\tname\n)
# 拼接字符串
greet = "hello, " + name.title()
print(greet)
注释
单行注释
# 这是一条注释
多行注释
'''
第一行注释
第二行注释
'''
Python之禅
import this
0x02 列表
列表介绍
列表由一系列按特定顺序排列的元素组成,其中的元素之间可以没有任何关系
鉴于列表通常包含多个元素,列表的名称一般指定为一个复数名字
在Python中,用方括号[]来表示列表,并用逗号来分隔其中的元素
适合存储在程序运行期间可能变化的数据集
motocycles = ['honda', 'yamaha', 'suzuki']
列表操作
访问列表元素
# 索引从0开始
print(motocycles[0])
修改元素
motocycles[0] = 'ducati'
删除元素
使用 del 语句删除
# 删除之后,无法再次访问该值
del motocycles[0]
使用 pop() 方法删除
# 删除列表末尾的元素
del_motocycle = motocycles.pop()
# 删除任何位置的元素
del_motecycle = motocycles.pop(0)
根据值删除元素
# 只删除第一个指定的值,若存在多个需要操作的对象,需要使用循环
motocycles.remove('ducati')
添加元素
末尾添加元素
motocycles.append('ducati')
任意位置插入元素
motocycles.insert(0, 'ducati')
组织列表
sort() 对列表永久性排序
# 永久性改变了列表元素的排列顺序
# 按照字母顺序
motocycles.sort()
# 与字母顺序想法的顺序
motocycles.sort(reverse=true)
sorted() 临时排序
print(sorted(motocycles))
反转列表
# reverse()永久改变列表元素的排列顺序
motocycles.recerse()
确定列表长度
len(motocycles)
数字列表
range()
# 区间左闭右开
for i in range(1, 10):
<body>
list() 和 range() 结合
# range()第三个可选步长参数
digits = list(range(1, 10, 2))
统计
min(digits)
max(digits)
sum(digits)
列表解析
squares = [values**2 for value in range(1,11)
列表使用
切片
players = ['charles', 'eli', 'martina', 'michael']
# 区间左闭右合
print(players[0:3])
遍历切片
for player in players[0:3]:
print(player)
复制列表
new_list = players[:]
0x03 元组
元组称为“不可变的列表”
使用圆括号定义元组
dimensions = (100, 200)
遍历元组
for item in dimensions:
print(item)
覆盖元组
元组元素不可变,但是可重新定义
dimensions = (50, 100)
0x04 字典
字典是一系列键-值对,每个键都与一个值相关联
与键相关联的值可以是数字、字符串、列表乃至字典
# 空字典
alien = {}
alien_0 = {'color': 'green', 'points': 5}
字典操作
访问字典中的值
# 通过键访问相应的值
print(alien_0['color'])
修改键值对
alien_0['points'] = 6
添加键值对
# 直接指定键和相关联的值
alien_0['x_position'] = 0
alien_0['y_position'] = 25
删除键值对
# 删除的键值对永远消失
del alien_0['color']
遍历字典
遍历所有键值对( items() )
user_0 = {
'user_name': 'efirmi',
'age': 18,
'country': 'China'
}
for key, value in user_0.items():
print(key)
print(value)
遍历所有键( keys())
for key in user_0.keys():
print(key)
按序遍历所有键( keys() and sorted() )
for key in sorted(user_0.keys()):
print(key)
遍历所有值( values() )
for value in user_0.values():
print(value)
嵌套
字典列表
alien_0 = {'color': 'red', 'points': 5}
alien_1 = {'color': 'brown', 'points': 3}
alien_2 = {'color': 'green', 'points': 1}
aliens = [alien_0, alien_1, alien_2]
for alien in aliens:
print(alien)
# 快速生成
for alien_number in range(30):
new_alien - {'color': 'green', 'points': 5, 'speed': 'slow'}
在字典中存储列表
ordered = {
'crust': 'thick',
'toppings': ['mushrooms', 'onion']
}
在字典中存储字典
user_0 = {
'staff': 'musician'
'age': 50,
}
user_1 = {
'staff': 'student',
'country': 'American'
}
users = {
'mike': user_0,
'john': user_1
}
0x05 条件语句
条件测试
检查是否相等
检查是否相等时不考虑大小写(针对字符串,使用 lower() 或者 upper() )
检查是否不相等
比较数字
检查多个条件
检查特定值是否在列表中
toppings = ['mushrooms', 'onions']
'mushrooms' in toppings
检查特定值是否不在列表中
'peach' not in toppings
布尔表达式
if语句
# 单个测试
if conditional_test:
do somethind
# if-else 语句
if conditional_test:
do something
else:
do other things
# if-elif-else 语句
# else 语句块可省略
if conditional_test1:
do something
elif conditional_test2:
do somethins
......
else:
do another thing
0x06 循环语句
Python 通过缩进来判断代码行与前一个代码行的关系
# 循环控制语句: break和continue
# for循环
for items in list:
<body>
# while 循环
while condition:
do something
# 在列表之间移动元素
list1 = ['alice', 'mike']
list2 = []
while list1:
temp = list1.pop()
list2.append(temp)
# 删除包含特定值的所有列表元素
pets = ['dog', 'cat', 'tiger', 'rabbit', 'goldfish']
while 'tiger' on pets:
pets.remove('tiger')
0x07 用户输入
message = input("Tell me something, and I wil repeat it back to you.")
print(message)
某些时候需要对输入进行类型转换
age = int(input("Tell me your age."))
print(f"Your age is {str(age)}")
0x08 函数
def greet(first, last):
print(f"Hello! {first.lower().title()} {last.lower().title()}")
first = input("Enter your first name:\n\t")
last = input("Enter your last name:\n\t")
# 位置实参
greet(first, last)
实参和形参的区别:
1. 形参:函数完成其工作所需的一项信息;
2. 实参:调用函数时传递给函数的信息
在Python中,函数的参数传递是通过对象应用传递的。
当一个对象被传入一个函数时,函数接收到的是对这个对象的应用,而不是对象本身的一个副本,
也就是说函数内对参数所作的修改会影响到原始的对象。
但是如果参数是不可变对象,如整数、字符串,修改参数值则不会影响到原对象,因为此时是修改的副本
传递实参
位置实参:基于实参的顺序,将函数调用中每个实参都关联到函数定义中的一个形参
关键字实参:传递给函数的名称-值对
必须准确指定函数定义中的形参名
greet(last=last, first=first)
# 或者这样
greet(first=first, last=last)
默认值:编写函数时,可给每个形参指定默认值
使用默认值时,在形参列表中必须先列出没有默认值的形参,再列出有默认值的形参
def pet(time, pet_name='dog'):
print(f"{pet_name} come here.")
返回值
# 返回一个值或者一组值
def get_formatted_name(first_name, last_name):
full_name = first_name.lower().title() + " " +
last_name.lower().title()
return full_name
musician = get_formatted_name('jimi', hendrix)
pirnt(musician)
'''
返回的值在形式上表现为一个,可以是字典,字符串,列表,元组等
'''
传递任意数量的形参
'''
*toppings中的星号让Python创建一个名为toppings的空元组,并将收到的所有值都封装到这个元组中
若要让函数接受不同类型的实参,必须在函数定义中将接纳任意数量实参的形参放在最后
'''
def make_pizza(*toppings):
# 打印顾客点的所有配料
print(toppings)
'''
形参**user_info中的星号让Python创建一个名为user_info的空字典,并将收到的所有名称-值对都封装到这
个字典中
'''
def build_profile(first, last, middle='', **user_info):
profile = {}
profile['first_name'] = first
profile['middle_name'] = middle
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)
模块
可将函数与主程序分离,将函数存储在被称为模块的独立文件中,再将模块导入到主程序
import语句允许在当前运行的程序文件中使用模块中的代码
导入整个模块
pizza.py
def make_pizza(size, *toppings):
print(f"\nMakeing a {str(size)}-inch pizza
with the following toppings: ")
for topping in toppings:
print(f"- {tpooings}")
making_pizza.py
import pizza.py
'''
import pizza.py as p
使用as给模块指定别名
'''
pizza.make_pizza(16, 'pepperoni')
pizza.make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese')
导入特定的函数
from file_name import function1_name, funciton2_name
pizza.py
def make_pizza(size, *toppings):
print(f"\nMakeing a {str(size)}-inch pizza
with the following toppings: ")
for topping in toppings:
print(f"- {tpooings}")
making_pizza.py
from pizza.py import make_pizza
'''
from pizza.py import make_pizza as mp
使用as给函数指定别名
'''
pizza.make_pizza(16, 'pepperoni')
pizza.make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese')
导入全部函数
不建议使用,使用*导入全部函数之后可通过名称直接调用每个函数,可能会与本模块的命名产生冲突>
from file_name import *
函数编写指南
给形参指定默认值时,等号两边不要有空格。对于函数调用中的关键字实参,也应遵循这种约定
0x09 类
类:表示现实世界中的事物和情景
实例化:根据类来创建对象
每一个与类相关联的方法调用都自动传递实参self,它是一个指向实例本身的引用,让实例能够访问类
中的属性和方法
clas Dog():
# 给属性指定默认值
def _init_(self, name, age):
self.name = name
self.age = age
self.owner = ''
def sit(self):
print(f"{self.name.title()} is now sitting.")
def set_owner(self, name):
self.owner = name
# 创建实例
my_dog = ('willie', 6)
your_dog = ('lucy', 10)
# 调用方法
my_god.sit()
your_dog.sit()
# 直接访问修改属性的值
my_dog.owner = 'you'
# 通过方法修改属性的值
my_dog.set_owner('you')
继承
编写类时,并非总是要从空白开始,如果要编写的类时另一个现成类的特殊版本,可使用继承
一个类继承另一个类时,将自动获得另一个类的所有属性和方法;
原有的属性称为父类,新类称为子类。
子类继承了其父类的所有属性和方法,同时还可以定义自己的属性和方法
创建子类时,父类必须包含在当前文件中,且位于子类前面
定义时,必须在括号内指定父类的名称
class Car():
def _init_(self, make, model):
self.make = make
self.model = model
self.gas_tank = 75
def fill_gas_tank(self):
self.gas_tank = 100
def get_decriptive_info(self):
print(f"Make:{self.make}, Model:{self.model}")
class Battery():
# 传参可以设置默认值
def _init(self, battery_size=70):
self.battery_size = battery_size
def describe_battery(self):
print(f"This car has a {str(self.battery_size)}-kwh battery.")
class ElectricalCar(Car):
def _init(self, make, model):
# 调用父类方法
super._init(self, make, model)
# 将实例用作属性
self.battery = Battery()
# 重写父类方法:要求方法名一致
def fill_gas_tank(self):
print("The car does not have a gas tank.")
导入类与导入函数用法一致
基本格式: from package_name import class_name , import package_name
类编码风格:
1. 类名采用驼峰命名法,即将类名中的每个单词的首字母都大写,而不使用下划线。实例名和模块名都采
用小写格式,并在单词之间加上下划线
2. 对于每一个类,都应紧跟在类定义后面包含一个文档字符串,简要描述类的功能;每个模块也都应包含
一个文档字符串,对其中的类用途进行描述
3. 在类中,使用一个空行来分隔方法;在模块中,使用两个空行来分隔类
4. 需要同时导入标准库中的模块和自行编写的模块时,先编写导入标准库模块的import语句,再添加一个
空行编写导入自行编写的模块的import语句
0x10 文件
读取文件
函数open()接受一个参数(文件名或者文件路径),在当前执行的文件所在的目录(文件路径)中查
找指定的文件
with关键字在便不再需要访问文件时需要关闭。可调用open()和close()来打开和关闭文件
实际上,Python会自动在合适的时候自动将其关闭
读取文本文件时,Python将其中的文本都解读为字符串
# 读取整个文件
with open('pi_digits.txt') as open_file:
contents = open_file.read()
print(contents)
# 逐行读取
# 文件中每一行末尾自带换行符,所以需要使用rstrip()
with open('pi_digits') as open_file:
for line in open_file:
print(line.rstrip())
# 创建一个包含文件各行内容的列表
file_name = 'pi_digits.txt'
with open(file_name) as file_object:
lines = file_object.readlines()
for line in lines:
print(line)
写入文件
调用open()函数可提供两个实参:第一个为文件名(路径),第二个为操作模式
1. 'w':写入模式,覆盖文件原有内容,不存在会新建新的文件
2. 'r':读取模式,只会查找已有的文件
3. 'a':附加模式
4. 'r+':读取和写入文件的模式
Python只能将字符串写入文本文件,要将数值数据存储到文本文件中,必须先使用函数str()将其转换
为字符串格式
# 写入空文件
file_name = 'test.txt'
with open(file_name, 'w') as file_object:
file_object.write("I love programming.")
# 写入多行
with open(file_name, 'w') as file_object:
file_object.write("I love programming.\n")
file_object.write("I love creating new games.\n")
# 附加到文件
with open(file_name 'a') as file_object:
file_object.write("T also love listening to music.\n")
案例
# 统计单词个数
def count_words(file_name):
try:
with open(file_name) as file_object:
contents = file_object.read()
expect FileNotFound:
print(f"Sorry, the file {file_name} does not exist.")
else:
words = contents.split()
num_words = len(words)
print(f'The file {file_name} has about {str(num_words)} words')
file_name = 'target.txt'
count_word(file_name)
JSON 存储数据
# number_writer.py
import json
numbers = [1, 2, 3, 4, 5]
file_name = 'numbers.json'
with open(file_name) as f_obj:
# dump()接受两个实参:要存储的数据和可用于存储数据的文件对象
json.dump(numbers, f_obj)
# number.reader.py
import json
file = 'numbers.json'
with open(file_name) as f_obj:
numbers = json.load(f_obj)
print(numbers)
重构:将代码划分为一系列完成具体工作的函数
import json
def get_stored_username():
--snip--
def get_new_user_name():
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(f"Welcome back, {username}.")
else:
username = get_new_user_name()
print(f"We'll remember you when you come back, {username}!")1
greet_user()
0x11 异常
try:
do something that could go wrong
# 异常执行
expect Error-Type:
handle exceptions
# 可直接使用pass语句
# 无异常执行
else:
do something
常见的错误类型:
FileNotFoundError
ZeroDivisionError
0x12 测试
使用Python模块unittest来测试代码
unittest模块中的断言方法
方法 用途
assertEqual(a, b) 核实a=b
assertNotEqula(a, b) 核实a!=b
assertTrue(x) 核实x为true
assertFalse(x) 核实x为false
assertIn(item, list) 核实item在list中
方法 用途
assertNotIn(item, list) 核实item不在list中
测试函数
单元测试:用于核实函数的某个方面没有问题
测试用例是一组单元测试,这些单元测试一起核实函数在各种情形下的行为都符合要求
全覆盖式测试:包含一整套单元测试,涵盖了各种可能的函数使用方式
# 要测试的函数模块:name_funciton.py
def get_formatted_name(first, last):
full_name = first + '' + last
return full_name.title()
# 测试用例:test_name_function.py
import unittest
from name_function import get_fortted_name as gfn
class NamesTestCase(unittest.TestCase):
def test_first_last_name(self):
formatted_name = get_formatted_name('janis', 'jplin')
self.assertEqula(formatted_name, 'Janis Jplin')
unittest.main()
测试类
# 需要测试的类
class AnonymousSurvey():
def _init_(self, question):
self.question = question
self.response = []
def show_question(self):
print(self.question)
def store_response(self, new_response):
self.reponse.append(new_reponse)
def sjpw_result(self):
print("Survery results:")
for response in self.responses:
print('- ' + response)
# test_anonymousSurvey.py
import unittest
from survey import AnonymousSurvey
class TestAnonmousSurvey(unittest.TestCase):
def setUp(self):
question = 'Enter your favorite language'
self.my_survey = AnonmousSurvey(question)
self.responses = ['Englise', 'Spanish', 'Mandarin']
def test_store_three_respones(self):
for response in self.responses:
self.my_survey.store_response(response)
for respoinse in slef.responses:
self.assertIn(response, self.my_survey.responses)