本篇博客的内容是《python编程从入门到实践》的精简版,主要是书中(本人认为的)重点精简,以及自己学习的一些理解。
文章目录
- 更好的阅读体验
- 变量和简单的数据类型
- 变量
- 字符串
- 字符串的几种定义方法
- 字符串拼接
- 列表简介
- 列表是什么
- 运行结果:列表的方括号也会被打印出来,但有时候我们不希望打印出来方括号 ![1.png](https://img-blog.csdnimg.cn/img_convert/784ab5aa97cea6a75ab4acefd0d8a29f.png)
- 修改、添加、删除列表中的元素
- 倒序
- 列表长度
- 操作列表
- 遍历整个列表
- 创建数值列表
- 使用列表的一部分
- 切片
- 复制列表
- 元组
- if语句
- 条件测试
- 1、检查多个条件时要用or或者and
- 2、检特定值是否包含在列表中
- 检验特定值是否不包含在列表中
- if语句
- 字典
- 字典的一些使用
- 如何对字典中的值进行访问
- 添加键值对
- 创建一个空字典
- 修改字典中的值
- 删除键值对
- 使用get()方法来访问值
- 遍历字典
- 遍历所有键值对
- 遍历字典中所有的键
- 遍历字典中的所有值
- 按特定的顺序遍历字典中的所有键
- 嵌套
- 字典列表
- 字典中存储列表
- 用户输入和while()循环
- 用户输入
- while循环
- 函数
- 定义函数
- 传递参数
- 位置参数
- 关键字实参
- 默认值
- 返回值
- 返回简单值
- 让实参变成可选
- 传递列表
- 在函数中修改列表
- 禁止函数修改列表
- 传递任意数量的实参
- 使用任意数量的关键字实参
- 将函数存储在模块中
- 导入整个模块
- 导入特定的函数
- 使用as给函数指定别名
- 使用as给模块指定别名
- 导入模块中的所有函数
- 类
- 创建和使用类
- 创建dog类
- 根据类创建实例
- 使用类和实例
- Car类
- 给属性指定默认值
- 修改属性的值
- 继承
- 子类的方法_init_()
- 给子类定义属性和方法
- 重写父类的方法
- 将实例用作属性
- 导入类
- 导入单个类
- 在一个模块中存储多个类
- 从一个模块中导入多个类
- 导入整个模块
- 导入模块中的所有类
- 在一个模块中导入另一个模块
- 使用别名
- Python标准库
- 类的命名规则
- 文件和异常
- 读文件中的数据
- 直接读整个文件
- 文件路径
- 逐行读取
- 创建一个包含文件各行内容的列表
- 将数据写回文件
- 写入空文件
- 写入多行
- 附加到文件
- 异常
- 除零异常ZeroDivisionError异常
- try-except代码块
- else
- 静默失败
- 存储数据
- 测试代码
- 测试函数
- 单元测试和测试用例
- 可通过的测试
- 测试类
- 各种断言方法
- 一个要测试的类
- 测试AnonymousSurvey类
- 方法setUp()
- 基础语法部分完结撒花!!!
更好的阅读体验
变量和简单的数据类型
变量
变量的命名规则:
1、只能包含字母、数字和下划线,并且不能以数字开头
2、变量名中不能是python中的保留字
字符串
字符串的几种定义方法
name = 'Bob'
name = "Bob"
name = """Bob"""
如何字符串本身包含单引号或者双引号,我们可以用与包含相反的方式去定义,也可以使用转移字符
字符串拼接
name = "Bob"
str = ' like alice'
print(name + str)
另一种方式的拼接
class_name = 123
avg_salary = 1345
message = "sdadas%s%s" %(class_name, avg_salary)
print(message)
%:表示占位符
s:表示字符串
多个变量占位时要用括号
拼接字符串的另一种用法这种方式称为f字符串的方式
class_name = 123
avg_salary = 1345
message = "sdadas%s%s" %(class_name, avg_salary)
full_name = f"{class_name} {avg_salary} {message}"
print(full_name)
这种拼接方式也很便捷,我们不关心类型,只需要将变量用花括号括起来就行但有一点不好的地方就是这种方式不能控制变量的精度
num = input("请输入一个数字")
num = int (num)
print(num)
列表简介
列表是什么
1、列表由一系列按特定顺序排列的元素组成。
2、列表中通常包含多个元素,因此给列表指定一个表示复数的名称比较好
3、python中用[]来表示列表
bicycles = ['trek', 'cannondable', 'redline', 'specialized']
print(bicycles)
运行结果:列表的方括号也会被打印出来,但有时候我们不希望打印出来方括号
这里列表中元素的类似c语言中的数组
bicycles = ['trek', 'cannondable', 'redline', 'specialized']
print(bicycles[0])
python中下标也是从0开始的,另外python中将索引指定为-1可以访问列表中的最后一个元素
bicycles = ['trek', 'cannondable', 'redline', 'specialized']
print(bicycles[-1])
修改、添加、删除列表中的元素
1、修改
motorcycles = ['honada', 'yamaha', 'suzuki']
print(motorcycles)
motorcycles[0] = 'ducati'
print(motorcycles)
2、添加元素
(1)、在列表吗末尾添加元素
用到的方法是append()
motorcycles = ['honada', 'yamaha', 'suzuki']
print(motorcycles)
motorcycles.append('ducati')
print(motorcycles)
(2)、在列表中插入元素
用到的方法是insert(index, data)
这里是插入到下标为index的位置
motorcycles = ['honada', 'yamaha', 'suzuki']
print(motorcycles)
motorcycles.insert(1, 'ducati')
print(motorcycles)
3、删除元素
a、使用del语句删除元素(前提是知道要删除元素在列表中的位置)
motorcycles = ['honada', 'yamaha', 'suzuki']
print(motorcycles)
del motorcycles[1]
print(motorcycles)
b、使用pop方法
pop方法可以删除列表末尾的元素,同时返回刚被弹出的元素
motorcycles = ['honada', 'yamaha', 'suzuki']
print(motorcycles)
popped_motorcycle = motorcycles.pop()
print(motorcycles)
print(popped_motorcycle)
c、弹出列表中任何位置的元素
motorcycles = ['honada', 'yamaha', 'suzuki']
print(motorcycles)
popped_motorcycle = motorcycles.pop(1)
print(motorcycles)
print(popped_motorcycle)
d、根据值删除元素
remove只删除找到的第一个元素,如果存在多个值相同的元素时
motorcycles = ['honada', 'yamaha', 'suzuki']
print(motorcycles)
motorcycles.remove('yamaha')
print(motorcycles)
4、排序
(1)、使用sort()方法对列表永久排序默认按字典序排序
cars = ['audi', 'bmw', 'toyota', 'subaru']
print(cars)
cars.sort()
print(cars)
sort()方法中可以传入参数,来改变排序规则
cars = ['audi', 'bmw', 'toyota', 'subaru']
print(cars)
cars.sort(reverse = True)
print(cars)
(2)、使用sorted函数对列表进行临时排序
cars = ['audi', 'bmw', 'toyota', 'subaru']
print(cars)
new_cars = sorted(cars)
print(new_cars)
print(cars)
倒序
用到主要是reverse方法
cars = ['audi', 'bmw', 'toyota', 'subaru']
print(cars)
cars.reverse()
print(cars)
列表长度
用到的是len函数
cars = ['audi', 'bmw', 'toyota', 'subaru']
print(cars)
cnt = len(cars)
print(cnt)
操作列表
遍历整个列表
magicians = ['alice', 'david', 'carolina']
for magician in magicians:print(magician)
上面的程序中就用到了python中的循环,当我们遍历时循环是必不可少的
python是根据缩进来判断代码行与前一个代码行的关系
循环中常见的问题:
1、缩进问题
2、冒号容易漏写
创建数值列表
使用的是range()函数
magicians = ['alice', 'david', 'carolina']
for i in range(0, 3):print(magicians[i])
range(i, j)生成一个从i到j-1的数值列表
使用range()创建一个数字列表
使用list函数和range()函数结合
numbers = list(range(1, 6))
print(numbers)
对数字列表进行简单的计算的函数
numbers = list(range(1, 6))
print(numbers)
print(min(numbers))
print(max(numbers))
print(sum(numbers))
使用列表的一部分
切片
处理列表中的部分元素就叫切片
players = ['charles', 'martina', 'michael', 'florence', 'eli']
print(players)
print(players[0:3])
如果前面一项缺即players[:4]默认从列表的起始位置开始, players[1:]默认到最后部分结束, 也可以在括号里面指定第三个之表示隔几个元素取一个(和matlab很像,不过python的间隔是在最后,matlab是在中间设置)
players = ['charles', 'martina', 'michael', 'florence', 'eli']
print(players)
print(players[0:6:2])
遍历切片
players = ['charles', 'martina', 'michael', 'florence', 'eli']
print(players)
new_players = players[0:6:2]
for player in new_players:print(player)print("over")
复制列表
可以用包含列表中所有元素的切片复制
players = ['charles', 'martina', 'michael', 'florence', 'eli']
print(players)
new_players = players[:]
print(new_players)
也可以直接复制
players = ['charles', 'martina', 'michael', 'florence', 'eli']
print(players)
new_players = players
print(new_players)
元组
元组和列表类似,但是元组中的数据不可修改,并且元组使用()圆括号标识
用法很多都和列表类似不再赘述
if语句
条件测试
1、检查多个条件时要用or或者and
age_0 = 22
age_1 = 18
print(age_0 >= 21 and age_1 >= 21)
2、检特定值是否包含在列表中
players = ['charles', 'martina', 'michael', 'florence', 'eli']
print('eli' in players)
结果:True
检验特定值是否不包含在列表中
players = ['charles', 'martina', 'michael', 'florence', 'eli']
print('eli' not in players)
结果:False
if语句
格式:
1、基本if语句
if conditindl_test:do something
2、if-else语句
if conditindl_test:do something
else:do something
3、if-elif-else语句
if conditindl_test:do something
elif conditindl_test:do something
else:do something
字典
字典的一些使用
字典时一系列键值对,每个键与一个值,与键相关联的值可以是数、字符串、列表乃至字典
字典用放在花括号中的一系列键值对表示
alien_0 = {'color' : 'green'}
这个字典中只存储了一个键值对,具体来说color时键,green是值
如何对字典中的值进行访问
alien_0 = {'color' : 'green'}
print(alien_0['color'])
添加键值对
alien_0 = {'color' : 'green'}
alien_0['X-position'] = 0
alien_0['y_position'] = 25
print(alien_0)
创建一个空字典
alien_0 = {}
修改字典中的值
alien_0 = {'color' : 'green'}
print(alien_0)
alien_0['color'] = 'yellow'
print(alien_0)
删除键值对
使用del语句
alien_0 = {'color' : 'green', 'position' : 5}
print(alien_0)
del alien_0['position']
print(alien_0)
使用get()方法来访问值
如果我们直接访问字典中一个不存在键值对时,这时python会报错,如果我们使用get()方法则不会报错会返回一个我们指定的信息
alien_0 = {'color' : 'green', 'position' : 5}
print(alien_0)
print(alien_0['a'])
如果使用get()方法
alien_0 = {'color' : 'green', 'position' : 5}
print(alien_0)
print(alien_0.get('a', 'No find'))
如果get()方法的第二个参数没有指定,这时候get()方法会返回一个None表示不存在我们要找的这样的键值对
遍历字典
遍历所有键值对
一个小例子
user = {'username' : 'efermi','first' : 'enrico','last' : 'fermi',
}
for k, v in user.items():print(f"\nKey:{k}")print(f"value{v}")
这个例子中我们用k,v两个变量分别保存键和值,然后调用items()方法
遍历字典中所有的键
favorite_languages = {'jen' : 'python','sarah' : 'c','edward' : 'ruby','phil' : 'python'
}
for name in favorite_languages.keys():print(name)
遍历字典中的所有值
favorite_languages = {'jen' : 'python','sarah' : 'c','edward' : 'ruby','phil' : 'python'
}
for language in favorite_languages.values():print(language)
按特定的顺序遍历字典中的所有键
favorite_languages = {'jen' : 'python','sarah' : 'c','edward' : 'ruby','phil' : 'python'
}
for name in sorted(favorite_languages):print(name)
嵌套
字典列表
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]
print(aliens)
for alien in aliens:print(alien)
字典中存储列表
pizza = {'crust' : 'a','toppings' : ['mushrooms', 'extra chrrse'],
}
for topping in pizza['toppings']:print(topping)
另外还有字典中套字典的用法,用法都是一样的不再赘述
用户输入和while()循环
用户输入
print("请告诉我你是谁")
name = input()
print("我是" + name)# input()还可以传参数
name = input("请告诉我,你是谁")
print(name)
需要注意的是不管我们输入的是什么类型的数据都会被input函数当成字符串类型的数据处理,如果想要得到我们想要得到的数据类型就需要进行类型转化
while循环
while的基本用法这里不再说了很简单只说一下while处理字典和列表
unconfirmed_users = ['alice', 'brain', 'candace']
confirmed_users = []while unconfirmed_users:current_user = unconfirmed_users.pop()print(f"Verifying user : {current_user}")confirmed_users.append(current_user)print("\nThe following users have been confirmed:")
for confirmed_user in confirmed_users:print(confirmed_user)
删除为特定值的所有列表元素
pets = ['dog', 'cat', 'dog', 'goldfish', 'cat', 'rabbit', 'cat']
print(pets)
while 'cat' in pets:pets.remove('cat')
print(pets)
函数
定义函数
def greet_user():"""显示简单的问候语"""print("Hello")greet_user()
def 告诉python,这里要定义一个函数,括号里面是参数
“”“”""里面可以放注释
def greet_user(username):"""显示简单的问候语"""print(f"Hello {username}")greet_user('jack')
传递参数
上面其实已经提到了参数的传递这里具体介绍几种传递参数的方法
位置参数
python调用函数时,必须将每个实参都关联到函数定义的一个形参中,最简单的关联方式就是基于实参的顺序
def describle_pet(animal_type, pet_name):"""显示宠物信息"""print(f"\nI have a {animal_type}")print(f"My {animal_type}'s name is {pet_name.title()}.")describle_pet('dog', '豆豆')
关键字实参
关键字实参是传递参数给函数的名称值对
def describle_pet(animal_type, pet_name):"""显示宠物信息"""print(f"\nI have a {animal_type}")print(f"My {animal_type}'s name is {pet_name.title()}.")describle_pet(animal_type = 'dog', pet_name = '豆豆')
默认值
# 给形参指定默认值时,等号两边不要有空格
def describle_pet(animal_type, pet_name='豆豆'):"""显示宠物信息"""print(f"\nI have a {animal_type}")print(f"My {animal_type}'s name is {pet_name.title()}.")describle_pet(animal_type = 'dog')
返回值
返回简单值
def get_formatted_name(first_name, last_name):full_name = f"{first_name} {last_name}"return full_namemusician = get_formatted_name('jimi', 'hendrix')
print(musician)
让实参变成可选
def get_formatted_name(first_name, last_name, middle_name = ''):if middle_name != '' :name = f"{first_name} {middle_name} {last_name}"else:name = f"{first_name} {last_name}"return name.title()musician = get_formatted_name('jimi', 'hendrix')
print(musician)
传递列表
def greet_user(names):"""向列表中的每位用户发出简单的问候"""for name in names:msg = f"Hello {name}"print(msg)names = ["Bob", "alen", 'alice']
greet_user(names)
在函数中修改列表
unprinted_designs = ['phone case', 'robot pendant', 'dodecahedrom']
completed_models = []while unprinted_designs:current_design = unprinted_designs.pop()print(f"Printing model:{current_design}")completed_models.append(current_design)print("\nThe following models have been printed:")
for completed_model in completed_models:print(completed_model)
禁止函数修改列表
有时候我们是不希望函数去修改原列表的,这时我们可以传入列表的切片副本
传递任意数量的实参
def make_pizza(*toppings):"""打印顾客点的所有配料"""print(toppings)
make_pizza('pepperoni')
make_pizza('mushrooms', 'green peppers', 'extra cheese')
形参名中的*让python创建一个名为toppings的空元组,并将收到的所有值都封装到这个元组中
def make_pizza(*toppings):"""打印顾客点的所有配料"""for topping in toppings:print(topping)
make_pizza('pepperoni')
make_pizza('mushrooms', 'green peppers', 'extra cheese')
使用任意数量的关键字实参
def build_profile(first, last, **user_info):user_info['first_name'] = firstuser_info['last_name'] = lastreturn user_infouser_profile = build_profile('a', 'b', location = 'CN', filed = 'CS')print(user_profile)
两个星号是让python创建一个名为user_info的字典,所有传递的参数都放在这个字典中
将函数存储在模块中
我们都知道使用函数的优点是可以将代码块和主程序分离,我们还可以进一步将函数存储在称为模块的独立文件中,再将模块导入到主程序中。import语句允许在当前运行的文件中使用模块中的代码
导入整个模块
要想让函数可以导入首先我们需要创建模块,模块的扩展名.py文件
def make_pizza(size, *toppings):print(f"\nMakeing a {size}-inch pizza with the following toppings:")for topping in toppings:print(f"- {topping}")
接下来我们需要在pizza.py所在的目录下创建一个.py文件,在这个文件中我们导入刚创建的模块,在调用make_pizza()两次
import pizza
pizza.make_pizza(16, 'pepperoni')
pizza.make_pizza(12, 'mushroome', 'green peppers', 'extra cheese')
导入特定的函数
语法格式如下:
from module_name import function_name
# 如果需要导入多个函数,用逗号分隔开即可,(偷偷多一嘴,都需要导入很多函数了不如直接把模块导进去)
from pizza import make_pizza
pizza.make_pizza(16, 'pepperoni')
pizza.make_pizza(12, 'mushroome', 'green peppers', 'extra cheese')
使用as给函数指定别名
如果要导入的函数名称可能和程序中现有的名称冲突,或则函数名太长,可以指定简短而独一无二的别名,别名是函数的另一个名称,类似于外号,如果我们想给函数起外号就必须在导入它的时候指定
from pizza import make_pizza as mp
mp(16, 'pepperoni')
mp(12, 'mushroome', 'green peppers', 'extra cheese')
需要注意当我们给函数指定别名以后在这个导入模块的程序中就只能使用这个别名了而不能使用之气那的名字可
使用as给模块指定别名
import pizza as p
p.make_pizza(16, 'pepperoni')
p.make_pizza(12, 'mushroome', 'green peppers', 'extra cheese')
导入模块中的所有函数
from pizza import *
make_pizza(16, 'pepperoni')
make_pizza(12, 'mushroome', 'green peppers', 'extra cheese')
类
创建和使用类
创建dog类
## 定义一个Dog类,在python中首字母大写的名称是类
class Dog:"""一次模拟小狗的简单尝试"""def __init__(self, name, age):"""初始化属性name和age"""self.name = nameself.age = agedef sit(self):"""模拟小狗收到命令时蹲下"""print(f"{self.name} is now sitting!")def roll_over(self):"""模拟小狗收到命令时打滚"""print(f"{self.name} rolled over!")
方法_init_()
类中的函数称为方法(和java一样)
这里的_init()_方法类似于构造器,每当根据GDog类创建实例的时候都会调用,为了避免和python中的普通方法发生命名冲突,每个这种方法前后都需要加上下划线。
再说参数,我们上面的例子有三个参数self、name、age,在这个方法中self是必不可少的,并且必须位于其他形参前面,self是一个指向实例本身的引用,像self.age = age这样通过实例访问的变量成为属性
根据类创建实例
## 定义一个Dog类,在python中首字母大写的名称是类
## 定义一个Dog类,在python中首字母大写的名称是类
class Dog:"""一次模拟小狗的简单尝试"""def __init__(self, name, age):"""初始化属性name和age"""self.name = nameself.age = agedef sit(self):"""模拟小狗收到命令时蹲下"""print(f"{self.name} is now sitting!")def roll_over(self):"""模拟小狗收到命令时打滚"""print(f"{self.name} rolled over!")my_dog = Dog('豆豆', 6)
print(f"My dog's name is {my_dog.name}")
print(f"My dog is {my_dog.name} years old.")
my_dog.sit()
my_dog.roll_over()
运行结果:
1、访问属性我们可以通过.来进行访问my_dog.name、my_dog.age
2、调用方法:也是通过.
3、可以通过一个类来创建多个实例
使用类和实例
Car类
class Car:"""一次模拟汽车的简单尝试"""def __init__(self, make, model, year):self.make = makeself.model = modelself.year = yeardef get_descriptive_name(self):"""返回整洁的描述性信息。"""long_name = f"{self.year} {self.make} {self.model}"return long_name.title()my_new_car = Car('audi', 'a4', 2019)
print(my_new_car.get_descriptive_name())
给属性指定默认值
class Car:"""一次模拟汽车的简单尝试"""def __init__(self, make, model, year):self.make = makeself.model = modelself.year = yearself.odometer_reading = 0def get_descriptive_name(self):"""返回整洁的描述性信息。"""long_name = f"{self.year} {self.make} {self.model}"return long_name.title()def read_odometer_reading(self):print(f"This car has {self.odometer_reading} miles on it")my_new_car = Car('audi', 'a4', 2019)
print(my_new_car.get_descriptive_name())
my_new_car.read_odometer_reading()
修改属性的值
1、直接修改
class Car:"""一次模拟汽车的简单尝试"""def __init__(self, make, model, year):self.make = makeself.model = modelself.year = yearself.odometer_reading = 0def get_descriptive_name(self):"""返回整洁的描述性信息。"""long_name = f"{self.year} {self.make} {self.model}"return long_name.title()def read_odometer_reading(self):print(f"This car has {self.odometer_reading} miles on it")my_new_car = Car('audi', 'a4', 2019)
print(my_new_car.get_descriptive_name())my_new_car.odometer_reading = 23
my_new_car.read_odometer_reading()
2、通过方法修改属性值
class Car:"""一次模拟汽车的简单尝试"""def __init__(self, make, model, year):self.make = makeself.model = modelself.year = yearself.odometer_reading = 0def get_descriptive_name(self):"""返回整洁的描述性信息。"""long_name = f"{self.year} {self.make} {self.model}"return long_name.title()def read_odometer_reading(self):print(f"This car has {self.odometer_reading} miles on it")def update_odometer(self, mileage):self.odometer_reading = mileagemy_new_car = Car('audi', 'a4', 2019)
print(my_new_car.get_descriptive_name())my_new_car.update_odometer(100)
my_new_car.read_odometer_reading()
继承
编写类的时候并非都是要从空白开始,如果我们要编写的类是另一个类的特殊版本我们就可以使用继承。一个类继承另一个类的时候,将自动获取另一个类的所有属性和方法。原有的类称为父类,新类称为子类,子类不仅可以继承父类的所有属性和方法还可以定义自己的属性和方法(和java中的继承一样)
子类的方法_init_()
在既有类的基础上编写新类时,通常我们需要调用父类的_init_()方法初始化父类中定义在_init_()中的属性
class Car:"""一次模拟汽车的简单尝试"""def __init__(self, make, model, year):self.make = makeself.model = modelself.year = yearself.odometer_reading = 0def get_descriptive_name(self):"""返回整洁的描述性信息。"""long_name = f"{self.year} {self.make} {self.model}"return long_name.title()def read_odometer_reading(self):print(f"This car has {self.odometer_reading} miles on it")def update_odometer(self, mileage):self.odometer_reading = mileageclass ElectricCar(Car):"""电动汽车的独特之处"""def __int__(self, make, model, year):super().__init__(make, model, year)my_tesla = ElectricCar('tesla', 'model s', 2019)
print(my_tesla.get_descriptive_name())
相信学过面向对象的友友们应该对这些都比较熟悉,super这里在java中也出现过就是代表父类,python中是通过super()这个函数来调用父类的方法
给子类定义属性和方法
class Car:"""一次模拟汽车的简单尝试"""def __init__(self, make, model, year):self.make = makeself.model = modelself.year = yearself.odometer_reading = 0def get_descriptive_name(self):"""返回整洁的描述性信息。"""long_name = f"{self.year} {self.make} {self.model}"return long_name.title()def read_odometer_reading(self):print(f"This car has {self.odometer_reading} miles on it")def update_odometer(self, mileage):self.odometer_reading = mileageclass ElectricCar(Car):"""电动汽车的独特之处"""def __init__(self, make, model, year):super().__init__(make, model, year)self.battery_size=75def describe_battery(self):"""打印一条描述电瓶容量的消息"""print(f"This car has a {self.battery_size}-kWh battery.")my_tesla = ElectricCar('tesla', 'model s', 2019)
print(my_tesla.get_descriptive_name())
my_tesla.describe_battery()
重写父类的方法
class Car:"""一次模拟汽车的简单尝试"""def __init__(self, make, model, year):self.make = makeself.model = modelself.year = yearself.odometer_reading = 0def get_descriptive_name(self):"""返回整洁的描述性信息。"""long_name = f"{self.year} {self.make} {self.model}"return long_name.title()def read_odometer_reading(self):print(f"This car has {self.odometer_reading} miles on it")def update_odometer(self, mileage):self.odometer_reading = mileagedef fill_gas_tank(self):print('This car has a big gas tank')class ElectricCar(Car):"""电动汽车的独特之处"""def __init__(self, make, model, year):super().__init__(make, model, year)self.battery_size=75def describe_battery(self):"""打印一条描述电瓶容量的消息"""print(f"This car has a {self.battery_size}-kWh battery.")def fill_gas_tank(self):print("This car doesn't need a gas tank!")my_tesla = ElectricCar('tesla', 'model s', 2019)
print(my_tesla.get_descriptive_name())
my_tesla.fill_gas_tank()
将实例用作属性
class Car:"""一次模拟汽车的简单尝试"""def __init__(self, make, model, year):self.make = makeself.model = modelself.year = yearself.odometer_reading = 0def get_descriptive_name(self):"""返回整洁的描述性信息。"""long_name = f"{self.year} {self.make} {self.model}"return long_name.title()def read_odometer_reading(self):print(f"This car has {self.odometer_reading} miles on it")def update_odometer(self, mileage):self.odometer_reading = mileageclass Battery:"""一次模拟电动汽车电瓶的简单尝试"""def __init__(self, battery_size=75):"""初始化电瓶的属性值"""self.battery_size = battery_sizedef describe_battery(self):"""打印一条描述电瓶容量的消息"""print(self.battery_size)class ElectricCar(Car):"""电动汽车的独特之处"""def __init__(self, make, model, year):super().__init__(make, model, year)self.battery = Battery()def describe_battery(self):"""打印一条描述电瓶容量的消息"""print(f"This car has a {self.battery.battery_size}-kWh battery.")my_tesla = ElectricCar('tesla', 'model s', 2019)
print(my_tesla.get_descriptive_name())
my_tesla.describe_battery()
导入类
随着类信息的不断增加,我们一个文件中代码会越来越长,python允许将类存储在模块中,我们在使用时只需要在主程序中导入所需要的模块即可
导入单个类
car.py文件
class Car:"""一次模拟汽车的简单尝试"""def __init__(self, make, model, year):self.make = makeself.model = modelself.year = yearself.odometer_reading = 0def get_descriptive_name(self):"""返回整洁的描述性信息。"""long_name = f"{self.year} {self.make} {self.model}"return long_name.title()def read_odometer_reading(self):print(f"This car has {self.odometer_reading} miles on it")def update_odometer(self, mileage):self.odometer_reading = mileage
my_car.py文件
from car import Carmy_new_car = Car('audi', 'a4', 2019)
print(my_new_car.get_descriptive_name())
my_new_car.odometer_reading = 23
my_new_car.read_odometer_reading()
这里如果我们还记得之前是怎么导入模块中的函数部分就会发现两者基本上就是一样的操作,所以关于导入类这部分可以类比之前的进行学习理解
在一个模块中存储多个类
一个模块中原则上是可以存储任意数量的类的,但是我们可以思考一下,我们为了工程项目上的方便,更应该将一些有联系的类放在一起,这样更有利于我们自己进行编程
从一个模块中导入多个类
既然上面我们说了一个模块中可以存储多个类,那么我们可以指定模块中的任何类导入我们的主程序,这里就会涉及如何从一个模块中导入多个类,这里和导入多个函数的操作是一样的import class1, class2, …, import后面跟的类用逗号隔开即可
格式:
from module import class1, class2, ...
导入整个模块
我们直接看例子更容易理解一些
import car
my_new_car = car.Car('audi', 'a4', 2019)
print(my_new_car.get_descriptive_name())
my_new_car.odometer_reading = 23
my_new_car.read_odometer_reading()
这里使用的时候需要car.
导入模块中的所有类
还是直接看例子
from module_name import *
在一个模块中导入另一个模块
就拿我们上面的例子来说,假如我们的car本身就很大,再将ElectricCar和它放到一起看起来就不是很清楚,这里我们就可以单独将ElectricCar这个类放到一个模块中,然后再将这个模块导入到car这个模块中
使用别名
和前面一样这里我们也可以使用别名
from electric_car import ElectricCar as EC
my_tesla = EC('tesla', 'roadster', 2019)
关于这个模块的理解,如果你学过java的话那么就可以把这个模块类比成java中的包,python的类的这部分是面向对象,所以所有面向对象语言的很多知识点都是互通的,如果学过其他面向对象语言学起来应该很轻松
Python标准库
Python标准库是一组模块,我们在安装python的时候都已经自动安装,我们可以使用Python标准库里面的很多函数和类,这将很大的提高我们的效率。
这里举的例子是random模块
import random as rm
a = rm.randint(1, 6)
print(a)
players = ['Bob', 'Alice', 'Tom', 'Jhon']
first_up = rm.choice(players)
print(first_up)
randint(i, j)是生成一个i和j之间的随机数
choice()函数的参数是一个列表或元组(还记不记得元组是什么?元组和列表的最大区别是元组不可修改哦),返回值是列表(或元组)中的随机一个元素
类的命名规则
类名应采用驼峰命名法,相信学过java的同学都知道这个驼峰命名法是个什么东西
驼峰命名法:将类名中的每个单词的首字母都大写而不使用下划线,而实例名和模块名都采用小写格式(这里将模块看作包能和java保持一致了)
文件和异常
读文件中的数据
直接读整个文件
with open('pi_digits.txt') as file_object:contents = file_object.read()
print(contents)
print(type (contents))
1、open()函数:open()函数接收了一个参数即要打开的文件的名称,Python在当前执行的文件所在的目录中查找指定的文件,open()返回值是一个表示文件的对象
2、with关键字的使用:with在不需要访问文件后将其关闭,在上面的程序中,我们调用了open(),但是却没有调用close(),我们也可以用close()来关闭,有时候我们自己使用close()关闭时机可能会不恰当导致出现一些错误,但是使用上面的with as结构python会自己去帮我们确定什么时候该关闭文件
3、read()函数:当我们有了文件对象之后,我们使用这read()函数读取这个文件中的全部内容,并将文件中的内容作为一个字符串赋值给变量contents,在上面例子的实验中我们也可以看出来,小tips当我们不确定python中一个数据是什么类型时我们可以用type这个运算符来进行确认,read()函数在达到文件末尾时返回一个空字符串,这会导致contents比原来的文件多一个空行,要想将空行删除可以用rstrip()函数
文件路径
当我们要打开的文件和我们程序不在同一目录下的时候,我们就需要用到路径来打开我们的文件,当然我们知道文件的绝对路径比较长,这里我们可以先将绝对路径赋值给一个字符串变量然后将变量作为参数传入open()函数即可
逐行读取
filename = 'pi_digits.txt'
with open(filename) as file_object:for line in file_object:print(line)
这里我们会发现打印时多了空白行
filename = 'pi_digits.txt'
with open(filename) as file_object:for line in file_object:print(line.rstrip())
创建一个包含文件各行内容的列表
filename = 'pi_digits.txt'
with open(filename) as file_object:lines = file_object.readlines()for line in lines:print(line.rstrip())
将数据写回文件
写入空文件
filename = 'pi_digits.txt'
with open(filename, 'w') as file_object:file_object.write("hello python")
open()函数再探析:这次我们传入了两个参数,第一个参数传入的就是文件的路径没第二个参数’w’告诉python我们要以写入模式打开这个文件
‘r’:读取模式
‘w’:写入模式
‘a’:附加模式
‘r+’:读写模式
写入多行
python中写入函数用write(),这个函数并不会在写入内容的末尾添加换行符,需要我们手动添加
附加到文件
有很多时候我们的文件并非空白文件,而是原本就含有一些内容,我们希望在原来的基础上进行修改的话就需要用到我们的附加模式
异常
异常的定义就不再说了,这里的异常和java的异常一样,可以看之前的博客
除零异常ZeroDivisionError异常
print(5/0)
try-except代码块
try:print(5/0)
except ZeroDivisionError:print("你除0了")
如果学过java上面的代码就很好理解,这和java中捕获异常的try-catch语句是一样的,
我们将一句可能发生错误的代码放在try代码块中,如果出现了和except中匹配的错误的话将执行except代码块中的内容,否则将跳过except代码块
else
try-except-else:这里和java中的try-catch-finally不一样,这里else是只有当try代码块的语句没有异常时才会执行else中的内容
静默失败
有时候我们在捕获到异常后并不希望每次都告诉用户,只是像什么都没有发生过一样继续运行,这时我们就可以用pass语句来执行这样的操作
存储数据
import jsonnumbers = [2, 3, 5, 7, 11, 13]filename = 'numbers.json'
with open(filename, 'w') as f:json.dump(numbers, f)
用load()函数将数据再读回来
import jsonfilename = 'numbers.json'
with open(filename) as f:numbers = json.load(f)
print(numbers)
可能很多人和我一样不知道json是什么文件这里放一下百度百科的解释
JSON ( JavaScript Object Notation, JS 对象简谱) 是一种轻量级的数据交换格式。. 它基于 ECMAScript (欧洲计算机协会制定的js规范)的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。. 简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。. 易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。
测试代码
测试函数
单元测试和测试用例
python标准库中的模块unittest提供了代码测试工具。
单元测试用于核实函数的某个方面没有问题。
测试用例是一组单元测试。
可通过的测试
我们这里先说创建测试用例的语法
,要为函数编写测试用例,可以先导入模块unittest和测试的函数,再创建一个继承unittest.TestCase的类,并编写一系列方法对函数行为的不同方面进行测试
def get_foramtted_name(first, last):""""生成整洁的姓名"""full_name = f"{first} {last}"return full_name.title()
import unittest
from name_function import get_foramtted_nameclass NamesTestCase(unittest.TestCase):""""测试name_function.py"""def test_first_last_name(self):""""能够正确地处理像Janis Joplin像这样的姓名码?"""formatted_name = get_foramtted_name('janis', 'joplin')self.assertEqual(formatted_name, 'Janis Joplin')if __name__ == '-_main-_':unittest.main()
这里解释一下这个程序
首先我们导入函数和unittest这个模块
然后我们创建了一个名为NameTestCase的类这个类必须继承unittest模块中的TestCase类
我们在运行tset_nbame_function.py这个文件的时候,所有以test开头的方法都将自动运行
断言方法:相信学过数据库的同学对这个断言有一定的了解,在python这里断言就是用于核实得到的结果是否和期望的结果一致,如果相等那么很好我们什么都不用管,如果不能相等那么就需要python告诉我们一声,这里主要是这个unittest里面的assertEqual()方法
__name__是一个特殊变量,这个变量是在程序执行时设置的,如果我们这个文件作为主程序执行,__name__将被设置为’main’,调用unittest.main()来运行测试用例。注意这里是双下滑线,也就是两个下划线,如果你在自己写的时候报错了可以看看是不是这里出了错
测试类
各种断言方法
下面是几种常见的断言方法
1、assertEqual(a, b) 核实a == b
2、assertBNotEqual(a, b) 核实a != b
3、assertTrue(x) 核实x为true
4、assertFalse(x) 核实x为False
5、assertIn(item, list) 核实item在list中
6、assertNotIn(item, list) 核实item不再list中
一个要测试的类
类的测试其实和函数的测试差不多,基本上对类的测试还是对类中方法的测试
class AnonymousSurvey:"""收集匿名调查问卷答案"""def __init__(self, question):"""存储一个问题,并为存储答案做准备"""self.question = questionself.responses = []def show_question(self):"""显示调查问卷"""print(self.question)def store_response(self, new_response):"""存储单份调查答卷"""self.responses.append(new_response)def show_results(self):"""显示收集到的所有答卷"""print("Survey result:")for response in self.responses:print(f"- {response}")
测试AnonymousSurvey类
test_survey.py文件
import unittest
from survey import AnonymousSurveyclass TestAnonymousSurvey(unittest.TestCase):def test_store_single_response(self):question = "What language did you first learn to speak?"my_survey = AnonymousSurvey(question)my_survey.store_response('a')self.assertIn('a', my_survey.responses)if __name__ == '__main__':unittest.main()
方法setUp()
import unittest
from survey import AnonymousSurveyclass TestAnonymousSurvey(unittest.TestCase):def setUp(self):question = "What language did you first learn to speak?"self.my_survey = AnonymousSurvey(question)self.responses = ['English', 'Spanish', 'Mandarin']def test_sore_single_respnose(self):self.my_survey.store_response(self.responses[0])self.assertIn(self.responses[0], self.my_survey.responses)if __name__ == '__main__':unittest.main()
setUP()做两个事情一创建一个调查对象,创建一个答案列表,我们使用setUP()方法可以只创建一个对象所有测试方法均可以通过self前缀来用这个对象进行验证,而不用在每个测试函数中都再创建一遍对象