打开Python官网地址
下载 executable installer,x86 表示是 32 位机子的,x86-64 表示 64 位机子的。
开始安装
import keyword
keyword.kwlist
# 关键字列表
['False', 'None', 'True', 'and', 'as', 'assert', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try', 'while', 'with', 'yield']
Python中单行注释以 # 开头,实例如下:
# 第一个注释
print ("Hello, Python!") # 第二个注释
多行注释可以用多个 # 号,还有’’'和 “”“xxxx”"":
# 第一个注释
# 第二个注释
'''
第三注释
第四注释
'''
"""
第五注释
第六注释
# 正确行与缩进
if True:
print ("True")
else:
print ("False")
# 错误的行与缩进
if True:
print ("Answer")
print ("True")
else:
print ("Answer")
print ("False") # 缩进不一致,会导致运行错误
total = item_one + \
item_two + \
item_three
在 [], {}, 或 () 中的多行语句,不需要使用反斜杠(),例如:
total = ['item_one', 'item_two', 'item_three',
'item_four', 'item_five']
Python中数字有四种类型:整数、布尔型、浮点数和复数。
int (整数), 如 1, 只有一种整数类型 int,表示为长整型,没有 python2 中的 Long。
bool (布尔), 如 True和False
float (浮点数), 如 1.23
complex (复数), 如 1 + 2j、 1.1 + 2.2j
查看类型,用type()方法
字符串
python中单引号和双引号使用完全相同
使用三引号(’’'或""")可以指定一个多行字符串
def hello():
pass
# 此处为空行
def word():
pass
input("请输入你的名字")
x = "a"
y = "b"
# 换行输出
print( x )
print( y )
print('---------')
# 不换行输出
print( x, end=" " )
print( y, end=" " )
print()
本章节主要说明Python的运算符。举个简单的例子 1 +2 = 3 。 例子中,1 和 1、2 被称为操作数,"+" 称为运算符。
Python语言支持以下类型的运算符:
以下假设变量:a=10,b=20
运算符 | 描述 | 实例 |
---|---|---|
+ | 加: 两个对象相加 | a + b 输出结果 30 |
- | 减 - 得到负数或是一个数减去另一个数 | a - b 输出结果 -10 |
* | 乘: 两个数相乘 | a * b 输出结果 200 |
返回一个被重复若干次的字符串,如:HI*3 | HI,HI,HI | |
/ | 除: x除以y(即两个数的商) | b / a 输出结果 2 |
% | 取模:返商的余数 | b % a 输出结果 0 |
** | 幂:返回x的y次幂 | a**b 为10的20次方,输出结果100000000000000000000 |
// | 取整除: 返回商的整数部分 | 9//2 输出结果 4 , 9.0//2.0 输出结果 4.0 |
注:加号也可用作连接符,但两边必须是同类型的才可以,否则会报错,如:23+ “Python” ,数字23和字符串类型不一致
比较运算符
以下假设变量a为10,变量b为20
运算符 | 描述 | 实例 |
---|---|---|
== | 等于:比较对象是否相等 | (a == b) 返回 False |
!= | 不等于:比较两个对象是否不相等 | (a != b) 返回 True |
> | 大于:返回x是否大于y | (a > b) 返回 False |
< | 小于:返回x是否小于y | (a < b) 返回 True。 |
>= | 大于等于:返回x是否大于等于y | (a >= b) 返回 False |
<= | 小于等于:返回x是否小于等于y | (a <= b) 返回 True |
注:所有比较运算符返回1表示真,返回0表示假。这分别与特殊的变量True和False等价。注意True和False第一个字母是大写
赋值运算符
以下假设变量a为10,变量b为20
运算符 | 描述 | 实例 |
---|---|---|
= | 简单的赋值运算符 | c = a + b 将 a + b 的运算结果赋值为 c |
+= | 加法赋值运算符 | c += a 等效于 c = c + a |
-= | 减法赋值运算符 | c -= a 等效于 c = c - a |
*= | 乘法赋值运算符 | c *= a 等效于 c = c * a |
/= | 除法赋值运算符 | c /= a 等效于 c = c / a |
%= | 取模赋值运算符 | c %= a 等效于 c = c % a |
**= | 幂赋值运算符 | c **= a 等效于 c = c ** a |
//= | 取整除赋值运算符 | c //= a 等效于 c = c // a |
Python语言支持逻辑运算符,以下假设变量 a 为 10, b为 20:
运算符 | 逻辑表达式 | 描述 | 实例 |
---|---|---|---|
and | x and y | 布尔"与":如果 x 为 False,x and y 返回 False,否则它返回 y 的计算值 | (a and b) 返回 20 |
or | x or y | 布尔"或" :如果 x 是非 0,它返回 x 的值,否则它返回 y 的计算值 | (a or b) 返回 10 |
not | not x | 布尔"非":如果 x 为 True,返回 False 。如果 x 为 False它返回 True | not(a and b) 返回 False |
运算符 | 描述 | 实例 |
---|---|---|
in | 如果在指定的序列中找到值返回 True,否则返回 False | x 在 y 序列中 , 如果 x 在 y 序列中返回 True |
not in | 如果在指定的序列中没有找到值返回 True,否则返回 False | x 不在 y 序列中 , 如果 x 不在 y 序列中返回 True |
身份运算符用于比较两个对象的存储单元
运算符 | 描述 | 实例 |
---|---|---|
is | is 是判断两个标识符是不是引用自一个对象 | x is y, 类似 id(x) == id(y) , 如果引用的是同一个对象则返回 True,否则返回 False |
is not | is not 是判断两个标识符是不是引用自不同对象 | x is not y , 类似 id(a) != id(b)。如果引用的不是同一个对象则返回结果 True,否则返回 False。 |
以下表格列出了从最高到最低优先级的所有运算符:
运算符 | 描述 |
---|---|
** | 指数 (最高优先级) |
~ + - | 按位翻转, 一元加号和减号 (最后两个的方法名为 +@ 和 -@) |
* / % // | 乘,商,取余和取整除 |
+ - | 加法减法 |
>> << | 右移,左移运算符 |
& | 位 ‘AND’ |
^ | | 位运算符 |
<= < > >= | 比较运算符 |
<> == != | 等于运算符 |
= %= /= //= -= += *= **= | 赋值运算符 |
is is not | 身份运算符 |
in not in | 成员运算符 |
not or and | 逻辑运算符 |
# -*- coding: utf-8 -*-
# @Author : 码上开始
var1 = 'Hello World!'
var2 = "Hello World!"
# -*- coding: utf-8 -*-
# @Author : 码上开始
var = “Hello World”
print(var[0])
#运行结果H
# -*- coding: utf-8 -*-
# @Author : 码上开始
print(var1[0:6] + “Python”)
#运行结果:Hello Python
另一种写法:
print(var1[:6] + “Python”)
#运行结果:Hello Python
#-*- coding: utf-8 -*-
#@Author : 码上开始
first_word = “码上”
last_word = “开始”
print(first_word + last_word)
#运行结果为:码上开始
# -*- coding: utf-8 -*-
# @Author : 码上开始
language = "Python "
language.rstrip() # 删除右边空格
language = " Python"
language.lstrip() # 删除左边空格
language = " Python " #
language.strip() # 删除左右空白
# str传入的是字符串
str.startswith(str, beg=0,end=len(string))
方法用于检查字符串是否是以指定子字符串开头,如果是则返回 True,否则返回 False。
如果参数 beg 和 end 指定值,则在指定范围内检查。
# -*- coding: utf-8 -*-
# @Author : 码上开始
str = "this is string example....wow!!!"
# 默认从坐标0开始匹配this这个字符
print str.startswith( 'this' )
# 指定下标从2到4匹配is
print str.startswith( 'is', 2, 4 )
# 同上
print str.startswith( 'this', 2, 4 )
# 运行结果
True
True
False
传入的值为元组时
# -*- coding: utf-8 -*-
# @Author : 码上开始
string = "Postman"
# 元组中只要任一元素匹配则返回True,反之为False
print(string.startswith(("P", "man"),0))
# 虽然元组元素Po/man都存在字符中,但不匹配开始的下标,所以仍返回值Flase
print(string.startswith(("Po", "man"),1))
# 语法
str.endswith(string,[, start[, end]])
Python endswith() 方法用于判断字符串是否以指定后缀结尾,如果以指定后缀结尾返回True,否则返回False。
可选参数"start"与"end"为检索字符串的开始与结束位置。
# -*- coding: utf-8 -*-
# @Author : 码上开始
string = "this is string example....wow!!!";
str = "wow!!!"
print(string.endswith(str))
print(string.endswith(str,20))
str1 = "is"
print(string.endswith(str1, 2, 4))
print(string.endswith(str1, 2, 6))
# 运行结果
True
True
True
False
# -*- coding: utf-8 -*-#
@Author : 码上开始
age = 29
print("my age is %d" %age)
#my age is 29
name = "makes"print("my name is %s" %name)
#my name is makes
print("%f" %2.3)#2.300000
**format()格式化:**占位符{},搭配format()函数一起使用
位置映射
print("{}:{}".format('192.168.0.100',8888))#192.168.0.100:8888
关键字映射
print("{server}{1}:{0}".format(8888,'192.168.1.100',server='Web Server Info :'))
#Web Server Info :192.168.1.100:8888
下表实例变量 a 值为字符串 “Hello”,b 变量值为 “Python”:
操作符 | 描述 | 实例 |
---|---|---|
+ | 字符串连接 | a + b ‘HelloPython’ |
* | 重复输出字符串 | a * 2 ‘HelloHello’ |
[] | 通过索引获取字符串中字符 | a[1] ‘e’ |
[ : ] | 截取字符串中的一部分 | a[1:4] ‘ell’ |
in | 成员运算符 - 如果字符串中包含给定的字符返回 True | “H” in a True |
not in | 成员运算符 - 如果字符串中不包含给定的字符返回 True | “M” not in a True |
r/R | 原始字符串 - 原始字符串:所有的字符串都是直接按照字面的意思来使用,没有转义特殊或不能打印的字符。 原始字符串除在字符串的第一个引号前加上字母"r"(可以大小写)以外,与普通字符串有着几乎完全相同的语法。 | >>>print r’\n’ \n >>> print R’\n’ \n |
[]
创建a = [1, 'jack', True, 100]
b = []
使用list()
可以将任何可迭代的数据转化成列表
a = list() # 创建一个空列表
b = list(range(5)) # [0, 1, 2, 3, 4]
c = list('nice') # ['n', 'i', 'c', 'e']
range()
创建整数列表range()
可以帮助我们非常方便的创建整数列表,这在开发中及其有用。语法格式为:`range([start,]end[,step])
start参数:可选,表示起始数字。默认是0。
end参数:必选,表示结尾数字。
step参数:可选,表示步长,默认为1。
python3中range()
返回的是一个range对象,而不是列表。我们需要通过list()
方法将其转换成列表对象。
a = list(range(-3, 2, 1)) # [-3, -2, -1, 0, 1]
b = list(range(2, -3, -1)) # [2, 1, 0, -1, -2]
a = [i * 2 for i in range(5) if i % 2 == 0] # [0, 4, 8]
points = [(x, y) for x in range(0, 2) for y in range(1, 3)]
print(points) # [(0, 1), (0, 2), (1, 1), (1, 2)]
当列表增加和删除元素时,列表会自动进行内存管理,大大减少了程序员的负担。但这个特点涉及列表元素的大量移动,效率较低。除非必要,我们一般只在列表的尾部添加元素或删除元素,这会大大提高列表的操作效率。
append()
>>>a = [20,40]
>>>a.append(80)
>>>a
[20,40,80]
+
运算符>>> a = [3, 1, 4]
>>> b = [4, 2]
>>> a + b
[3, 1, 4, 4, 2]
extend()
将目标列表的所有元素添加到本列表的尾部,属于原地操作,不创建新的列表对象。
>>> a = [3, 2]
>>> a.extend([4, 6])
>>> a
[3, 2, 4, 6]
insert()
使用insert()
方法可以将指定的元素插入到列表对象的任意指定位置。这样会让插入位置后面所有的元素进行移动,会影响处理速度。涉及大量元素时,尽量避免使用。类似发生这种移动的函数还有:remove()、pop()、del(),它们在删除非尾部元素时也会发生操作位置后面元素的移动。
>>> a = [2, 5, 8]
>>> a.insert(1, 'jack')
>>> a
[2, 'jack', 5, 8]
>>> a = [4, 5]
>>> a * 3
[4, 5, 4, 5, 4, 5]
适用于乘法操作的,还有:字符串、元组。
del()
>>> a = [2, 3, 5, 7, 8]
>>> del a[1]
>>> a
[2, 5, 7, 8]
pop()
>>> a = [3, 6, 7, 8, 2]
>>> b = a.pop()
>>> b
2
>>> c = a.pop(1)
>>> c
6
remove()
>>> a=[10,20,30,40,50,20,30,20,30]
>>> a.remove(20)
>>> a
[10, 30, 40, 50, 20, 30, 20, 30]
clear()
a = [3, 6, 7, 8, 2]
a.clear()
print(a) # []
>>> a = [2, 4, 6]
>>> a[1]
4
index()
获得指定元素在列表中首次出现的索引index()
可以获取指定元素首次出现的索引位置。语法是:index(value,[start,[end]])
。其中,start
和end
指定了搜索的范围。>>> a = [10, 20, 30, 40, 50, 20, 30, 20, 30]
>>> a.index(20)
1
>>> a.index(20, 3)
5
>>> a.index(20, 6, 8)
7
返回指定元素在列表中出现的次数。
>>> a = [10, 20, 30, 40, 50, 20, 30, 20, 30]
>>> a.count(20)
3
[起始偏移量start:终止偏移量end[:步长step]]
三个量为正数的情况下
| 操作和说明 | 示例 | 结果 |
| ---------------------------------------------------- | ------------------------------------- | -------------- |
| [:]
提取整个列表 | [10, 20, 30][:]
| [10, 20, 30]
|
| [start:]
从start索引开始到结尾 | [10, 20, 30][1:]
| [20, 30]
|
| [:end]
从头开始到 end-1 | [10, 20, 30][:2]
| [10, 20]
|
| [start:end]
从 start 到 end-1 | [10, 20, 30, 40][1:3]
| [20, 30]
|
| [start:end:step]
从 start 提取到 end-1,步长是step | [10, 20, 30, 40, 50, 60, 70][1:6:2]
| [20, 40, 60]
|
三个量为负数的情况
| 示例 | 说明 | 结果 |
| ------------------------------------- | ---------------------- | ------------------------ |
| [10, 20, 30, 40, 50, 60, 70][-3:]
| 倒数三个 | [50, 60, 70]
|
| [10, 20, 30, 40, 50, 60, 70][-5:-3]
| 倒数第五个至倒数第四个 | [30, 40]
|
| [10,20,30,40,50,60,70][::-1]
| 逆序 | [70,60,50,40,30,20,10]
|
t1 = [11, 22, 33, 44, 55, 66, 77, 88, 99]
print(t1[100:]) # []
print(t1[0:-1]) # [11, 22, 33, 44, 55, 66, 77, 88]
print(t1[1:5:-1]) # []
print(t1[-1:-5:-1]) # [99, 88, 77, 66]
print(t1[-5:-1:-1]) # []
print(t1[5:-1:-1]) # []
print(t1[::-1]) # [99, 88, 77, 66, 55, 44, 33, 22, 11]
# 注意以下两个
print(t1[3::-1]) # [44, 33, 22, 11]
print(t1[3::1]) # [44, 55, 66, 77, 88, 99]
123456789101112131415161718
a = [3, 2, 8, 4, 6]
print(id(a)) # 2180873605704
a.sort() # 默认升序
print(a) # [2, 3, 4, 6, 8]
print(id(a)) # 2180873605704
a.sort(reverse=True)
print(a) # [8, 6, 4, 3, 2]
12345678
# 将序列的所有元素随机排序
import random
b = [3, 2, 8, 4, 6]
random.shuffle(b)
print(b) # [4, 3, 6, 2, 8]
12345
sorted()
进行排序,这个方法返回新列表,不对原列表做修改。a = [3, 2, 8, 4, 6]
b = sorted(a) # 默认升序
c = sorted(a, reverse=True) # 降序
print(b) # [2, 3, 4, 6, 8]
print(c) # [8, 6, 4, 3, 2]
12345
list1 = [34,54,6,5,65,100,4,19,50,3]
#冒泡排序,以升序为例
#外层循环:控制比较的轮数
for i in range(len(list1) - 1):
#内层循环:控制每一轮比较的次数,兼顾参与比较的下标
for j in range(len(list1) - 1 - i):
#比较:只要符合条件则交换位置,
# 如果下标小的元素 > 下标大的元素,则交换位置
if list1[j] < list1[j + 1]:
list1[j],list1[j + 1] = list1[j + 1],list1[j]
print(list1)
li = [17, 4, 77, 2, 32, 56, 23]
# 外层循环:控制比较的轮数
for i in range(len(li) - 1):
# 内层循环:控制每一轮比较的次数
for j in range(i + 1, len(li)):
# 如果下标小的元素>下标大的元素,则交换位置
if li[i] > li[j]:
li[i], li[j] = li[j], li[i]
print(li)
# 顺序查找
# 1.需求:查找指定元素在列表中的位置
list1 = [5, 6, 5, 6, 24, 17, 56, 4]
key = 6
for i in range(len(list1)):
if key == list1[i]:
print("%d在列表中的位置为:%d" % (key,i))
# 2.需求:模拟系统的index功能,只需要查找元素在列表中第一次出现的下标,如果查找不到,打印not found
# 列表.index(元素),返回指定元素在列表中第一次出现的下标
list1 = [5, 6, 5, 6, 24, 17, 56, 4]
key = 10
for i in range(len(list1)):
if key == list1[i]:
print("%d在列表中的位置为:%d" % (key,i))
break
else:
print("not found")
# 3.需求:查找一个数字列表中的最大值以及对应的下标
num_list = [34, 6, 546, 5, 100, 16, 77]
max_value = num_list[0]
max_index = 0
for i in range(1, len(num_list)):
if num_list[i] > max_value:
max_value = num_list[i]
max_index = i
print("最大值%d在列表中的位置为:%d" % (max_value,max_index))
# 4.需求:查找一个数字列表中的第二大值以及对应的下标
num_list = [34, 6, 546, 5, 100, 546, 546, 16, 77]
# 备份
new_list = num_list.copy()
# 升序排序
for i in range(len(new_list) - 1):
for j in range(len(new_list) - 1 - i):
if new_list[j] > new_list[j + 1]:
new_list[j],new_list[j + 1] = new_list[j + 1],new_list[j]
print(new_list)
# 获取最大值
max_value = new_list[-1]
# 统计最大值的个数
max_count = new_list.count(max_value)
# 获取第二大值
second_value = new_list[-(max_count + 1)]
# 查找在列表中的位置:顺序查找
for i in range(len(num_list)):
if second_value == num_list[i]:
print("第二大值%d在列表中的下表为:%d" % (second_value,i))
# 二分法查找的前提:有序
li = [45, 65, 7, 67, 100, 5, 3, 2, 35]
# 升序
new_li = sorted(li)
key = 100
# 定义变量,表示索引的最小值和最大值
left = 0
right = len(new_li) - 1
# left和right会一直改变
# 在改变过程中,直到left==right
while left <= right:
# 计算中间下标
middle = (left + right) // 2
# 比较
if new_li[middle] < key:
# 重置left的值
left = middle + 1
elif new_li[middle] > key:
# 重置right的值
right = middle - 1
else:
print(f'key的索引为{
li.index(new_li[middle])}')
break
else:
print('查找的key不存在')
reverse()
a = [3, 2, 8, 4, 6]
a.reverse()
print(a) # [6, 4, 8, 2, 3]
copy()
复制列表,属于浅拷贝。
a = [3, 6, 7, 8, 2]
b = a.copy()
print(b) # [3, 6, 7, 8, 2]
max()
和min()
a = [3, 2, 8, 4, 6]
print(max(a)) # 8
print(min(a)) # 2
sum()
对数值型列表的所有元素进行求和操作,对非数值型列表运算则会报错。
a = [3, 2, 8, 4, 6]
print(sum(a)) # 23
# -*- coding: utf-8 -*-
# @Author : 码上开始
dict = {
"CSDN": "码上开始", "name": "老猪"}
# -*- coding: utf-8 -*-
# @Author : 码上开始
dict = {
"CSDN": "码上开始", "name": "老猪"}
print(dict["CSDN"])
# 运行结果
码上开始
# -*- coding: utf-8 -*-
# @Author : 码上开始
dict = {
"CSDN": "码上开始", "name": "老猪"}
dict["age"] = 35
print(dict)
# 运行结果
{
'CSDN': '码上开始', 'name': '老猪', 'age': 35}
# -*- coding: utf-8 -*-
# @Author : 码上开始
dict = {
"CSDN": "码上开始", "name": "老猪"}
del dict["name"]
# dict.pop("name")
print(dict)
# 运行结果
{
'CSDN': '码上开始'}
# -*- coding: utf-8 -*-
# @Author : 码上开始
dict = {
"CSDN": "码上开始", "name": "老猪"}
dict.clear()
print(dict)
# 运行结果
{
}
# -*- coding: utf-8 -*-
# @Author : 码上开始
dict = {
"CSDN": "码上开始", "name": "老猪"}
dict["CSDN"]="乌托邦"
print(dict)
# 运行结果
{
'CSDN': '乌托邦', 'name': '老猪'}
dict.keys()—获取字典里所有的键
常搭配for循环使用
# -*- coding: utf-8 -*-
# @Author : 码上开始
dict = {
"CSDN": "码上开始", "name": "老猪"}
for key in dict.keys():
print(key)
# 运行结果
CSDN
name
# -*- coding: utf-8 -*-
# @Author : 码上开始
dict = {
"CSDN": "码上开始", "name": "老猪"}
for value in dict.values():
print(value)
# 运行结果
码上开始
老猪
# -*- coding: utf-8 -*-# @Author : 码上开始dict = {"CSDN": "码上开始", "name": "老猪"}for key, value in dict.items(): print("key值:", key) print("value:", value) # 运行结果key值: CSDNvalue: 码上开始key值: namevalue: 老猪
将列表或元组转成字典
语法:dict(list/tuple)
# -*- coding: utf-8 -*-# @Author : 码上开始tuple = (("CSDN, "码上开始"), ("name", "老猪"))# list = [["CSDN", "码上开始"], ["name", "老猪"]]print(dict(tuple))# 运行结果{'CSDN': '码上开始', 'name': '老猪'}
# -*- coding: utf-8 -*-# @Author : 码上开始words = {"name": {"CSDN": "码上开始"}}print(words["name"]["CSDN"])# 运行结果码上开始
Python 的元组与列表类似,不同之处在于元组的元素不能修改
元组与列表类似,下标索引从 0 /-1开始,可以进行截取,组合等
# -*- coding: utf-8 -*-
# @Author : 码上开始
songs = ()
# -*- coding: utf-8 -*-
# @Author : 码上开始
songs = ("千里之外", "东风破", "比我幸福")
# -*- coding: utf-8 -*-
# @Author : 码上开始
songs = ("千里之外", "东风破", "比我幸福")
print(songs[0])
# 运行
千里之外
# -*- coding: utf-8 -*-
# @Author : 码上开始
songs = ("千里之外", "东风破")
singers = ("周杰伦",)
starts = songs + singers
print(starts)
# -*- coding: utf-8 -*-
# @Author : 码上开始
songs = ("千里之外", "东风破")
del songs
# 运行报错,提示变量没有定义
print(songs)
Python 表达式 | 结果 | 描述 |
---|---|---|
len((1, 2, 3)) | 3 | 计算元素个数 |
(1, 2, 3) + (4, 5, 6) | (1, 2, 3, 4, 5, 6) | 连接 |
(‘Hi!’,) * 4 | (‘Hi!’, ‘Hi!’, ‘Hi!’, ‘Hi!’) | 复制 |
3 in (1, 2, 3) | True | 元素是否存在 |
for x in (1, 2, 3): print (x,) | 1 2 3 | 迭代 |
因为元组也是一个序列,所以我们可以访问元组中的指定位置的元素
也可以截取索引中的一段元素
操作方式和列表一样
tup = ('Google', 'Runoob', 'Taobao', 'Wiki', 'Weibo','Weixin')
Python 表达式 | 结果 | 描述 |
---|---|---|
tup[1] | ‘Runoob’ | 读取第二个元素 |
tup[-2] | ‘Weibo’ | 反向读取,读取倒数第二个元素 |
tup[1:] | (‘Runoob’, ‘Taobao’, ‘Wiki’, ‘Weibo’, ‘Weixin’) | 截取元素,从第二个开始后的所有元素。 |
tup[1:4] | (‘Runoob’, ‘Taobao’, ‘Wiki’) | 截取元素,从第二个开始到第四个元素(索引为 3)。 |
# -*- coding:utf-8 -*-
# @Time : 2020/10/8 9:59
# @File :day1.py
# @Author: "码上开始"
# 重复的元素,打印结果中只会显一个
fruit = {
'apple', 'orange', 'apple', 'pear', 'orange', 'banana'}
# 打印结果
{
'pear', 'orange', 'apple', 'banana'}
# -*- coding:utf-8 -*-
# @Author: "码上开始"
fruit = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana']
new_set = set(fruit)
# 重复的元素,打印结果中只会显一个
print(new_set)
# 结果
{
'banana', 'apple', 'orange', 'pear'}
# -*- coding:utf-8 -*-
# @Author: "码上开始"
a = set('abracadabra') # {'r', 'a', 'd', 'c', 'b'}
b = set('alacazam') # {'m', 'a', 'z', 'c', 'l'}
# a包含b不包含的元素
c = a - b
print(c)
# 结果
{
'b', 'r', 'd'}
# 集合a或b中包含的所有元素
c = a | b
print(c)
# 结果
{
'm', 'a', 'r', 'l', 'd', 'z', 'b', 'c'}
# 集合a和b中都包含了的元素
c = a & b
print(c)
# 结果
{
'c', 'a'}
# 不同时包含于a和b的元素
c = a ^ b
print(c)
# 结果
{
'r', 'm', 'z', 'b', 'd', 'l'}
# -*- coding:utf-8 -*-
# @Time : 2020/10/8 9:59
# @File :day1.py
# @Author: "码上开始"
num = {
1, 2, 3}
num.add(4)
print(num)
# 结果
{
1, 2, 3, 4}
# -*- coding:utf-8 -*-
# @Author: "码上开始"
# 如果添加为列表等,则要用update方法
num = {
1, 2, 3}
list = [4, 5]
num.update(list)
print(num)
# 结果
{
1, 2, 3, 4, 5}
# -*- coding:utf-8 -*-
# @Author: "码上开始"
num = {
1, 2, 3}
num.remove(1)
print(num)
# 结果
{
2, 3}
# -*- coding:utf-8 -*-
# @Author: "码上开始"
# 随机删除集合中的元素
num = {
1, 2, 3}
num.pop()
print(num)
# 结果
{
2, 3}
# -*- coding:utf-8 -*-
# @Time : 2020/10/8 9:59
# @File :day1.py
# @Author: "码上开始"
num = {
1, 2, 3}
print(len(num))
# 结果
3
# -*- coding:utf-8 -*-
# @Time : 2020/10/8 9:59
# @File :day1.py
# @Author: "码上开始"
num ={
1, 2, 3}
num.clear()
print(num)
# 结果
set()
判断元素 x 是否在集合中,存在返回 True,不存在返回 False
# -*- coding:utf-8 -*-
# @Time : 2020/10/8 9:59
# @File :day1.py
# @Author: "码上开始"
num ={
1, 2, 3}
if 1 in num:
print("存在集合中")
方法 | 描述 |
---|---|
add() | 为集合添加元素 |
clear() | 移除集合中的所有元素 |
copy() | 拷贝一个集合 |
difference() | 返回多个集合的差集 |
difference_update() | 移除集合中的元素,该元素在指定的集合也存在。 |
discard() | 删除集合中指定的元素 |
intersection() | 返回集合的交集 |
intersection_update() | 返回集合的交集。 |
isdisjoint() | 判断两个集合是否包含相同的元素,如果没有返回 True,否则返回 False。 |
issubset() | 判断指定集合是否为该方法参数集合的子集。 |
issuperset() | 判断该方法的参数集合是否为指定集合的子集 |
pop() | 随机移除元素 |
remove() | 移除指定元素 |
symmetric_difference() | 返回两个集合中不重复的元素集合。 |
symmetric_difference_update() | 移除当前集合中在另外一个指定集合相同的元素,并将另外一个指定集合中不同的元素插入到当前集合中。 |
union() | 返回两个集合的并集 |
update() | 给集合添加元素 |
每条if语句的核心都是一个值为True或False的表达式,这种表达式被称为条件测试。
Python 根据条件测试的值为True还是False来决定是否执行if语句中的代码。
如果条件测试的值为True, Python就执行紧跟在if语句后面的代码.
Python程序语言指定任何非0和非空(null)值为True,0 或者 null为False。
可以通过下图来简单了解条件语句的执行过程:
score = 90
if score >= 90:
print("成绩优秀")
score = 80
if score >= 90:
print("成绩优秀")
else:
print("成绩中等")
score = 60
if score >= 90:
print("成绩优秀")
elif score > 60 :
print("成绩刚刚及格")
else:
print("你没及格喔,加油!")
for循环是在python开发中用的很多的一种循环类型, 需要熟练掌握。
for循环的使用场景
#for循环主要用来遍历、循环、序列、集合、字典
Fruits = ['apple','orange','banana','grape']
for fruit in Fruits:
print(fruit)
print("结束遍历")
结果演示:
apple
orange
banana
grape
结速遍历
#for循环主要用来遍历、循环、序列、集合、字典
#把banana改为Apple
Fruits=['apple','orange','banana','grape']
for i in range(len(Fruits)):
if Fruits[i] == 'banana':
Fruits[i] ='apple'
print(Fruits)
结果演示:['apple', 'orange', 'apple', 'grape']
Fruits=['apple','orange','banana','grape']
for i in Fruits:
if i == 'banana':
Fruits.remove(i)
print(Fruits)
结果演示:['apple', 'orange', 'grape']
#统计apple的个数
Fruits = ['apple','orange','banana','grape','apple']
count = 0
for i in Fruits:
if i=='apple':
count+=1
print("Fruits列表中apple的个数="+str(count)+"个")
结果演示:Fruits列表中apple的个数=2个
注:列表某一数据统计还可以使用Fruit.count(object)
sum=1
for i in list(range(1,10)):
sum *= i
print("1*2...*9=" + str(sum))
结果演示:1*2...*10=362880
for str in 'abc':
print(str)
结果演示:
a
b
c
for str in {
'a',2,'bc'}:
print(str)
结果演示:
a
2
bc
for content in open("D:\\test.txt"):
print(content)
结果演示:
朝辞白帝彩云间,千里江陵一日还。
两岸猿声啼不住,轻舟已过万重山。
for key,value in {
"name":'码上开始',"age":22}.items():
print("键---"+key)
print("值---"+str(value))
结果演示:
键---name
值---码上开始
键---age
值---22
你可以定义一个由自己想要功能的函数,以下是简单的规则:
#! /usr/bin/python3
# @Author : 码上开始
def example():
'''
一个简单的函数
'''
print("Hello World !")
example()
打印结果:
Hello World !
三引号中间的内容属于函数的注释文档,注释的作用是告诉别人或以后查看代码知道能快速知道这段干嘛是做什么的。
函数还可以嵌套,也就是函数里面有函数
#! /usr/bin/python3
# @Author : 码上开始
def exapmle(name):
def go(name):
print('我最棒:' + name)
go(name)
example('小明')
打印结果:
我最棒:小明
形参和实参
#! /usr/bin/python3
# @Author : 码上开始
def example(username):
print("Hello World ! My name is " + str(username))
example("小明")
example("小花")
打印结果:
Hello World ! My name is 小明
Hello World ! My name is 小花
这是一个带参数的函数,在函数example中,username就是一个形参,也就是形式参数,是用来接收调用函数时传入的参数,你传的是啥它就是啥,传人它就是人,传鬼它就是鬼的那种。
实参就是实际参数,在调用函数的时候,传递是小明,那么小明就是实参,传递的是小花,那么小花也是实参,实参传递给函数后,会赋值给函数中的形参,然后我们就可以在函数中使用到外部传入的数据了。
写Java的时候最痛恨的就是方法不能设置默认值,使得必须得重载才行。
python允许我们给函数的形参设置一个默认值,不传参数调用的话,就统一默认是这个值。
#! /usr/bin/python3
# @Author : 码上开始
def welcome(username = '奥特曼'):
print("Hello World ! My name is " + str(username))
welcome("小明")
welcome()
打印结果:
Hello World ! My name is 小明
Hello World ! My name is 奥特曼
在函数中修改参数内容会不会影响到外部,这个问题取决于实参的类型是不是可变的,可不可变就是可不可以修改。
字符串就是一种不可变的类型。
比如:
name = “小明”
name = “小花”
请问,我是把"小明"修改成了"小花"吗? 答案是 非也。
实际上我是把"小花"这个字符串赋值给了name,让name指向了这个新字符串,替换掉了原来的"小明",原来的"小明"仍然是"小明",没有受到一点改变。
在python中,不可变类型有:整数、字符串、元组,可变类型有:列表、字典。如果传递的参数包含可变类型,并且在函数中对参数进行了修改,那么就会影响到外部的值。
#! /usr/bin/python3
# @Author : 码上开始
def change(lis):
lis[1] = '小明他二舅'
names = ['小明','小花','小红']
change(names)
print(names)
打印结果:
[‘小明’, ‘小明他二舅’, ‘小红’]
如果我们不希望出现这种事情,那么就将对象复制一份再传递给函数。
#! /usr/bin/python3
# @Author : 码上开始
def change(lis):
lis[1] = '小明他大爷'
names = ['小明','小花','小红']
change(names[:])
print(names)
打印结果:[‘小明’, ‘小花’, ‘小红’]
我们用切片的方法拷贝了一份names,函数中尽管修改了参数,也不过是修改的是副本,不会影响到原始的names。
关键字参数让你可以不用考虑函数的参数位置,你需以键值对的形式指定参数的对应形参。
#! /usr/bin/python3
# @Author : 码上开始
def welcome(name,address):
print(f"你好 {
name} , 欢迎来到 {
address} !")
welcome(address='长沙',name='小强')
打印结果:你好 小强 , 欢迎来到 长沙 !
有时候我们需要允许用户提供任意数量的参数,函数的形参可以带个星号来接收,不管调用函数的时候传递了多少实参,都将被收集到形参这个变量当中,形参的类型是元组。
#! /usr/bin/python3
# @Author : 码上开始
def welcome(*names):
print(names)
welcome('乐迪','天天','酷飞','小黑')
打印结果:(‘乐迪’, ‘天天’, ‘酷飞’, ‘小黑’)
还有一种是带两个星号的形参,用于接收键值对形式的实参,导入到函数中的类型是字典。
#! /usr/bin/python3
# @Author : 码上开始
def welcome(**names):
print(names)
welcome(name='小明',age=20,sex='男')
打印结果:{‘name’: ‘小明’, ‘age’: 20, ‘sex’: ‘男’}
分配参数是收集参数的相反操作,可使得一个元组或字典变量自动分配给函数中的形参。
#! /usr/bin/python3
# @Author : 码上开始
def welcome(name,address):
print(f"你好 {
name} , 欢迎来到 {
address} !")
a = ('小明','广州')
welcome(*a)
打印结果:你好 小明 , 欢迎来到 广州 !
我们改成字典的方式:
#! /usr/bin/python3
# @Author : 码上开始
def welcome(name,address):
print(f"你好 {
name} , 欢迎来到 {
address} !")
a = {
'address':'山东','name':'小红'}
welcome(**a)
打印结果:你好 小红 , 欢迎来到 山东 !
首先说明,所有的函数都是有返回值的,如果编程人员没有指定返回值,那么默认会返回None,对标其他语言中的null。
一个简单的函数返回值的例子:
#! /usr/bin/python3
# @Author : 码上开始
def get_full_name(first_name,last_name):
return first_name + last_name
r = get_full_name('王','大拿')
print(r)
打印结果:王大拿
然而python中的函数还可以返回多个值,返回出的值被装载到元组中:
#! /usr/bin/python3
# @Author : 码上开始
def func(num):
return num**2,num**3,num**4
result = func(2)
print(result)
打印结果:(4, 8, 16)
在python中函数定义的时候没有返回值的签名,导致我们无法提前知道函数的返回值是什么类型,返回的什么完全看函数中的return的是什么,特别是逻辑代码比较多的函数,比如里面有多个if判断,有可能这个判断return出来的是布尔值,另一个判断return出来的是列表,还一个判断啥也不return,你调用的时候你都搞不清楚该怎么处理这个函数的返回值,在这一点来说,Java完胜。
所以在无规则限制的情况下,代码写的健不健壮,好不好用,主要取决于编程人员的素质。
匿名函数就是不用走正常函数定义的流程,可以直接定义一个简单的函数并把函数本身赋值给一个变量,使得这个变量可以像函数一样被调用,在python中可以用lambda关键字来申明定义一个匿名函数。
我们把王大锤的例子改一下:
# -*- coding: utf-8 -*-
# @Author : 一凡
get_full_name = lambda first_name,last_name : first_name + last_name
r = get_full_name('王','大锤')
print(r)
打印结果:王大锤
访问全局作用域
python每调用一个函数,都会创建一个新命名空间,也就是局部命名空间,函数中的变量就叫做局部变量,与外部的全局命名空间不会相互干扰。
这是常规状态,当然也会有非常规需求的时候,所以python给我们提供了globals()函数,让我们可以在局部作用域中访问到全局的变量。
#! /usr/bin/python3
# @Author : 码上开始
def func():
a = globals()
print(a['name'])
name = '小明'
func()
打印结果:小明
globals()函数只能让我们访问到全局变量,但是是无法进行修改的,如果我们要修改全局变量,需要用到global关键字将全局变量引入进来。
#! /usr/bin/python3
# @Author : 码上开始
def func():
global name
name = '小花'
name = '小明'
func()
print(name)
打印结果:小花
类顾名思义,就是一类事物、或者叫做实例,它用来描述具有共同特征的一类事物
我们在Python中声明类的关键词是class,类还有功能和属性,属性就是这类事物的特征,而功能就是它能做什么,也是就是方法或者函数
比如把人为一类,人的名字,年龄,身高,肤色是属性,人可以跑,跳这种为方法
定义类:
class 类名(object):
def function1(self):
pass
def function2(self):
pass
.....
# -*- coding: utf-8 -*-
# @Author : 码上开始
class Test():
def __init__(self):
print("我是构造方法, 实例化对像后就会自动调用")
def test01(self):
print("该方法没有执行")
test = Test()
# 运行结果
我是构造方法, 实例化对像后就会自动调用
# -*- coding: utf-8 -*-
# @Author : 码上开始
class Phone(object):
def __init__(self):
self.phone_money = 3500
def money(self):
print("手机价格是:", self.phone_money)
# 实例化对像
test = Phone()
test.money()
# 运行结果
手机价格是: 3500
我提高了手机购买预算,价格为6000,通过直接修改默认价格的方法修改
# -*- coding: utf-8 -*-
# @Author : 码上开始
class Phone(object):
def __init__(self):
self.phone_money = 3500
def money(self):
print("手机价格是:", self.phone_money)
# 实例化对像
test = Phone()
# 直接修改价格--对像名.属性名
test.phone_money= 6500
test.money()
# -*- coding: utf-8 -*-
# @Author : 码上开始
class Phone(object):
def money(self, m):
self.mobile_money = m
print("手机价格是:", self.mobile_money)
# 实例化对像
test = Phone()
test.money(5000)
test.money(6000)
# 运行结果
手机价格是: 5000
手机价格是: 6000
# -*- coding: utf-8 -*-
# @Author : 码上开始
class Phone(object):
def __init__(self):
self.phone_money = 3500
def update(self,money):
self.phone_money += money
print("手机价格是:", self.phone_money)
# 实例化对像
test = Phone()
test.update(2500)
# 运行结果
手机价格是:6000
实例:
# -*- coding: utf-8 -*-
# @Author : 码上开始
class Mobile:
'''创建父类手机'''
def call(self):
print("可以拨打电话")
# 创建智能手机子类,且继承父类
class Smartphone(Mobile):
'''创建智能手机子类'''
pass
# 子类实例
phone = Smartphone()
# 子类调用父类方法
phone.call()
子类和父类中拥有方法名相同的方法,说明子类重写了父类的方法
重写的作用:父类中已经有了这个方法,但子类想修改里面的内容,直接修改父类是不好的,就需要用到重写
实例:
# -*- coding: utf-8 -*-
# @Author : 码上开始
class Mobile:
'''创建父类手机'''
def call(self):
print("可以拨打电话")
# 创建智能手机子类,且继承父类
class Smartphone(Mobile):
'''创建智能手机子类'''
def call(self):
print("不仅可以打电话,还能发送微信语音")
# 子类实例
phone = Smartphone()
# 调用自己方法,重写父类call方法
phone.call()
# -*- coding: utf-8 -*-
# @Author : 码上开始
class Mobile:
'''创建父类手机'''
def call(self):
print("可以拨打电话")
class Music():
movie = "可以看电影"
def music(self):
print("可以播放音乐")
# 继承了多个父类
class Smartphone(Mobile, Music):
pass
# 子类实例
phone = Smartphone()
# 调用父类方法
phone.call()
phone.music()
# 调用类中属性
print(phone.movie)
class Father():
def __init__(self):
print("自动调用父类构造方法")
def hello(self):
print("hello, 码上开始")
class Son(Father):
pass
son = Son()
son.hello()
以封装和继承为前提,不同的子类对像调用相同的方法,产生不同的执行结果
在定义变量时,不需要提前指定数据类型,变量的数据类会根据你赋值的数据来决定
a= 1当前为整数类型
a="hello"当前为字符串类型
# @Time : 2021/1/9 16:11
# @Author : 码上开始
class WeChatPay():
def payfor(self):
print("微信支付")
class ALiPay():
def payfor(self):
print("支付宝支付")
class StartPay():
def start(self, pay_method):
pay_method.payfor()
wx = WeChatPay()
zfb = ALiPay()
zf = StartPay()
# 传入微信实例对像
zf.start(wx)
# 传入支付宝实例对像
zf.start(zfb)
try:
pass
except Exception as e:
print(e)
try:
pass
except Exception as e:
print("No exception")
else:
print("我打印的是else")
try:
pass
except Exception as e:
print("Exception: ", e)
finally:
print("try is done")
使用raise来抛出一个异常:
a = 0
if a == 0:
raise Exception("a must not be zero")
最好指出异常的具体类型,如:
a = 0
if a == 0:
raise ZeroDivisionError(``"a must not be zero"``)
python中的logging模块用于记录日志。用户可以根据程序实现需要自定义日志输出位置、日志级别以及日志格式。
一个最简单的logging模块使用样例,直接打印显示日志内容到屏幕。
import logging
logging.critical("critical log")
logging.error("error log")
logging.warning("warning log")
logging.info("info log")
logging.debug("debug log")
输出结果如下:
CRITICAL:root:critical log
ERROR:root:error log
WARNING:root:warning log
说明:默认情况下python的logging模块将日志打印到标准输出,并且只显示大于等于warning级别的日志(critical > error > warning > info > debug)。
将日志事件记录到文件是一种非常常见的情况,方便出现问题时快速定位问题。在logging模块默认配置条件下,记录日志内容,代码如下:
import logging
logging.basicConfig(filename='example.log',level=logging.DEBUG)
logging.debug('This message should go to the log file')
logging.info('So should this')
logging.warning('And this, too')
输出结果如下:
D:\pycharm\work>type example.log
DEBUG:root:This message should go to the log file
INFO:root:So should this
WARNING:root:And this, too
说明:type为dos窗口下查看文件内容命令
根据程序运行对日志记录的要求,通常需要自定义日志显示格式、输出位置以及日志显示级别。可以通过logging.basicConfig()定制满足自己要求的日志输出格式。
import logging
logging.basicConfig(format='[%(asctime)s %(filename)s line:%(lineno)d] %(levelname)s: %(message)s',
level=logging.DEBUG, filename="log.txt", filemode="w")
logging.debug('This message should appear on the console')
logging.info('So should this')
logging.warning('And this, too')
输出结果如下:
```python
D:\pycharm\work>type log.txt
[2020-02-02 10:31:42,994 json_pro.py line:5] DEBUG: This message should appear on the console
[2020-02-02 10:31:42,995 json_pro.py line:6] INFO: So should this
[2020-02-02 10:31:42,995 json_pro.py line:7] WARNING: And this, too
通过修改logging.basicConfig()函数中参数取值来定制日志显示。函数参数定义及含义如下:
filename 指定日志写入文件名。
filemode 文件打开方式,默认值为"a"
format 设置日志显示格式
dateft 设置日期时间格式
level 设置显示日志级别
stream 指定stream创建StreamHandler。可以指定输出到sys.stderr,sys.stdout或者文件。默认为sys.stderr。
format参数用到的格式化字符串如下:
%(asctime)s 字符串形式的当前时间。默认格式是 “2003-07-08 16:49:45,896”。逗号后面的是毫秒
%(filename)s 调用日志输出函数的模块的文件名
%(levelname)s 文本形式的日志级别
%(funcName)s 调用日志输出函数的函数名
%(lineno)d 调用日志输出函数的语句所在的代码行
%(message)s 用户输出的消息
%(module)s 调用日志输出函数的模块名
如果开发的程序包含多个模块,就需要考虑日志间的记录方式。基本样例如下:
主程序文件:
import logging
import mylib
def main():
logging.basicConfig(format='[%(asctime)s %(filename)s line:%(lineno)d] %(levelname)s: %(message)s',
level=logging.DEBUG, filename="log.txt", filemode="w")
logging.info('Started')
mylib.do_something()
logging.info('Finished')
if __name__ == '__main__':
main()
logging模块可以通过FileHander和StreamHandler分别制定向文件和屏幕输出。
import logging
logger = logging.getLogger() # 不加名称设置root logger
logger.setLevel(logging.DEBUG)
formatter = logging.Formatter(
'%(asctime)s - %(name)s - %(levelname)s: - %(message)s',
datefmt='%Y-%m-%d %H:%M:%S')
# 使用FileHandler输出到文件
fh = logging.FileHandler('log.txt')
fh.setLevel(logging.DEBUG)
fh.setFormatter(formatter)
# 使用StreamHandler输出到屏幕
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
ch.setFormatter(formatter)
# 添加两个Handler
logger.addHandler(ch)
logger.addHandler(fh)
logger.info('this is info message')
logger.warning('this is warn message')
控制台输出如下:
[2020-02-02 10:58:16 json_pro.py line:22] INFO: this is info message
[2020-02-02 10:58:16 json_pro.py line:23] WARNING: this is warn message
日志文件内容如下:
D:\pycharm\work>type log.txt
[2020-02-02 10:58:55 json_pro.py line:22] INFO: this is info message
[2020-02-02 10:58:55 json_pro.py line:23] WARNING: this is warn message
当我们在Python中需要使用到时间的时候,有两个关于时间的模块,分别是time和datetime。time模块偏底层,在部分函数运行的时候可能会出现不同的结果,而datetime模块提供了高级API,使用起来更为方便,我们通常在使用的时候会涉及到包含时间和日期的datetime、只包含日期的date以及只包含时间的time,本节我们就对这三种方法进行学习。
datetime.dateto,e(year, month, day, hour``=``0``, minute``=``0``, second``=``0``, microsecond``=``0``, tzinfo``=``None``, ``*``, fold``=``0``)
其中year,month和day是不能缺少的,tzinfo为时区参数,可以为None或其他参数,其余参数的范围如下:
MINYEAR <= year <= MAXYEAR,
1 <= month <= 12,
1 <= day <= number of days in the given month and year,
0 <= hour < 24,
0 <= minute < 60,
0 <= second < 60,
0 <= microsecond < 1000000,
fold in [0, 1].
#! /usr/bin/python3
# @公众号 : 码上开始
import datetime
# 返回当前日期及时间
now_time = datetime.datetime.now()
print(now_time)
输出结果为:
2020``-``02``-``01` `19``:``18``:``59.926474
#! /usr/bin/python3
# @公众号 : 码上开始
import datetime
#返回当前日期及时间``
now_time= datetime.datetime.now()
#输出当前的日期
print(now_time.date())
输出结果:
2020``-``02``-``01
代码如下:
#! /usr/bin/python3
# @公众号 : 码上开始
import datetime
#返回当前日期及时间
now_time = datetime.datetime.now()
#输出当前的时间
print(now.time())
输出结果为:
19``:``22``:``10.948940
date对象是日期的专属对象,语法格式如下:
datetime.date(year,month,day),参数分别代表年月日。
#! /usr/bin/python3
# @公众号 : 码上开始
import datetime
#返回当前日期
now_time = datetime.date.today()
print(now_time)
输出结果为:
2020``-``02``-``01
这种方式返回与时间戳对应的日期,代码如下:
#! /usr/bin/python3
# @公众号 : 码上开始
import datetime
import time
c = time.time()
#返回当前的时间戳
print('当前的时间戳为:' ,c)
now_time = datetime.date.fromtimestamp(c)
#与时间戳对应的日期
print('当前时间戳对应的日期为:', now_time)
输出结果为:
当前的时间戳为: ``1580556848.3161435``当前时间戳对应的日期为: ``2020``-``02``-``01
在这个例题中我们先引入了time模块中的方法,time模块中的time.time()能返回当前时间戳,然后我们使用上面的方法可以返回与时间戳对应的日期。
time类中包含了一整天的信息,语法结构如下:
datetime.time(hour,moniute,second,microsecond,tzinfo``=``None``)
最后一个时区可以省略,看下面例子:
#! /usr/bin/python3
# @公众号 : 码上开始
import datetime
now_time = datetime.time(19, 42, 34, 12)
print(now_time)
输出结果为:
19:42:34.000012
由于datetime模块中封装了time模块,所以我们使用datetime模块可以保证数据更为精确,在使用过程中也可以穿插着time模块中的部分功能,例如暂停time.sleep()等方法。
在自动化测试中,经常需要查找操作文件,比如说查找配置文件(从而读取配置文件的信息),查找测试报告(从而发送测试报告邮件),经常要对大量文件和大量路径进行操作,这就依赖于os模块,所以今天整理下比较常用的几个方法。
#! /usr/bin/python3
# @Author : 码上开始
import os
# 查看当前路径文件路径
print(os.getcwd())
# 运行结果
E:\study
#! /usr/bin/python3
# @Author : 码上开始
import os
# 当前路径有哪些文件,返回的路径有哪些文件
print(os.listdir(os.getcwd()))
# 运行结果
['day1.py', 'day2.py', 'day3.py', 'day4.py', 'day5.py']
mkdir()
方法使用数字模式模式创建一个名为path
的目录。默认模式为0777
(八进制)#! /usr/bin/python3
# @Author : 码上开始
import os
os.mkdir("E:/study/hello")
#! /usr/bin/python3
# @Author : 码上开始
import os
os.rmdir("E:/study/hello")
#! /usr/bin/python3
# @Author : 码上开始
import os
os.rmdir("E:/study/hello/day6.py")
#! /usr/bin/python3
# @Author : 码上开始
import os
print(os.path.dirname("E:/study/day5.py"))
#运行结果
E:/study
#! /usr/bin/python3
# @Author : 码上开始
import os
print(os.path.join("E:/study/", 'day6.py'))
#运行结果
E:/study/day6.py
#! /usr/bin/python3
# @Author : 码上开始
import os
print(os.path.split("E:\study\day4.py"))
# 运行结果
('E:\\study', 'day4.py')
#! /usr/bin/python3
# @Author : 码上开始
import os
print(os.path.splitext("E:\study\day4.py"))
# 运行结果
('E:\\study\\day4', '.py')
#! /usr/bin/python3
# @Author : 码上开始
import os
print(os.path.getmtime("E:/study/old.html"))
print(os.path.getmtime("E:/study/new.html"))
# 运行结果
1597062314.1353853
1597062332.269248
#! /usr/bin/python3
# @Author : 码上开始
import random
num = random.random()
print(num)
# 运行结果
0.5234072981721078
#! /usr/bin/python3
# @Author : 码上开始
import random
num = random.uniform(1, 10)
print(num)
#运行结果
2.1220664313759947
#! /usr/bin/python3
# @Author : 码上开始
import random
num = random.randint(1, 10)
print(num)
# 运行结果
6
#! /usr/bin/python3
# @Author : 码上开始
import random
num = random.choice(["135", "138", "186"])
print(num)
# 运行结果
135
#! /usr/bin/python3
# @Author : 码上开始
import random
list = [1, 2, 3, 4]
random.shuffle(list)
print("随机排序列表 : ", list)
random.shuffle(list)
print("随机排序列表 : ", list)
# 运行结果
随机排序列表 : [2, 4, 1, 3]
随机排序列表 : [3, 1, 2, 4]
#! /usr/bin/python3
# @Author : 码上开始
import random
num = random.sample(["135", "138", "186"], 2)
print(num)
# 运行结果
['186', '135']
在软件需求、开发、测试过程中,有时候需要使用一些测试数据,针对这种情况,我们一般要么使用已有的系统数据,要么需要手动制造一些数据。
在手动制造数据的过程中,可能需要花费大量精力和工作量,现在好了,有一个Python包能够协助你完成这方面的工作。
1.什么是Faker
Faker是一个Python包,开源的GITHUB项目,主要用来创建伪数据,使用Faker包,无需再手动生成或者手写随机数来生成数据,只需要调用Faker提供的方法,即可完成数据的生成。
项目地址:https://github.com/joke2k/faker
pip install Faker
如果下载速度比较慢的话,可以使用国内镜像源来下载
例如:pip3 install -i https://pypi.doubanio.com/simple/ faker
from faker import Faker
#创建对象,默认生成的数据为为英文,使用zh_CN指定为中文
fake = Faker('zh_CN')
print(fake.name())#随机生成姓名
print(fake.address())#随机生成地址
print(fake.phone_number())#随机生成电话号码
print(fake.pystr())#随机生成字符串
print(fake.email())#随机生成邮箱地址
for i in range(10):
print(fake.name())#随机生成10个姓名
输出:
徐博
云南省玉市璧山梧州路p座 523028
13039830591
RPHadhNxNMISoBTbQbQn
[email protected]
张淑英
叶燕
陈琳
王俊
胡秀荣
阮淑英
徐娟
黄冬梅
梁丽华
袁琴
由于SMPT太过于麻烦复杂,所以就用zamil发送邮件试试。
zmail模块只支持Python3模块,该模块为第3方模块,需自行安装(pip install zmail)
使用 Zmail 发送接收邮件方便快捷,不需手动添加服务器地址、端口以及适合的协议,可以轻松创建 MIME 对象和头文件
注意:Zmail 仅支持 Python3,不支持 Python2
#!/usr/bin/python3
import zmail
def send_mail():
# 定义邮件
mail = {
"subject": "接口测试报告",# 任一填写
'content_text': '手机号归属地_API自动化测试报告',# 任一填写
# 多个附件使用列表
"attachments": "E:/report/result.html"
}
# 自定义服务器
server = zmail.server("发送人邮箱.com",
"QQ邮箱是用授权码",
smtp_host="smtp.qq.com",
smtp_port = 465)
# 发送邮件
server.send_mail("收件人QQ邮箱", mail)
try:
send_mail()
except FileNotFoundError:
print("未找到文件")
else:
print("发送成功")
他们都说yagmail 只需要三行代码,就可以实现发送邮件,爽歪歪!
相比 zmail,yagmail 实现发送邮件的方式更加简洁优雅
首先,安装依赖库(pip install yagmail)
发送邮件有三个步骤:
1、连接服器(类似你先要登录邮箱)
2、编辑邮件内容和主题
3、发送邮件
#!/usr/bin/python3
import yagmail
# 定义用户名、授权码、服务器地址且连接服务器
mail_server = yagmail.SMTP(user='发件人邮箱', passwd='授权码', host='smtp.qq.com')
# 发送对象列表
Email_to = ['收件人邮箱']
subject = '任一填写'
Email_text = "任一填写内容"
# 多个附件用逗号隔开
attachments = ['html报告目录地址']
# 发送邮件
mail_server.send(Email_to, subject, Email_text, attachments)
Page Object Model (POM) 直译为“页面对象模型”,这种设计模式旨在为每个待测试的页面创建一个页面对象(class),将那些繁琐的定位操作封装到这个页面对象中,只对外提供必要的操作接口,是一种封装思想。
#! /usr/bin/python3
#-*- coding:utf-8 -*-
'''管理登录页面所有的元素,操作这些元素的方法'''
from selenium.webdriver.common.by import By
class LoginPage:
username_input = (By.XPATH,'//*[@id="name"]') #登录页面的用户名输入框
password_input = (By.XPATH,'//*[@id="password"]') #登录页面的密码输入框
login_button = (By.XPATH,'//*[@id="submit"]') #登录按钮
#! /usr/bin/python3
#-*- coding:utf-8 -*-
from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
'''封装一些常用公共方法'''
class InitBrowser():
'''浏览器常用操作封装'''
def __init__(self):
self.driver = webdriver.Firefox() # 启动谷歌浏览器
self.driver.get('https://sso.kuaidi100.com/sso/authorize.do') # 打开网站
def wait_element_visible(self, locate):
ele = WebDriverWait(self.driver, 10).until(EC.visibility_of_element_located(locate)) #等待元素出现再去操作
print('等待元素出现')
return ele
def click_until_visible(self, locate):
self.wait_element_visible(locate).click()
def send_keys_until_visible(self, locate, value):
self.wait_element_visible(locate).send_keys(value)
#! /usr/bin/python3
#-*- coding:utf-8 -*-
'''管理测试用例'''
import unittest
from common import InitBrowser
# 导入Pages文件下的login_page文件中的LoginPage类
from Pages.login_page import LoginPage
class TestCases(unittest.TestCase, InitBrowser, LoginPage):
def setUp(self) -> None:
'''前置操作初始化:打开浏览器,连接数据库,初始化数据'''
InitBrowser.__init__(self)
def testcase01(self):
'''测试用例'''
self.send_keys_until_visible(LoginPage.username_input, "账号")
self.send_keys_until_visible(LoginPage.password_input, "密码")
self.click_until_visible(LoginPage.login_button)
def tearDown(self) -> None:
'''后置操作:关闭浏览器,关闭数据库连接,清理测试数据'''
self.driver.quit()
if __name__=='__main__':
unittest.main()
id | url | boke |
---|---|---|
1 | https://blog.csdn.net/laozhu_Python | 骑着乌龟找猪 |
2 | https://www.cnblogs.com/zzpython | 码上开始 |
处理一个表格,首先要知道路径,所以我们需要知道文件路径然后打开这张表
#! /usr/bin/python3
# @Time : 2020/8/5 13:30
# @Author : 码上开始
import xlrd
# 定义文件路径
path = "E:/data.xls"
# 然后打开一个表
data = xlrd.open_workbook(path)
打开表之后,通过获取表对像来操作这个表,相当于我们用鼠标选中这个Sheet1就能操作这个表里内容了,明白了吗?
#! /usr/bin/python3
# @Author : 码上开始
import xlrd
# 定义文件路径
path = "E:/data.xls"
# 然后打开一个表
data = xlrd.open_workbook(path)
# 通过表名获取表对象,用于操作表
sheet1 = data.sheet_by_name("Sheet1")
#! /usr/bin/python3
# @Author : 码上开始
import xlrd
# 打开需要操作的表
path = "E:/data.xls"
data = xlrd.open_workbook(path)
# 通过下标获取表对象,用于操作表
sheet1 = data.sheet_by_name("Sheet1")
# 列数
cols = sheet1.ncols
# 行数
rows = sheet1.nrows
#! /usr/bin/python3
# @Author : 码上开始
import xlrd
# 打开需要操作的表
path = "E:/data.xls"
data = xlrd.open_workbook(path)
# 通过下标获取表对象,用于操作表
sheet1 = data.sheet_by_name("Sheet1")
# 列数
cols = sheet1.ncols
# 行数
rows = sheet1.nrows
# 定义空列表和字典用于存放数据
list = [ ]
# 获取第一行的值
one_value = sheet1.row_values(0)
# 通过打印来检查是不是获取到表里第一行的值
print(one_value)
#! /usr/bin/python3
# @Author : 码上开始
import xlrd
# 打开需要操作的表
path = "E:/data.xls"
data = xlrd.open_workbook(path)
# 通过下标获取表对象,用于操作表
sheet1 = data.sheet_by_name("Sheet1")
# 列数
cols = sheet1.ncols
# 行数
rows = sheet1.nrows
# 定义空列表和字典用于存放数据
list = [ ]
# 获取第一行的值
one_value = sheet1.row_values(0)
# 打印结果是:["id", "url", "boke"]
print(one_value)
# 代码最重要的一段
# 外循环行数(我们从excel表里第2行开始,即下标从1开始,括号里即(1, 3)总循环次数两次
for i in range(1, rows):
# 定义一个字典存放每一行的数据
dict = {
}
# 列的数据则是从0开始(就是第1列)结束是我们或取的列值即:(0, 3)
for y in range(0, cols):
# 第一次循环字典是这样写入的:dict["id"] = 1
# 然后依次把数字套进去
dict[one_value[y]] = sheet1.row_values(i)[y]
# 然后将字典数据存放在列表中
list.append(dict)
print(list)
运行结果
[{
'id': '1', 'url': 'https://blog.csdn.net/laozhu_Python', 'boke': '骑着乌龟找猪'}, {
'id': '2', 'url': 'https://www.cnblogs.com/zzpython/', 'boke': '码上开始'}]
实际工作中,我们经常需要用Python读取文txt文件中的数据. 我们使用open()函数来打开一个文件, 获取到文件句柄. 然后通过文件句柄就可以进行各种各样的操作了. 根据打开方式的不同能够执行的操作也会有相应的差异
#! /usr/bin/python3
# @公众号 : 码上开始
file = open("E:\\study\\good.txt", "r", encoding="utf-8")
line = file.read()
print(line)
# open模式打开文件一定要记得关闭操作
file.close()
# 运行结果
好好学习
公众号:码上开始
#! /usr/bin/python3
# @公众号 : 码上开始
f = open("study.txt", mode="w", encoding="utf-8")
f.write("好好学习Python")
# 刷新. 养成好习惯
f.flush()
f.close()
#! /usr/bin/python3
# @公众号 : 码上开始
file = open("study.txt", mode="r+", encoding="utf-8")
# 先读取
content = file.read()
# 再写入
file.write("好好学, 天天向上")
print(content)
# 刷新. 养成好习惯
f.flush()
file.close()
# 运行结果
好好学, 天天向上
#! /usr/bin/python3
# @公众号 : 码上开始
file = open("study.txt", mode="a+", encoding="utf-8")
# 先读取
content = file.read()
# 再写入
file.write("好好学习")
file.write("天天向上")
# 刷新. 养成好习惯
f.flush()
print(file.readline())
file.close()
学Python的小伙伴都知道,Python学习过程中需要装不少的第3方的库,今天就和大家一起分享下第3方库的安装方法
通过Terminal安装(Pycharm版本为社区版,版本不同可能存在位置差异,请查行查找)
在线安装模式经常会出现安装失败的情况,这时候可以进行离线安装方式
有时候在线安装第三方模块的时,会因为网络原因总是装不上,那怎么办呢?那就手动安装
在我学习Ui自动化时,总会遇到浏览器驱动版本问题,小伙伴也是一头雾水也找不到下载的地方,今天给大家整理
chromedriver版本 | 支持的chrome版本 |
---|---|
v2.46 | v72-74 |
v2.45 | v70-72 |
v2.44 | v69-71 |
v2.43 | v69-71 |
v2.42 | v68-70 |
v2.41 | v67-69 |
v2.40 | v66-68 |
v2.39 | v66-68 |
v2.38 | v65-67 |
v2.37 | v64-66 |
v2.36 | v63-65 |
v2.35 | v62-64 |
v2.34 | v61-63 |
v2.33 | v60-62 |
v2.32 | v59-61 |
v2.31 | v58-60 |
v2.30 | v58-60 |
==============================================================================
点击进入微软edge浏览器wendriver版
我们在做WEB自动化时,经常听到小伙伴说,明明代码没问题,死活定位不到元素,一运行就报错啊。是因为有时候因为网络或其它原因导致我们需要定位的元素还没加载出来,我们代码就执行下一步操作了,这个时候就需要我们在某些场景下加等待时间。
我们平常用到的有三种等待方式:
# -*- coding: utf-8 -*-
# @Author : 一凡
from selenium import webdriver
# 启动浏览器
driver = webdriver.Chrome()# 打开百度首页
driver.get('https://www.baidu.com/')# 强制等待3秒
time.sleep(3)
driver.find_element_by_css_selector("#kw").send_keys("python")# 退出
driver.quit()
第二种办法叫隐性等待,implicitly_wait(xx),隐性等待的意义是:闪电侠和凹凸曼约定好,不论闪电侠去哪儿,都要等凹凸曼xx秒,如果凹凸曼在这段时间内来了,则俩人立即出发去打怪兽,如果凹凸曼在规定时间内没到,则闪电侠自己去,那自然就等着凹凸曼给你抛异常吧。
# -*- coding: utf-8 -*-
# @Author : 一凡
# 启动浏览器
driver = webdriver.Chrome()# 打开百度首页
driver.get(r'https://www.baidu.com/')
driver.find_element_by_css_selector("#kw").send_keys("python")
driver.find_element_by_css_selector("#su").click()# 隐式等待30秒
driver.implicitly_wait(30)
result = driver.find_elements_by_css_selector("h3.t>a")for i in result:print(i.text)# 退出
driver.quit()
第三种办法就是显性等待,WebDriverWait,配合该类的until()和until_not()方法,就能够根据判断条件而进行灵活地等待了。它主要的意思就是:程序每隔xx秒看一眼,如果条件成立了,则执行下一步,否则继续等待,直到超过设置的最长时间,然后抛出TimeoutException。
主要有4个参数:
# -*- coding: utf-8 -*-
# @Author : 一凡
from seleniumimport webdriver
from selenium.webdriver.support.wait importWebDriverWait
driver = webdriver.Chrome()# 打开百度首页
driver.get(r'https://www.baidu.com/')
driver.find_element_by_css_selector("#kw").send_keys("selenium")
driver.find_element_by_css_selector("#su").click()# 超时时间为30秒,每0.2秒检查1次,直到class="tt"的元素出现
text =WebDriverWait(driver, 30, 0.2).until(lambda x:x.find_element_by_css_selector(".tt")).text
print(text)# 退出
driver.quit()
需求:
问题解析:
1.打开txt文件
2.读取每一行数据
3.将文件存放在列表中(方便循环读取)
# -*- coding: utf-8 -*-
# @Author : 一凡
with open("E:/test.txt", "r") as f:
#readlines读取文件内每一行数据
for line in f.readlines():
line = line.strip('\n') #去掉列表中每一个元素的换行符
# split():拆分字符串。通过指定分隔符对字符串进行切片,并返回分割后的字符串列表(list)
data = (line.split(","))
print(data)
小伙伴都知道,测试用例是写在Excel里的,如果是少量的用例很容易处理,如果用例成百上千条呢?
自动化测试的话,需要对用例数据进行读取,那必须循环读取才可以实现自动化。那么问题来了,怎么做呢?
用例如下图:
问题解析:
1、用列表存放这些用例数据,所以要用到列表
2、每一行用例要存放在字典内,所以需要用到字典
3、循环写入到字典,然后存放到列表内
# -*- coding: utf-8 -*-
# @Author : 一凡
import xlrd
class excel_data:
"""读取excl表接口数据"""
data_path = "E:\\api_interface\\data\\interface.xlsx"
# 打开文件
excel = xlrd.open_workbook(data_path)
# 通过下标定位表格
sheet = excel.sheet_by_index(0)
# 行: 6 和列数: 5
rows, cols = sheet.nrows, sheet.ncols
def read_excl(self):
# 获取第一行数据key
first_row = self.sheet.row_values(0)
# print(first_row) # [编号,接口方式,host, params, result]
# 定义空列表,用于存放用例数据
self.result = []
# 从第一行用例开始循环(1, 6)循环5次
for i in range(1, self.rows):
# 定义空字典
info_dict = {
}
# 每1次大循环要循环5次(字典里有5组数据)
for j in range(0, self.cols):
# j=0,1,2,3,4
# 添加到字典 (1)[0]---第2行第1例的值,依次循环
info_dict[first_row[j]] = self.sheet.row_values(i)[j]
# 将数据存放在列表中
self.result.append(info_dict)
print(self.result)
if __name__ == "__main__":
ex = excel_data()
ex.read_excl()
#!/usr/bin/python3
import yaml
import os
# 获取当前脚本所在文件夹路径
curPath = os.path.dirname(os.path.realpath(__file__))
# 获取yaml文件路径
yamlPath = os.path.join(curPath, "E:\\api_interface\\config\\yaml.yaml")
# open方法打开直接读出来
open_file = open(yamlPath, 'r', encoding='utf-8')
result = open_file.read()
file_dict = yaml.load(result, Loader=yaml.FullLoader) # 用load方法转字典
print(file_dict)
大家应该接触过.ini格式的配置文件。配置文件就是把一些配置相关信息提取出去来进行单独管理,如果以后有变动只需改配置文件,无需修改代码。
特别是后续做自动化的测试,代码和数据分享,进行管理。比如说发送邮件的邮箱配置信息、数据库连接等信息。
今天介绍一些如何用Python读取ini配置文件。
一、ini文件格式
;这是注释
[section]
key1 = value1
key2= value2
[section] key3=value3 key4=value4
[section]
:ini的section模块,是下面参数值的一个统称,方便好记就行key = value
:参数以及参数值Py3和Py2区别
# python3
import configParser
# python2
import ConfigParser
二、读取ini文件
Python自带有读取配置文件的模块ConfigParser,配置文件不区分大小写。
有一系列的方法可提供。
read(filename)
:读取文件内容sections()
:得到所有的section,并以列表的形式返回。options(section)
:得到该section的所有option。items(section)
:得到该section的所有键值对。get(section,option)
:得到section中option的值,返回string类型。getint(section,option)
:得到section中option的值,返回int类型。示例:
# -*- coding: utf-8 -*-
# @Author : 一凡
import os
import configparser
# 当前文件路径
proDir = os.path.split(os.path.realpath(__file__))
# 在当前文件路径下查找.ini文件
configPath = os.path.join(proDir, "config.ini")
print(configPath)
conf = configparser.ConfigParser()
# 读取.ini文件
conf.read(configPath)
# get()函数读取section里的参数值
name = conf.get("section1","name")
print(name)
print(conf.sections())
print(conf.options('section1'))
print(conf.items('section1'))
运行结果:
D:\Python_project\python_learning\config.ini
2号
['section1', 'section2', 'section3', 'section_test_1']
['name', 'sex', 'option_plus']
[('name', '2号'), ('sex', 'female'), ('option_plus', 'value')]
三、修改并写入ini文件
write(fp)
:将config对象写入至某个ini格式的文件中。add_section(section)
:添加一个新的section。set(section,option,value)
:对section中的option进行设置,需要调用write将内容写入配置文件。remove_section(section)
:删除某个section。remove_option(section,option)
:删除某个section下的option接上部分
# -*- coding: utf-8 -*-
# @Author : 一凡
# 写入配置文件 set()
# 修改指定的section的参数值
conf.set("section1",'name','3号')
# 增加指定section的option
conf.set("section1","option_plus","value")
name = conf.get("section1","name")
print(name)
conf.write(open(configPath,'w+'))
# 增加section
conf.add_section("section_test_1")
conf.set("section_test_1","name","test_1")
conf.write(open(configPath,'w+'))
自动化测试需要做到代码和数据分离,我们经常需要将不同的数据放到不同的文件内进行读取,比如用例放到Excel表里,配置文件放到ini文件里等等。yaml专门用于写配置文件
pip install pyyaml
yaml文件,test.yaml
user: admin
pwd: 123456
#! /usr/bin/python3
# @Author : 码上开始
import yaml
# 定义yaml文件路径
yaml_path = "E:\\study\\date.yaml"
# 打开yaml文件
file = open(yaml_path, "r", encoding="utf-8")
# 读取
string = file.read()
dict = yaml.load(string)
# 转换后数据类型为:dict
print(type(dict))
print(dict)
# 运行结果:
{
'usr': 'admin', 'pwd': 123456}
- admin1
- admin2
- admin3
#! /usr/bin/python3
# @Author : 码上开始
import yaml
# 定义文件路径
yaml_path = "E:\\study\\date.yaml"
file = open(yaml_path, "r", encoding="utf-8")
string = file.read()
print(string)
# 转换后数据类型为列表
list = yaml.load(string, Loader=yaml.FullLoader)
print(list)
# 运行结果
<class 'list'>
['admin1', 'admin2', 'admin3']
# 布尔值true/false
n: true
# int
n1: 12
# float
n2: 12.3
# None
n3: ~
{
'n': True, 'n1': 12, 'n2': 12.3, 'n3': None}
- usr:
name: admin
pwd: 123456
- mail:
user: [email protected]
pwd: 123456
运行结果:
[{
'usr': {
'name': 'admin', 'pwd': 123456}}, {
'mail': {
'user': '[email protected]', 'pwd': 123456}}]
#! /usr/bin/python3
# @Author : 码上开始
import yaml
写入键值对
# data = {"send_mail": "[email protected]"}
# 写入列表
# data =["[email protected]", "[email protected]"]
# 写入混合数据
# data = [{"mai": {"send": "[email protected]"}}]
# yaml文件路径
yaml_path = "E:\\study\\date.yaml"
# 打开文件,a是在文件末尾写入内容
file = open(yaml_path, "a", encoding="utf-8")
# 写入数据, allow_unicode=True
yaml.dump(data, file)
# 关闭文件
file.close()
运行结果
# 键值对
send_mail: [email protected]
# 列表
- [email protected]
- [email protected]
# 混合数据
- mai:
send: [email protected]
上面我们说了yaml用于在自动化测试中实现代码和数据分离。那么我们在企业项目中如何用yaml实现代码和数据分离呢?有一个场景,我们要发送邮件给指定收件人。
# 发件人邮箱和授权码
- send_mail: [email protected]
password: QQ邮箱的授权码
# 收件人邮箱
- get_mail: [email protected]
#! /usr/bin/python3
# 公众号 : 码上开始
import yaml
def read_yaml():
"""读取yaml文件"""
# 定义yaml文件路径
yaml_path = "E:\\mail\\date\\yaml.yaml"
# 打开yaml文件
file = open(yaml_path, "r")
# 读取文件
string = file.read()
# 转换为python对像,类型为字典
dict = yaml.load(string)
print(dict)
# 返回数据为字典类型
return dict
运行结果
[{
'send_mail': '[email protected]', 'password': 'code'}, {
'get_mail': '[email protected]'}]
# -*- coding: utf-8 -*-
# @Author : 一凡
import zmail
# 导入common文件下的read_yaml函数
from common import read_yaml
# 调用yaml文件里的数据
response = read_yaml.read_yaml()
def send(send_mail, password, get_mail):
"""发送测试报告"""
report_path = "E:\\mail\\report\\test.html"
MAIL = {
'subject': '邮件主题',
'content_text': '测试发送邮件',
'attachments': report_path,
}
server = zmail.server(send_mail, password)
server.send_mail(get_mail, MAIL)
send(response[0]["sendmail"], response[0]["password"], response[1]["getmail"])
自动化测试中,经常需要向数据库添加或删除数据,也需要验证测试数据和数据库的数据是否一致。这个时候就需要用Python连接Mysql
pip install PyMySQL
# -*- coding: utf-8 -*-
# @Author : 一凡
import pymysql
# 打开数据库连接
db = pymysql.connect("localhost", "root", "111223", "study_date")
# 使用 cursor() 方法创建一个游标对象 cursor
cursor = db.cursor()
# 使用 execute() 方法执行 SQL 查询
cursor.execute("SELECT VERSION()")
# 使用 fetchone() 方法获取单条数据.
data = cursor.fetchone()
print("Database version : %s " % data)
# 关闭数据库连接
db.close()
insert 语句可以用来将一行或多行数据插到数据库表中, 使用的一般形式如下:
insert into 表名 [(列名1, 列名2, 列名3, ...)] values (值1, 值2, 值3, ...);
# -*- coding: utf-8 -*-
# @Author : 一凡
import pymysql
# 打开数据库连接
db = pymysql.connect("localhost", "root", "111223", "study_date")
# 使用cursor()方法获取操作游标,以字典的方式获取数据,原数据类型为元组
cursor = db.cursor(cursor=pymysql.cursors.DictCursor)
insert_sql = "insert into studys(id, name, age) values(3, '骑着乌龟赶猪', 35)"
# 执行sql语句
cursor.execute(insert_sql)
# 提交到数据库执行
db.commit()
# 关闭数据库连接
db.close()
delete 语句用于删除表中的数据
delete from 表名称 where 删除条件;
# -*- coding: utf-8 -*-
# @Author : 一凡
import pymysql
# 打开数据库连接
db = pymysql.connect("localhost", "root", "111223", "study_date")
# 使用cursor()方法获取操作游标,以字典的方式获取数据,原数据类型为元组
cursor = db.cursor(cursor=pymysql.cursors.DictCursor)
# SQL 删除数据
del_sql = "delete from studys where id=3"
# 执行sql语句
cursor.execute(del_sql)
# 提交到数据库执行
db.commit()
# 关闭数据库连接
db.close()
update 语句可用来修改表中的数据
update 表名称 set 列名称=新值 where 更新条件;
update studys set age=25 where id=1
# -*- coding: utf-8 -*-
# @Author : 一凡
import pymysql
# 打开数据库连接
db = pymysql.connect("localhost", "root", "111223", "study_date")
# 使用cursor()方法获取操作游标,以字典的方式获取数据,原数据类型为元组
cursor = db.cursor(cursor=pymysql.cursors.DictCursor)
# SQL 修改数据
updata_sql = "update studys set age=30 where id=2"
# 执行sql语句
cursor.execute(updata_sql)
# 提交到数据库执行
db.commit()
# 关闭数据库连接
db.close()
语法:
fetchone()
例如要查询 students 表中所有学生的名字和年龄, 输入语句
select name, age from studys
fetchone()获取一行数据
# 导入模块
# -*- coding: utf-8 -*-
# @Author : 一凡
import pymysql
# 打开数据库连接 数据库地址
db = pymysql.connect("localhost", "root", "111223", "study_date")
# 使用cursor()方法获取操作游标,以字典的方式获取数据,原数据类型为元组
cursor = db.cursor(cursor=pymysql.cursors.DictCursor)
# 使用 execute()方法执行 SQL 查询
# 通配符,意思是查询表里所有内容
cursor.execute("select * from studys")
# 使用 fetchone() 方法获取一行数据.
data = cursor.fetchone()
print(data)
# 关闭数据库连接
db.close()
电商项目实战–判断主界面商品分类是否与数据库一致
第1步:获取界面分类数据
# -*- coding: utf-8 -*-
# @Author : 一凡
from selenium import webdriver
url = "http://localhost:8080/Shopping/index.jsp"
driver = webdriver.Chrome()
driver.get(url)
复数形式定位定位
els = driver.find_elements_by_xpath("/html/body/table[5]/tbody/tr/td[2]/table[1]/tbody/tr/td/a")
空列表用于存放数据
list = [ ]
for i in els:
# 获取text文本然后添加到列表
list.append(i.text)
print("界面数据:", list)
第2步:获取数据库商品分类数据
db = pymysql.connect(host="localhost", user="root", password="111223", database="db_shopping")
cur = db.cursor(cursor=pymysql.cursors.DictCursor)
# 从tb_bigtype数据库中选择bigName列表
sql = "select bigName from tb_bigtype"
cur.execute(sql)
db.commit()
cur.execute(sql)
data = cur.fetchall()
db_list = []
print("数据库数据:",data)
for i in data:
for j in i.values():
db_list.append(j)
print(db_list)
第3步:两组数据进行断言
第一种方法:
# 反向排序列表
list.reverse()
if db_list == list:
print("一致")
else:
print("不一致")
第二种方式断言:
断言>>集合>>求交集
if set(list) & set(db_list):
print("两者一致")
else:
print("不一致")
接口普遍有两种意思,一种是API(Application Program Interface),应用编程接口,它是一组定义、程序及协议的集合,通过API接口实现计算机软件之间的相互通信。而另外一种则是Interface,它是面向对象语言如java,c#等中一个规范,它可以实现多继承的功能。接口测试中的接口指的是API。
为什么要使用接口:
假如公司的产品前端开发还没开发完,接口开发好了。有天领导说,小王,你测下这个登录功能,要是你不懂接口的话就会对领导说这个功能测不了啊,页面没开发完。领导会把你!@¥@)¥!
接口测试是不需要看前端页面的,可以更早的介入到测试工作中,提高工作效率。
根据测试金字塔,越底层成本越低,一个底层的bug可能会引起上一层的多个bug,所以测试越底层,越能保证产品的质量,也越能节省测试的成本。而单元测试一般是由开发来完成的,所以对于测试来说,接口测试是非常必要的。
对于自动化测试来说,UI的变动性最大,所以UI自动化测试的维护成本很高。而接口的改动很小,所以接口自动化测试是最实用,最节约成本的。
接口功能自动化测试流程如下:
需求分析 -> 用例设计 -> 脚本开发 -> 测试执行 -> 结果分析
示例接口
手机号码归属地
接口地址:http://apis.juhe.cn/mobile/get
返回格式:json/xml
请求方式:get
请求示例:http://apis.juhe.cn/mobile/get?phone=手机号&key=您申请的KEY
需求分析是参考需求、设计等文档,在了解需求的基础上还需清楚内部的实现逻辑,并且可以在这一阶段提出需求、设计存在的不合理或遗漏之处。
如:手机号归属地接口,输入不同号码段的手机号,查看手机号归属和手机号码属于哪个运营商
5.1 模块安装
使用pip命令安装即可:pip install requests
5.2 接口调用
使用requests库,我们可以很方便的编写上述接口调用方法(如输入phone=手机号,示例代码如下):
在实际编写自动化测试脚本时,我们需要进行一些封装。
import unittest
import requests
import json
class Test_Moblie(unittest.TestCase):
# 封装公共的数据
def common(self, phone):
url = "http://apis.juhe.cn/mobile/get"
date = {
'key': "4391b7dd8213662798c3ac3da9f54ca8",
'phone': phone
}
self.response = requests.get(url, params=date)
return self.response
def test_1(self):
self.common("1857110")
print(self.response.text)
def test_2(self):
self.common("1868115")
print(self.response.text)
if __name__ == '__main__':
unittest.main()
我们按照测试用例设计,依次编写每个功能的自动化测试脚本即可。
5.3 结果校验
在手工测试接口的时候,我们需要通过接口返回的结果判断本次测试是否通过,自动化测试也是如此。
对于本次的接口,输入手机,我们需要判断返回的结果resultcode是不是等于200结果分页时需要校验返回的结果数是否正确等。完整结果校验代码如下:
# -*- coding: utf-8 -*-
# @Author : 一凡
import unittest
import requests
class Test_Moblie(unittest.TestCase):
# 封装公共的数据
def common(self, phone):
url = "http://apis.juhe.cn/mobile/get"
date = {
'key': "4391b7dd8213662798c3ac3da9f54ca8",
'phone': phone
}
self.response = requests.get(url, params=date)
return self.response
def test_2(self):
self.common("1868115")
print(self.response.json())
dict_2 = self.response.json()
# 打印值省份值为:200
resultcode = dict_2["resultcode"]
# 为演式错误的示例,将对比值改为200,正确值为200,可自行修改
self.assertEqual(resultcode, "200", msg='失败原因:%s != %s' % (resultcode, "200"))
if __name__ == '__main__':
unittest.main()
# -*- coding: utf-8 -*-
# @Author : 一凡
from unittest import TestSuite
from unittest import TestLoader
import requests
import json
import HTMLTestRunner
import unittest
class Test_Moblie(unittest.TestCase):
# 封装公共的数据
def common(self, phone):
url = "http://apis.juhe.cn/mobile/get"
date = {
'key': "4391b7dd8213662798c3ac3da9f54ca8",
'phone': phone
}
self.response = requests.get(url, params=date)
return self.response
def test_1(self):
"""判断状态码"""
self.common("1857110")
print(self.response.json())
# 返回数据为dict
print(type(self.response.json()))
dict_1 = self.response.json()
# 打印值省份值为:湖北
province = dict_1["result"]["province"]
self.assertEqual(province, "湖北", msg='失败原因:%s != %s' % (province, "湖北"))
def test_2(self):
"""判断省份"""
self.common("1868115")
print(self.response.json())
dict_2 = self.response.json()
# 打印值省份值为:湖北
resultcode = dict_2["resultcode"]
# 为演式错误的示例,将对比值改为201,正确值为200,可自行修改
self.assertEqual(resultcode, "201", msg='失败原因:%s != %s' % (resultcode, "200"))
if __name__ == '__main__':
report = "E:/report_path/result.html"
file = open(report,"wb")
# 创建测试套件
testsuit = unittest.TestSuite()
testload = unittest.TestLoader()
# 括号内传入的是类名,会自动找到以test开头全部的用例
# 用例以例表形式存储
case = testload.loadTestsFromTestCase(Test_Moblie)
testsuit.addTests(case)
run = HTMLTestRunner.HTMLTestRunner(stream=file,
title="接口自动化测试报告",
description="用例执行结果")
run.run(testsuit)
file.close()
5.5发送邮件报告
# -*- coding: utf-8 -*-
# @Author : 一凡
import zmail
def send_mail():
# 定义邮件
mail = {
"subject": "接口测试报告",# 任一填写
'content_text': '手机号归属地_API自动化测试报告',# 任一填写
# 多个附件使用列表
"attachments": "E:/report/result.html"
}
# 自定义服务器
# 如果不知道如何查看授权码,请查看这一篇博客:https://www.cnblogs.com/zzpython/p/13095749.html
server = zmail.server("发送人邮箱.com",
"QQ邮箱是用授权码",
smtp_host="smtp.qq.com",
smtp_port = 465)
# 发送邮件
server.send_mail("收件人QQ邮箱", mail)
try:
send_mail()
except FileNotFoundError:
print("未找到文件")
else:
print("发送成功")
其实关于编程这事儿没有接触的那么早,大一的时候没什么关注点,有一门课是vb,一天天的,就抄抄作业啥的就完事儿了。当时也觉的自己不是学编程的料,想着以后估摸也不会干开发相关的工作。
为什么是名师指路,因为确实需要老师来指点你的学习,关于这个老师,没有一个确切的点,父母可为师,同学也可以为师,甚至比自己年纪小、资历少的人也可以为师。
重要的是在我们迷茫的时候有一个人带来帮助和指点,所以我觉得,这一点是无比重要的,我们需要的是方向,而不是事事都给你解决掉的人,就好像是父亲,他会给你指明方向,会骂你,但是不管如何都不会替你做你应该做的事
其实这件事对于我来说是顺其自然的,由于我个人没有那么衰,相信在此的各位也都是积极向上的,爱上学习这件事是很容易的,尤其是最近疫情期间在家一直躺到想起床学习。
最重要的,是我们要正视学习和娱乐,我们所谓的放松不是打一把游戏就算了,要知道职业选手一天要打十几个小时的游戏,换成我们这些普通人同样也hold不住,所以学习同样是一种放松,正确的看待游戏和学习
在这里我觉得很有必要的是要有求知欲,这不是说我想有就能有的,这真的是要自己去探索,有一张图很好,贴在这里一下,做一个分享
大概自学的同学,都是看视频或着看博客来学的,总会感觉到讲师有多么的厉害,其实这最能体现的就是,把一个东西教给别人的时候,能学习到更多的东西,能够检查自己学习是否全面,是否掌握,这个时候,不仅他人能够受益,自己收获也会很大,要乐于把自己学会的东西分享出去,有了反馈之后一定会有不一样的感受
自学最大挑战,就是坚持不下去,所以,可以找同学一起学习,当然,也可以发帖找人一起打卡,每天分享心得,这样,有了反馈,有人一起,学习的效率就会更高,当然也就会更优秀。听过一句话,一个人可以走的很快,一群人会走的很远。找个伙伴可能会体会到不一样的感觉,奥利给!!!
其实学习这件事很容易,不局限于编程,学习是一件持久的事情,从始至终,有句话说得好,“知之者不如好之者,好之者不如乐之者”,我们要爱上学习。
作为一名软件测试工程师,我是很喜欢Python的,每当解决了工作中的问题,会觉的很高兴,帮助我实现了我想要的功能,大大提高了我的工作效率。
编写代码时的优雅是无与伦比的,我喜欢他那多样化的编写方式,深深地使我折服,那流畅的语言,是你与计算机独特的交流方式,和计算机共同构建着这独一无二的艺术品,外部功能的完善,内部代码的优雅,巧夺天工都不足以来形容。