Python语言程序设计

2021/05/30

基本算法

恺撒密码

是古罗马恺撒大帝用来对军事情报进行加解密的算法,它采用了替换方法对信息中的每一个英文字符循环替换为字母表序列中该字符后面的第三个字符,即,字母表的对应关系如下:‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‪‬

原文:A B C D E F G H I J K L M N O P Q R S T U V W X Y Z‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‪‬

密文:D E F G H I J K L M N O P Q R S T U V W X Y Z A B C‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‪‬

对于原文字符P,其密文字符C满足如下条件:C=(P+3) mod 26‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‪‬

上述是凯撒密码的加密方法,解密方法反之,即:P=(C-3) mod 26‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‪‬

假设用户可能使用的输入包含大小写字母a~zA~Z、空格和特殊符号,请编写一个程序,对输入字符串进行恺撒密码加密,直接输出结果,其中空格不用进行加密处理。使用input()获得输入。

tmp = input()
buff = ""
for i in tmp:
    if "a" <= i <= "z" :
        buff += chr(ord("a") + (ord(i)-ord("a") + 3) % 26)
    elif "A" <= i <= "Z" :
        buff += chr(ord("A") + (ord(i)-ord("A") + 3) % 26)
    else:
        buff += i
print(buff)

梅森旋转算法

待补充

科赫曲线的绘制

import turtle
def koch(size, n):
    if n == 0:
        turtle.fd(size)
    else:
        for angle in [0, 60, -120, 60]:
            turtle.left(angle)
            koch(size/3, n-1)

def main():
    level = 3
    koch(400, level)
    turtle.right(120)
    koch(400, level)
    turtle.right(120)
    koch(400, level)
    turtle.hideturtle()
    turtle.done()
main()

深度优先遍历(DFS)

实现一个方法,将JSON对象中所有为空字符串的字段去掉

def bianli(dict_value, tmp_return):
    for i in dict_value:
        dict_value[i]
        if dict_value[i] == '':  # 盘点值是否为空,是则不添加这个值
            pass
        else:
            try:
                dict_value[i].keys()
            except:
                tmp_return[i] = dict_value[i]
            else:  # 判断值是否为字典,是则遍历字典
                tmp_return[i] = {}
                bianli(dict_value[i], tmp_return[i])
    return tmp_return
oj = {'a': 1, 'tmp1': '', 'b': {"c": {'tmp2': '', 'd': 'stromg'}, 'tmp3': '', 'e': {}}}
print(bianli(oj, {})) # {'a': 1, 'b': {'c': {'d': 'stromg'}, 'e': {}}}

基本语法

import

  • import 库名
    • 调用函数: 库名.函数名(函数参数)
  • from 库名 import 函数:导入某个函数
    • from 库名 import * :导入所有函数
    • 调用函数: 函数名(函数参数)
  • import 库名 as 别名
    • 调用函数:库别名.函数名(函数参数)

return

def a():
    return 1, 2, 3
tmp = a()
print(tmp)  # (1, 2, 3)
print(type(tmp))   <class 'tuple'>

if

  • 二分之结构
    • <表达式1> if <条件> else <表达式2>
if '28F'[-1] in ['F', 'f']:
    print('{}里面包含了字母F或者字母f'.format('28F'))  # 28F里面包含了字母F或者字母f


if "a" <= "b" <= "z":
    print('{}大于等于a并且小于等于z'.format('b'))  # b大于等于a并且小于等于z

# 二分之结构
tmp = 1
print("猜{}了".format("对" if tmp==1 else "错"))  # 猜对了

赋值

tmp = 1 if 1 == 2 else 2
print(tmp)  # 2

a, b = 1, 2
print(a, b)  # 1 2

异常处理

try: # 可能发生异常的代码
    eval("abc")  
except NameError:  # 只捕捉特定类型的异常,非本类型异常则报错
    print("应该给一个数字类型的字符串")  # 应该给一个数字类型的字符串



try:
    <语句块1>  # 可能发生异常的代码
except:  # 捕捉全部异常
    <语句块2>  # 执行发生异常后执行
else:
    <语句块3>  # 程序没有发生异常情况下执行
finally:
    <语句块4>  # finally的语句一定会执行

循环

i = 10
while i>0:
    i -= 1
else:
   	print("正常结束")  
# 输出正常结束,因为没有遇到break语句,如果循环有else的情况,没有遇到break语句就会执行行else的语句块

i = 10
while i>0:
    i -= 1
    if i == 5:
        print("不正常退出")
        break
else:
   	print("正常结束")
# 不正常退出
    
    
for i in "test":
    print(i, end="")
else:
    print("正常结束")
# test正常结束
    
for i in "test":
    if "s" == i:
        break
        print("不正常正常结束")
    print(i, end="")
else:
    print("正常结束")
# te

变量

  • 局部变量是函数内定义的变量,全局变量是函数外定义的变量
  • 局部变量在函数销毁时同时销毁
  • 局部变量和全局变量重名时,使用的就是局部变量
  • 局部变量为组合数据类型且未创建,等同于全局变量
  • 使用global关键字可以在函数内调用全局变量
'''局部变量为组合数据类型且未创建,等同于全局变量'''
ls = ['f', 'F']
def func():
    ls.append(1)
func()
print(ls) #  ['f', 'F', 1]

'''局部变量和全局变量重名时,使用的就是局部变量'''
sa = 1
def func():
    sa = 2
func()
print(sa) #  1

'''使用`global`关键字可以在函数内调用全局变量'''
a = 'test'
def func():
    global a
    print(a)
func()

lambda

  • 匿名函数,用于可在一行内表达的简单函数
  • 函数名 = lambda 参数1, 参数2:表达式
func = lambda a, b: a+b
print(func(1, 2))  # 3 

语法糖

;

  • 特殊情况非要把代码写在一行的时候使用;来分隔
tmp = 1;print(tmp)

\

  • 代码写在一行的时候太长的时候可以使用\进行换行,换行后和写在一行的效果是一致的
print \
(1)  # 1

二元操作符

t = 1

t += 1
print(t)  # 2

t -= 1
print(t)  # 1

t *= 3
print(t)  # 3

t /= 4
print(t)  # 0.75

t **= 5
print(t)  # 0.2373046875

t %= 7
print(t)  # 0.2373046875

t //= 2
print(t)  # 0.0

切片

  • 左闭右开
tmp = "一二三四五六七八九十"
print(tmp[4])  # 五
print(tmp[3:])  # 四五六七八九十
print(tmp[:3])  # 一二三
print(tmp[:-3])  # 一二三四五六七
print(tmp[-3:])  # 八九十
print(tmp[2:3])  # 三
print(tmp[::2])  # 一三五七九
print(tmp[::-1])  # 十九八七六五四三二一

循环语法糖

a  = [i for i in range(10)] 
print(a)

基础函数

eval - 学习地址

  • 函数用来执行一个字符串表达式,并返回表达式的值。
  • 表达式就是字符串类型的Python语句,eval函数会把字符串类型的Python语句变成Python语句
eval("print('Hello World')") # Hello World

print

  • 接收值,然后打印到控制台
print('Hello World') # Hello World

# 打印结尾以逗号结尾
for i in ['1', '2', '3', '4']:
    print(i, end=",") # 1,2,3,4,
    
    
# 加入空格输出
print("Hello", "World") # Hello World

range

  • range(N) 产生0到N-1的整数序列,共N个
  • range(M,N)产生M到N-1的整数序列,共N-M个
  • range(N,M,S)产生N开头,到M-1结尾,步长为S的列表
for i in range(10):
    print(i, " ", end="")  # 0  1  2  3  4  5  6  7  8  9  
print()
for i in range(5, 10):
    print(i, " ", end="")  # 5  6  7  8  9  
for i in range(1, 6,2):
    print(i, ",", end="")  # 1 ,3 ,5 ,

map(function, iterable, ...)

第一个参数function以参数序列中的每一个元素调用function函数,返回包含每次function函数返回值的新列表

  • function – 函数
  • iterable - 一个或多个序列
tmp = ['1', '2', '3', '4']
print(sum(map(eval, tmp)))  # 10

数值类

hex(x)

  • 整数x的小写字符串的十六进制形式

oct(x)

  • 整数x的小写字符串的八进制形式

max(x1, x2, ..., xn)

  • 求最大值,n不限
print(max([1, 2, 3, 4, 5]))  # 5

print(max(1, 2, 3, 4, 5))  # 5

min(x1, x2, ..., xn)

  • 求最小值,n不限
print(max([1, 2, 3, 4, 5]))  # 1

print(max(1, 2, 3, 4, 5))  # 1

abs

  • 求绝对值
  • 参数1是需要求绝对值的数
print(abs(-1021))  # 1021

divmod(x,y)

  • 商余,(x//y, x%y)同时输出商和余数
tmp = divmod(2, 2)
print(tmp)  # (1, 0)
print(type(tmp))  # <class 'tuple'>

round

  • round(x, d):对x四舍五入,d是小数截取位数
  • 浮点数间运算及比较用round()函数辅助
  • 不确定位数一般发生到$10^{-16}$作用,round()十分有效
print(0.1+0.2 == 0.3) # False
print(round(0.1+0.2, 2) == 0.3) # True

Pow

  • 可正可负,没有取值范围
  • pow(x, y[,z])函数:计算$x^y$,想算多大算多大
# 求2的8次方是多大
print(pow(2, 8)) # 256

# 求2的8次方的结果除2余数是多少
print(pow(2, 8, 2))  #  0

字符串

encode('utf-8')

  • utf-8编码数据

decode('utf-8')

  • utf-8解码数据
st = '二狗子'.encode("utf-8")
print(st)
print(st.decode('utf-8'))

strip()

  • 去除两边指定字符,接收一个字符串,会去除两旁参数字符串中包含的字符,不指定字符串默认去除空白
# 去除空白
s = "    1    "
print(s.strip())  # 1

# 去除指定字符串
s = "222---1---222"
print(s.strip("-2"))  # 1

chr(u)

  • u为Unicode编码,返回其对应的字符
tmp = chr(98)
print(tmp)  # b
print(type(tmp))  # <class 'str'>

ord(x)

  • x为字符,返回其对应的Unicode编码
tmp = ord("陈")
print(tmp)  # 38472
print(type(tmp))  # <class 'int'>

lower()

  • 把字符串转换为小写
print('CBD'.lower())  # cbd

upper()

  • 把字符串大写
print('CBD'.upper())  # ABC

split(sep=None)

  • str根据sep被分隔的部分组成
tmp = "A,B,C,D,E".split(",")
print(tmp)  # ['A', 'B', 'C', 'D', 'E'] 
print(type(tmp))  # <class 'list'>

count(sub)

  • 返回字串substr中出现的次数
tmp = '我是你爸爸的爸爸,也就是爷爷'.count("爸爸")
print(tmp)  # 2
print(type(tmp))  # <class 'int'>

replace(old, new)

  • 返回字符串str副本,所有old子串被替换为new
tmp = '我是你爸爸的爸爸,也就是爷爷'.replace("爸爸", "老子")
print(tmp)  # 我是你老子的老子,也就是爷爷
print(type(tmp))  # <class 'str'>

center(width, [,fillchar])

  • 字串符str根据width居中,fillchar可选
print('test'.center(20, '='))
# ========test========

join(iter)

  • iter变量除最后元素外每个元素后增加一个str
print(",".join('test'))  # t,e,s,t

format - 学习地址

  • 格式化字符串的函数 str.format(),它增强了字符串格式化的功能

  • 基本语法是通过{}:来代替以前的%

  • format函数可以接收不限个参数,位置可以不按顺序

  • 槽内部对格式化的配置方式

    • <填充> <宽度> <对齐> <,> <.精度> <类型>
      引导符号 用于填充的单个字串 槽设定的
      输出宽度
      <左对齐
      >右对齐
      ^居中对其
      数字的
      千分位分隔符
      浮点数小数
      精度或字符串
      最大输出长度
      整数类型
      b,c,d,o,x,X
      浮点数类类型
      e,E,f,%
print("{} {}".format{"hello", "world"} # 不指定位置,按默认顺序)
# hello world

print("{0} {1}".format("hello", "world") # 设置置顶位置)
# hello world

print("{1} {0} {1}".format("hello", "world") # 设置指定位置)
# world hello world

print("名称:{name},年龄: {age}".format(name='张三', age=18))
# 名称:张三,年龄:18

site = {"name":"张三", "age": "18"}
print("名称:{name},年龄:{age}".format(**site))
# 名称:张三,年龄:18
      
my_list = ['张三', '18']
print("姓名:{0[0]}, 年龄:{0[1]}".format(my_list))
# 姓名:张三,年龄:18

print("姓名:{},余额:{:.3f}".format('陈新世', 3.14159)) # 保留三位小数,并且四舍五入
# 姓名:陈新世,余额:3.141
      
print("{:*^5}前面是槽".format(2))  # **2**前面是槽
      
print("{:,.3f}前面是槽".format(25631325156.65165156))  # 25,631,325,156.652前面是槽
      
print("{0:b},{0:c},{0:d},{0:o},{0:X}".format(100))  # 1100100
      

时间

time

  • 获取当前系统时间戳,浮点数
import time
tmp = time.time()
print(tmp)  # 1620555274.9285612
print(type(tmp))  # <class 'float'>

ctime(sec)

  • 格式化时间戳为可读时间形式字符串。sec未传入则以本地时间为准
import time
tmp = time.ctime()
print(tmp)  # Sun May  9 18:15:08 2021
print(type(tmp))  # <class 'str'>

gmtime

  • 获取一个时间对象
import time
tmp = time.gmtime()
print(tmp)  # time.struct_time(tm_year=2021, tm_mon=5, tm_mday=9, tm_hour=10, tm_min=17, tm_sec=17, tm_wday=6, tm_yday=129, tm_isdst=0)
print(type(tmp))  # <class 'time.struct_time'>

localtime(sec)

  • 格式化时间戳为时间对象。sec未传入则以本地时间为准
import time
ti = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(1621691486.8812747))
print(ti) # 2021-05-22 21:51:26
print(type(ti)) # <class 'str'>

perf_counter

  • 返回一个CPU级别的精确时间计数值,单位为秒
  • 由于这个计数值起点不确定,连续调用差值才有意义
import time
start = time.perf_counter()
print("1")  # 1
end = time.perf_counter()
print("程序打印用时{:.10f}".format(start - end))  # 程序打印用时-0.0000040000

时间格式

格式化字符串 日期/时间说明 值范围和实例
%Y 年份 0000~9999,例如:1900
%m 月份 01~12,例如:10
%B 月份名称 January-Decmber,例如:April
%b 月份名称缩写 Jan-Dec,例如:Apr
%d 日期 01~31,例如:25
%A 星期 Monday~Sunday,例如:Wednesday
%a 星期缩写 Mon~Sun,例如:Wed
%H 小时(24h制) 00~23,例如:12
%I 小时(12h制) 01~12,例如:7
%p 上/下午 AP,PM,例如:PM
%M 分钟 00~59,例如:26
%S 00~59,例如:26

strftime(tpl, ts)

  • tpl是格式化模板字符串,用来定义输出效果,ts是计算机内部时间类型变量
import time
tmp = time.strftime("%Y-%m-%d %H:%M:%S" , time.gmtime())
print(tmp)  # 2021-05-09 10:10:42
print(type(tmp))  # <class 'str'>

strpitime(str, tpl)

  • str是字符串形式的时间值
  • tpl是格式化模板字符串,用来定义输入效果
import time
tmp = time.strptime("2021-07-09 18:21:31", "%Y-%m-%d %H:%M:%S") 
print(tmp)  # time.struct_time(tm_year=2021, tm_mon=7, tm_mday=9, tm_hour=18, tm_min=21, tm_sec=31, tm_wday=4, tm_yday=190, tm_isdst=-1)
print(type(tmp))  # <class 'time.struct_time'>

sleep(s)

  • s是休眠的时间,单位是秒,可以是浮点数
import time
start = time.perf_counter()
time.sleep(1)
end = time.perf_counter()
print("程序打印用时{:.10f}".format(start - end))  # 程序打印用时-1.0118159000

随机数

seed(a=None)

  • 初始化给定的随机种子,默认为当前系统时间
import random as rd

rd.seed(10)  # 给定种子情况下,随机数是可以复现的
tmp = rd.random()
print(tmp)  # 0.5714025946899135
print(type(tmp))  # <class 'float'>

randome()

  • 生成一个[0.0, 1.0]之间的随机小数
import random as rd

tmp = rd.random()
print(tmp)  # 0.22985667275294253
print(type(tmp))  # <class 'float'>

randint(a, b)

  • 生成一个[a, b]之间的整数
import random as rd

tmp = rd.randint(1, 10)
print(tmp)  # 0.4
print(type(tmp))  # <class 'int'>

randrange(m, n[,k])

  • 生成一个[m, n ]之间以k为步长的随机整数
import random as rd

tmp = rd.randrange(1, 10, 3)
print(tmp)  # 0.4
print(type(tmp))  # <class 'int'>

getrandbits(k)

  • 生成一个k比特长的随机整数
import random as rd

tmp = rd.getrandbits(16)
print(tmp)  # 12592
print(type(tmp))  # <class 'int'>

uniform(a, b)

  • 生成一个[a, b]之间的随机整数
import random as rd

tmp = rd.uniform(10, 100)
print(tmp)  # 44.01421656979518
print(type(tmp))  # <class 'float'>

choice(seq)

  • 从序列seq中随机选择一个元素
import random as rd

tmp = rd.choice(["a", "b", 2, 4, 6])
print(tmp)  # 2
print(type(tmp))  # <class 'int'>

shuffle(seq)

  • 将序列seq中元素随机排列,返回打乱后的序列
import random as rd

tmp = [1, 2, 3, 4, 5, 6, 7, 8]; rd.shuffle(tmp)
print(tmp)  # [6, 3, 1, 2, 5, 4, 8, 7]
print(type(tmp))  # <class 'list'>

集合

S.add(x)

  • 如果x不在集合S中,将x增加到S
tmp = {1, 1, 1, 2, 3, 4}
tmp.add('a') 
print(tmp)  # {1, 2, 3, 4, 'a'}
print(type(tmp))  # <class 'set'>

S.discard(x)

  • 移除S中元素x,如果x不在集合S集合中,不报错
tmp = { 1, 2, 3, 4}
tmp.discard(5)
print(tmp)  # {1, 2, 3, 4}
print(type(tmp))  # <class 'set'>

S.remove(x)

  • 移除S中元素x,如果x不在集合S中,产生KeyError异常
tmp = { 1, 2, 3, 4}
tmp.remove(5)
print(tmp)
print(type(tmp))

'''
Traceback (most recent call last):
  File "E:/pythonDemo/jcstore-v2/Pytest.py", line 2, in <module>
    tmp.remove(5)
KeyError: 5
'''

S.clear()

  • 移除S中所有元素
tmp = { 1, 2, 3, 4}
tmp.clear()
print(tmp)  # set()
print(type(tmp))  # <class 'set'>

S.pop()

  • 随机返回S的一个元素,更新S,若S为空产生KeyError异常
tmp = { 1, 2, 3, 4}
tmp.pop()
print(tmp)  # {2, 3, 4}
print(type(tmp))  # <class 'set'>

S.copy()

  • 返回一个集合S的一个副本
tmp = { 1, 2, 3, 4}
test = tmp.copy()
print(test)  # {1, 2, 3, 4}
print(type(test))  # <class 'set'>

序列

len(s)

  • 返回序列s的长度
tmp = [1, 2, 3, 4, 5]
print(len(tmp)) # 5

min(s)

  • 返回序列s的最大元素,s的元素需要可比较
tmp = [1, 2, 3, 4, 5]
print(min(tmp)) # 1

max(s)

  • 返回序列s的最大元素,s的元素需要可比较
tmp = [1, 2, 3, 4, 5]
print(max(tmp)) # 5

s.index(x) 或 s.index(x, i, j)

  • 返回序列si开始到j位置中第一次出现元素x的位置,左闭右开
tmp = [1, 2, 3, 4, 5]
print(tmp.index(4)) # 3
print(tmp.index(2, 0, 4)) # 1

s.count(x)

  • 返回序列s中出现x的总次数
tmp = [1, 2, 3, 4, 5, 5]
print(tmp.count(5)) # 2

列表

ls[i = x]

  • 替换列表lsi元素为x
tmp = [1, 2, 3, 4, 5]
tmp[0] = "str"
print(tmp)  # ['str', 2, 3, 4, 5]
print(type(tmp))  # <class 'list'>

ls[i:j:k] = lt

  • 用列表lt替换ls切片后对应元素子列表
tmp = [1, 2, 3, 4, 5]
tmp[0: 2] = "str"
print(tmp)  # ['s', 't', 'r', 3, 4, 5]
print(type(tmp))  # <class 'list'>

del ls[i]

  • 删除列表ls中第i元素
tmp = [1, 2, 3, 4, 5]
del tmp[0]
print(tmp)  # [2, 3, 4, 5]
print(type(tmp))  # <class 'list'>

del ls[i: j: k]

  • 删除列表lsi到第jk为步长的元素
tmp = [1, 2, 3, 4, 5]
del tmp[0: 2]
print(tmp)  # [3, 4, 5]
print(type(tmp))  # <class 'list'>

ls += lt

  • 更新列表ls,将列表lt元素增加到列表ls
tmp = [1, 2, 3, 4, 5]
tmp_a = "abcdefg"
tmp += tmp_a
print(tmp)  # [1, 2, 3, 4, 5, 'a', 'b', 'c', 'd', 'e', 'f', 'g']
print(type(tmp))  # <class 'list'>

ls *= n

  • 更新列表ls, 其元素重复n
tmp = [1, 2, 3, 4, 5]
tmp *= 2
print(tmp)  # [1, 2, 3, 4, 5, 1, 2, 3, 4, 5]
print(type(tmp))  # <class 'list'>

ls.append(x)

  • 在列表ls中增加元素x
tmp = [1, 2, 3, 4, 5]
tmp.append('abcd')
print(tmp)  # [1, 2, 3, 4, 5, 'abcd']
print(type(tmp))  # <class 'list'>

ls.clear()

  • 删除列表ls中所有元素
tmp = [1, 2, 3, 4, 5]
tmp.clear()
print(tmp)  # []
print(type(tmp))  # <class 'list'>

ls.copy

  • 生成一个新列表,赋值ls中所有元素
tmp = [1, 2, 3, 4, 5]
tmp_a = tmp.copy()
print("tmp的信息:")
print(tmp)  # [1, 2, 3, 4, 5]
print(id(tmp))  # 1992890122816
print(type(tmp))  # <class 'list'>
print("tmp_a的信息:")
print(tmp_a)  # [1, 2, 3, 4, 5]
print(id(tmp_a))  # 1992891399680
print(type(tmp_a))  # <class 'list'>

ls.insert(i,x)

  • 在列表ls的第i位置增加元素x
tmp = [1, 2, 3, 4, 5]
tmp.insert(2, 'a')
print(tmp)  # [1, 2, 'a', 3, 4, 5]
print(type(tmp))  # <class 'list'>

ls.pop(i)

  • 在列表ls中第i位置元素去除并删除该元素
tmp = [1, 2, 3, 4, 5]
tmp.pop(3)
print(tmp)  # [1, 2, 3, 5]
print(type(tmp))  # <class 'list'>

ls.remove(x)

  • 在列表ls中出现的第一个元素x删除
tmp = [1, 2, 3, 4, 5]
tmp.remove(3)
print(tmp)  # [1, 2, 4, 5]
print(type(tmp))  # <class 'list'>

ls.reverse()

  • 将列表ls中的元素反转
tmp = [1, 2, 3, 4, 5]
tmp.reverse()
print(tmp)  # [5, 4, 3, 2, 1]
print(type(tmp))  # <class 'list'> 

sorted(ls)

  • 将列表ls排序
tmp = [3, 2, 1, 4]
tmp_b = sorted(tmp)
print(tmp_b)  # [1, 2, 3, 4]
print(type(tmp_b))  # <class 'list'>

ls.sort(cmp=None, key=None, reverse=False)

学习地址

对原列表进行排序

  • key – 传入一个方法,每次调用这个方法获取值比较
  • reverse – 排序规则,reverse = True 降序, reverse = False 升序(默认)。
def get_value(ls):
    return ls[1]
'''以二维列表中的第二个值进行排序比较'''
tmp = [[1, 2], [4, 5], [9, 1], [10, 4]]
# tmp.sort(key=lambda x:x[1], reverse=True)
tmp.sort(key=get_value, reverse=True)
print(tmp)  # [[4, 5], [10, 4], [1, 2], [9, 1]]
print(type(tmp))

字典

del d[k]

  • 删除字典d中键对应的数据值
tmp = {18: "张三", 25: "李四", 36: "王五"}
del tmp[18]
print(tmp)  # {25: '李四', 36: '王五'}
print(type(tmp))  # <class 'dict'>

k in d

  • 判断键k是否在字典d中,如果在返回True, 否则False
tmp = {18: "张三", 25: "李四", 36: "王五"}
tmp_a = 18 in tmp
print(tmp_a)  # True
print(type(tmp_a))  # <class 'bool'>

d.keys()

  • 返回字典d中所有的键信息
tmp = {18: "张三", 25: "李四", 36: "王五"}
tmp_a = tmp.keys()
print(tmp_a)  # dict_keys([18, 25, 36])
print(type(tmp_a))  # <class 'dict_keys'>

d.values()

  • 返回字典d中所有的值信息
tmp = {18: "张三", 25: "李四", 36: "王五"}
tmp_a = tmp.values()
print(tmp_a)  # dict_values(['张三', '李四', '王五'])
print(type(tmp_a))  # <class 'dict_values'>

d.items()

  • 返回字典d中所有的键值对信息
tmp = {18: "张三", 25: "李四", 36: "王五"}
tmp_a = tmp.items()
print(tmp_a)  # dict_items([(18, '张三'), (25, '李四'), (36, '王五')])
print(type(tmp_a))  # <class 'dict_items'>

d.get(k, <default>)

  • k存在,则返回相应值,不在则返回<default>
tmp = {18: "张三", 25: "李四", 36: "王五"}
tmp_a = tmp.get(28)
print(tmp_a)  # None
print(type(tmp_a))  # <class 'NoneType'>

d.pop(k, <default>)

  • k存在,则取出相应值,不在则返回<default>
tmp = {18: "张三", 25: "李四", 36: "王五"}
tmp_a = tmp.pop(18)
print(tmp_a)  # 张三
print(tmp)  # {25: '李四', 36: '王五'}
print(type(tmp))  # <class 'dict'>

d.popitem()

  • 随机从字典d中取出一个键值对,以元组形式返回
tmp = {18: "张三", 25: "李四", 36: "王五"}
tmp_a = tmp.popitem()
print(tmp_a)  # (36, '王五')
print(type(tmp_a))  # <class 'tuple'>
print(tmp)  # {18: '张三', 25: '李四'}
print(type(tmp))  # <class 'dict'>

d.clear()

tmp = {18: "张三", 25: "李四", 36: "王五"}
tmp.clear()
print(tmp)  # {}
print(type(tmp))  # <class 'dict'>

len(d)

  • 返回字典d中元素的个数
tmp = {18: "张三", 25: "李四", 36: "王五"}
tmp_a = len(tmp)
print(tmp_a)  # 3
print(type(tmp_a))  # <class 'int'>

os

os库提供通用的、基本的操作胸痛交互功能

os库是Python标准库,包含几百个函数

常用路径操作、进程管理、环境参数等几类问题

op.path

os.path子库以path为入口,用于操作和处理文件路径

os.path.abspath(path)

  • 返回path再当前系统中的绝对路径
import os.path as op
test = op.abspath('test.txt')
print(test)  # E:\pythonDemo\jcstore-v2\test.txt
print(type(test))  # <class 'str'>

os.path.normpath()

  • 归一化path的表示方式,统一用\\分隔路径
import os.path as op
test = op.normpath('E:\\pythonDemo\\jcstore-v2\\test.txt')
print(test)  # E:\pythonDemo\jcstore-v2\test.txt
print(type(test))  # <class 'str'>

os.path.relpath(path)

  • 返回当前程序与文件之间的相对路径(relative path)
import os.path as op
test = op.relpath('E:\\pythonDemo\\jcstore-v2\\test.txt')
print(test)  # test.txt
print(type(test))  # <class 'str'>

os.path.basename(path)

  • 返回path中的文件名称
import os.path as op
test = op.basename('E:\\pythonDemo\\jcstore-v2\\test.txt')
print(test)  # test.txt
print(type(test))  # <class 'str'>

os.path.dirname(path)

  • 返回path中的目录名称
import os.path as op
test = op.dirname('E:\\pythonDemo\\jcstore-v2\\test.txt')
print(test)  # E:\pythonDemo\jcstore-v2
print(type(test))  # <class 'str'>

os.path.join(path)

  • 组合pathpaths,返回一个路径字符串
import os.path as op
test = op.join('E:\\', 'pythonDemo\\jcstore-v2\\test.txt')
print(test)  # E:\pythonDemo\jcstore-v2\test.txt
print(type(test))  # <class 'str'>

os.path.exists(path)

  • 判断path对应文件或目录是否存在,返回TrueFalse
import os.path as op
test = op.exists('E:\\pythonDemo\\jcstore-v2\\test.txt')
print(test)  # True
print(type(test))  # <class 'bool'>

os.path.isfile(path)

  • 判断path对应是否为已存在的文件,返回TrueFalse
import os.path as op
test = op.isfile('E:\\pythonDemo\\jcstore-v2\\test.txt')
print(test)  # True
print(type(test))  # <class 'bool'>

os.path.isdir(path)

  • 判断path对应是否为已存在的目录,返回TrueFalse
import os.path as op
test = op.isdir('E:\\pythonDemo\\jcstore-v2\\test.txt')
print(test)  # False
print(type(test))  # <class 'bool'>

os.path.getatime(path)

  • 返回path对应文件或目录上一次的访问时间
import os.path as op
import time
test = op.getatime('E:\\pythonDemo\\jcstore-v2\\test.txt')
print(test)  # 1621691486.8812747
print(type(test))  # <class 'float'>  # <class 'float'>
print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(test)))  # 2021-05-22 21:51:26

os.path.getmtime(path)

  • 返回path对应文件或目录最近一次的修改时间
import os.path as op
import time
test = op.getmtime('E:\\pythonDemo\\jcstore-v2\\test.txt')
print(test)  # 1621691472.2872932
print(type(test))  # <class 'float'>  # <class 'float'>
print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(test)))  # 2021-05-22 21:51:12

os.path.getmtime(path)

  • 返回path对应文件或目录的创建时间
import os.path as op
import time
test = op.getctime('E:\\pythonDemo\\jcstore-v2\\test.txt')
print(test)  # 1621678251.9427152
print(type(test))  # <class 'float'>  # <class 'float'>
print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(test)))  # 2021-05-22 18:10:51

os.path.getsize(path)

  • 返回path对应文件的大小,以字节为单位
import os.path as op
test = op.getsize('E:\\pythonDemo\\jcstore-v2\\test.txt')
print(test)  # 246
print(type(test))  # <class 'int'>

系统操作

os.chdir()

  • 修改当前程序操作的路径
import os
os.chdir('E:\\pythonDemo')
test = os.getcwd()
print(test)  # E:\pythonDemo
print(type(test))  # <class 'str'>

os.getcwd()

  • 返回程序的当前路径
import os
test = os.getcwd()
print(test)  # E:\pythonDemo\jcstore-v2
print(type(test))  # <class 'str'>

os.getlogin()

  • 获得当前系统登录用户名称
import os
test = os.getlogin()
print(test)  # sorry_le
print(type(test))  # <class 'str'>

os.getlogin()

  • 获得当前系统登录用户名称
import os
test = os.getlogin()
print(test)  # sorry_le
print(type(test))  # <class 'str'>

os.cpu_count()

  • 获得当前系统的CPU数量
import os
test = os.cpu_count()
print(test)  # 12
print(type(test))  # <class 'int'>

os.path.cpu_count()

  • 获得当前系统的CPU数量
import os
test = os.unandom()
print(test)  # 12
print(type(test))  # <class 'int'>

os.path.urandom(n)

  • 获得n各字节长度的随机字符串,通常用于加解密运算
import os
test = os.urandom(10)
print(test)  # b'a\xdf(*\xc7Q\xdf\x9bE{'
print(type(test))  # <class 'bytes'>

文件

<变量名> = open(<文件名>, <打开模式>)

  • 变量名 - 是操作文件的句柄,不管是读写都用这个句柄进行操作
  • 文件名 - 是文件的路径, 例子:D:/PYE/f,txt 或者 D:\\PYE\\f.txt
  • 打开模式 - 文本 or 二进制,读 or 写
文件的打开模式 描述
‘r’ 只读模式,默认值,如果文件不存在,返回FIleNotFoundError
‘w’ 覆盖写模式,文件不存在则创建,存在则完全覆盖
‘x’ 创建写模式,文件不存在则创建,存在则返回FileExistsError
‘a’ 追加写模式,文件不存在则创建,存在则在文件最后追加内容
‘b’ 二进制文件模式
‘t’ 文本文件模式,默认值
‘+’ r/w/x/a一同使用,在原功能基础上增加同时读写功能

test.txt文件内容

中国是一个伟大的国家!
是的

<f>.read()

  • 读入全部内容,如果给出参数,则读取前size长度
tmp = open('./test.txt', 'r', encoding='UTF-8')
text = tmp.read(2)
print(text)  # 中国
print(type(text))  # <class 'str'>

<f>.readline()

  • 读入一行内容,如果给出参数,读入该行前size长度
tmp = open('./test.txt', 'r', encoding='UTF-8')
text = tmp.readline()
print(text)  # 中国 
print(type(text))  # <class 'str'>

<f>.readlines()

  • 读入文件所有行,以每行为元素形成列表
  • 如果给出参数,读入前hint行
tmp = open('./test.txt', 'r', encoding='UTF-8')
text = tmp.readlines()
print(text)  # ['中国是一个伟大的国家!\n', '是的\n', '赞同']
print(type(text))  # <class 'list'>

<f>.write(s)

  • 向文件写入一个字符串和字节流

<f>.writelines(lines)

  • 将一个元素全为字符串的列表写入文件
ls = ['\n', '中国', '美国', '法国']
tmp = open('./test.txt', 'r+', encoding='UTF-8')
tmp.writelines(ls)
print(tmp.readlines())  # ['中国是一个伟大的国家!\n', '是的\n', '赞同']
print(type(tmp))  # <class '_io.TextIOWrapper'>

<f>.seek(offset)

  • 改变当前文件操作指针的位置,offset含义如下:0 文件开头; 1 当前位置;2 文件结尾

socket

学习地址

Socket又称”套接字”,应用程序通常通过”套接字”向网络发出请求或者应答网络请求,使主机间或者一台计算机上的进程间可以通讯。

通用方法

socket.socket()

  • 创建套接字

bind((host, port))

  • 绑定地址host和端口port到套接字中,以元组(host, port)的形式表示地址

recv(bufsize)

  • 接收TCP数据,数据以字符串形式返回,bufsize指定要接收的最大数据量。

send(string)

  • 发送TCP数据,将string发送到连接的套接字。返回值时要发送的字节数量,该数量可能小于string的字节大小

sendall(string)

  • 完整发送 TCP 数据。将 string 中的数据发送到连接的套接字,但在返回之前会尝试发送所有数据。成功返回 None,失败则抛出异常。

recvfrom()

  • 接收 UDP 数据,与 recv() 类似,但返回值是(data,address)。其中 data 是包含接收数据的字符串,address 是发送数据的套接字地址。

sendto()

  • 发送 UDP 数据,将数据发送到套接字,address 是形式为(ipaddr,port)的元组,指定远程地址。返回值是发送的字节数。

settimeout(timeout)

  • 设置套接字操作的超时期,timeout是一个浮点数,单位是秒。值为None表示没有超时期。一般,超时期应该在刚创建套接字时设置,因为它们可能用于连接的操作(如connect()

setsockopt(level,optname,value) - 学习地址

  • 设置给定套接字选项的值。

setblocking(flag)

  • 如果flag为0,则将套接字设为非阻塞模式,否则将套接字设为阻塞模式(默认值)。非阻塞模式下,如果调用recv()没有发现任何数据,或send()调用无法立即发送数据,那么将引起socket.error异常。

s.close()

  • 关闭套接字

socket()

服务端方法

listen(number)

  • 开始TCP监听。number指定在拒绝连接之前,操作系统可以挂起的最大连接数量。该值至少为1,大部分应用层序设为5。

accept()

  • 被动接收TCP客户端连接,(阻塞式)等待连接的带来
import socket

se = socket.socket()  # # 创建套接字
se.bind(('localhost', 8083))  # 绑定ip地址和端口
se.listen(5)  # 监听,并且指定最大连接排队数
while 1:
    connection, addr = se.accept()  # 被动接收客户端连接
    try:
        data = connection.recv(2048)  # 获取连接传输的数据,最长2048字节
        print(data.decode('utf-8'))  # 以utf-8解码后打印
        connection.send('2.找我干嘛?'.encode('utf-8'))  # 数据以utf-8编码h后发送 
    except Exception as e:
        connection
    connection.close() # 关闭连接

    
'''
<socket.socket fd=1120, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 8083), raddr=('127.0.0.1', 9999)>            ('127.0.0.1', 9999)
1.喂!
2.找我干嘛?
'''

客户端方法

connect(address)

  • 主动初始化TCP服务器连接,。一般address的格式为元组(host,port),如果连接出错,返回socket.error错误。

connect_ex()

  • connect()函数的扩展版本,出错时返回出错码,而不是抛出异常

getsockopt(level,optname[.buflen])

  • 返回套接字选项的值。

gettimeout()

  • 返回当前超时期的值,单位是秒,如果没有设置超时期,则返回None。

fileno()

  • 返回套接字的文件描述符。
import  socket
# 创建一个socket
cl = socket.socket()
# 绑定端口,地址
cl.bind(('localhost', 9999))
# 连接至对端端口和地址
cl.connect(('localhost', 8083))

# 把数据以utf-8编码后发送,避免编码不同导致乱码
send_data = '1.喂!'
cl.send(send_data.encode('utf-8'))

# 接收数据以utf-8解码打印,避免编码不同导致乱码
data = cl.recv(2048)
print(data.decode('utf-8'))

# 关闭连接
cl.close()


'''
<socket.socket fd=1120, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 8083), raddr=('127.0.0.1', 9999)>            ('127.0.0.1', 9999)
1.喂!
2.找我干嘛?
'''

通用方法获取信息

getpeername()

  • 返回连接套接字的远程地址。返回值通常是元组(ipaddr,port)

getsockname()

  • 返回套接字自己的地址。通常是一个元组(ipaddr,port)

makefile()

  • 创建一个与该套接字相关连的文件

关键字

raise nolocal assert is
class with yield  
       
       

程序设计

IPO

  • 确定IPO:明确计算部分及功能边界
  • 编写程序:将计算求解的设计变成现实
  • 调试程序:确保程序按照正确逻辑能够正确运行

模块化设计的思想

分而治之

  • 通过函数或对象封装程序划分为模块及模块之间的表达
  • 具体包括:主程序、子程序和子程序间的关系
  • 分而治之:一种分而治之、分层抽象、体系化的设计思想

-紧耦合:两个部分之间交流很多,无法独立存在

-松耦合:两个部分之间交流较少,可以独立存在

模块内部紧耦合、模块之间松耦合

配置设计

  • 引擎+配置:程序执行和配置分离,将可选参数配置化
  • 将程序开发变成配置文件编写,扩展功能而不修改程序
  • 关键在于接口设计,清晰明了、灵活可扩展

分析方法

自顶向下(设计)

  • 将一个总问题表达为若干个小问题组成的形式
  • 使用同样方法进一步分解小问题
  • 直至,小问题可以用计算机简单明了的解决

自底向上(执行)

  • 分单元测试,逐步组装
  • 按照自顶向下相反的路径操作
  • 直至,系统各部分以组装的思路都经过测试和验证

思维特征

  • 逻辑思维:推理和演绎,数学为代表,若A->B B->C 则A->C
  • 实证思维:实验和验证,物理为代表,提出引力波假说<-大量实验证实

计算思维

设计和构造,计算机为代表,汉诺塔递归

  • 抽象和自动化
    • 抽象问题的计算过程,利用计算机自动化分解
    • 抽象时基于计算机的思维方式
  • 抽象问题的计算过程,利用计算机自动化求解
    • 计算思维基于计算机强大的算力及海量数据
    • 抽象计算过程,关注设计和构造,而非因果
    • 以计算机程序设计为实现的主要手段

应用开发

  • 产品定义:对应用需求充分理解和明确定义产品定义,而不仅时功能定义,要考虑商业模式
  • 系统架构:以系统方式思考产品的技术实现系统架构,关注数据流、模块化、体系架构
  • 设计与实现:结合架构完成关键设计及系统实现结合可扩展性、灵活性等进行设计优化
  • 用户体验:从用户角度思考应用效果,用户至上,体验优先,以用户为中心

用户体验

思维转变:实现功能 -> 关注体验

用户体验指产品建立的主观感受和认识

关心功能实现,更要关系用户体验,才能做好产品

编程只是啥都按,不是目的,程序最终为人类服务

  1. 进度展示
    • 如果程序需要计算时间,可能产生等待,请增加进度条 - 循环可能会消耗大量时间,需要增强交互
    • 如果程序有若干步骤,需要提示用户,请增加进度展示 - 提示用户下一步或还剩多少步
    • 如果程序可能存在大量次数的循环,请增加进度条 - 循环可能会消耗大量时间,需要增强交互
  2. 异常处理
    • 当获得用户输入,对合规性需要检查,需要异常处理
    • 当读写文件时,对结果进行判断,需要异常处理
    • 对进行输入输出时,对运算结果进行判断,需要异常处理
  3. 其他类方法
    • 打印输出:特定位置,输出程序运行的过程信息
    • 日志文件:对程序异常及用户使用进行定期记录
    • 帮助信息:给用户多种方式提供帮助信息

程序设计基础

程序设计基本方法

计算机是根据指令操作数据的设备

  • 功能性:对数据的操作,表现为数据计算、输入输出处理和结果存储等
  • 可编程性:根据一系列指令自动地、可预测地、准确地完成操作者的意图

计算机的发展参照摩尔定律,表现为指数方式

  • 计算机硬件所依赖的集成电路规模参照摩尔定律发展
  • 计算机运行速度因此也接近几何级数快速增长
  • 计算机所能高效支撑的各类运算功能不断丰富发展

摩尔定律Moore‘s Law

  • Intel公司创始人之一戈登·摩尔在1964年提出
  • 单位面积集成电路可容纳晶体管的数量约每两年翻一番
  • GPU/CPU、内存、硬盘、电子产品价格等都遵守摩尔定律

计算机的发展

  • 当今世界,唯一长达50 年有效且按照指数发展的技术领域
  • 计算机深刻改变人类社会,甚至可能改变人类本身
  • 可预见的未来30年,摩尔定律还将持续有效

程序设计是计算机可编程性的体现

  • 程序设计,亦称编程,深度应用计算机的主要手段
  • 程序设计已经成为当今社会需求量最大的职业技能之一
  • 很多岗位都将被计算机程序接管,程序设计将是生存技能

编程语言基础概念

源代码:采用某种编程语言编写的计算机程序,人类可读

例如: result = 2+3

目标代码:计算机课直接执行,人类不可读

例如:11010010 0011011

编译:将源代码一次性转换成目标代码的过程

image-20210823225630707

解释:将源代码逐条转换成目标代码同时逐条运行的过程

image-20210425204524006

静态语言:使用编译执行的编程语言C/C++、JAVA语言

  • 编译器一次性生成目标代码,优化更充分,程序运行速度更快

脚本语言:使用解释器执行的编程语言:Python、JavaScript、PHP

  • 执行程序过程时需要源代码,维护更灵活,源代码在维护灵活、跨多个操作系统平台

程序的基本编写方法

理解IPO

输入/Input:程序的输入,输入是程序开始

  • 文件输入、网络输入、控制台输入、交互界面输入、内部参数输入等

输出/Output:程序的输出,输出是程序展示运算结果的方式

  • 控制台输出、图形输出、文件输出、网络输出、操作系统内部变量输出等

处理/Process:处理时程序输入数据进行计算产生输出结果的过程

  • 处理方法统称为算法,它是程序最重要的不发

  • 算法是一个程序的灵魂

问题的计算部分:一个待解决问题中,可以用程序辅助完成的部分

  • 计算机只能计算问题,既问题的计算部分
  • 一个问题可能有多种角度理解,产生不同的计算部分
  • 问题的计算部分一般都有输入、处理和输出过程

编程解决问题的步骤

  1. 分析问题:分析问题的计算部分,想清楚
  2. 划分边界:划分问题的功能边界,规划IPO
  3. 设计算法:设计问题的求解算法,关注算法
  4. 编写程序:编写问题的计算程序,编程序
  5. 调试测试:调试程序使正确运行,运行调试
  6. 升级维护:适应问题的升级维护,更新完善

求解计算机问题的精简步骤

  • 确定IPO:明确计算部分及功能边界

  • 编写程序:将计算求解的设计编程现实

    • 调试程序:确保程序按照正确逻辑能够正确运行

Python的两种编程方式

IDLE练习Python语法

交互式和文件式

  • 交互式:对每个输入语句即时运行结果,适合语法练习
  • 文件式:批量执行一组语句并运行结果,编程的主要方式

实例

温度转换:温度刻画的两种不同体系

  • 摄氏度:中国等世界大多数国家使用
    • 以1标准大气压下水的结冰点为0度,沸点为100度,将温度进行等分刻画
  • 华氏度:美国、英国等国家使用
    • 以1标准大气压下水的结冰点为32位,沸点位212度,将温度进行等分刻画

需求分析:两种温度体系的转换

  • 摄氏度转换为华氏度
  • 华氏度转换为摄氏度

问题分析:该问题计算部分的理解和确定

  • 理解1:直接将温度值进行转换
  • 理解2:将温度信息发布的声音或图像形式进行理解和转换
  • 理解3:监控温度信息发布渠道,实时获取并转换温度值

采用理解1:直接将温度值进行转换

  • 温度数值需要标明温度体系,既摄氏度或华氏度
  • 转换后也需要给出温度体系

划分边界

  • 输入: 带华式或摄氏标志的温度值
  • 处理:根据温度标志选择适当的温度转换算法
  • 输出:带摄氏或华式标志的温度值

输入输出格式设计

  • 标识放在温度最后,F表示华式度,C表示摄氏度
  • 82F表示华式82度,28C表示摄氏28度

设计算法

根据华式和摄氏温度定义,利用转换公式如下:

TempStr = input("请输入带有符号的温度值:")
if TempStr[-1] in ['F', 'f']:
    C = (eval(TempStr[0:-1]) -32)/1.8
    print("转换后的温度是{:.2f}C".format(C))
elif TempStr[-1] in ['C', 'c']:
    F = 1.8 * eval(TempStr[0:-1]) + 32
    print("转换后的温度是{:.2f}F".format(F))
else:
    print("输入格式错误")

数据类型

整数数据类型

四种进制的表示形式

  • 十进制:1010,99,-23
  • 二进制,以0b0B或开头:0b010,-0b101
  • 八进制,以0o或0O开头:0o872,-0O123
  • 十六进制,以0x或0X开头:0x9a,-0X89

浮点数类型

浮点数的取值范围和小数进度都存在限制,但常规计算可忽略

取值范围数量级约-10^308 至$10^308$,精度数量级$10^{-16}$

浮点数间运算存在不确定尾数,浮点数在计算中以53位二进制表示,

0.1表示

二进制表示:0.00011001100110011001100110011001100110011001100110011010

十进制表示:0.100000000000000055511151231257827021181583404541015625

二进制表示小数可以无限接近,但不完全相同

**浮点数的运算需要使用round函数**

浮点数可以采用科学计数法表示

使用eE作为幂的符号,以10为技术,格式如下:aEb 表示:$a*10^b$

例如:4.3e-3值为0.0043 9.6E5值为960000.0

复数类型

与数学中复数的概念一致

如果$x^2= -1$,那么x的值是什么

  • 定义$j=\sqrt{(-1)}$,以此为基础,构建数学体系

  • $a+b_j$被称为复数,其中,a是实部,b是虚部

复数实例

$z=1.23e-4+5.6e+89j$

实部是什么?``z.real`获得实部($1.23e-4$)

虚部是什么?z.imag获得虚部($5.6e+89j$)

z=1.23e-4+5.6e+89j
print(z.real) # 0.000123
print(z.imag) # 5.6e+89

数值运算操作符

操作符及使用 描述
$x+y$ 加,x与y之和
$x-y$ 减,x与y之差
$x*y$ 乘,x与y之积
$x/y$ 除,x与y之商 $10/3$结果是3.33333333335
$x//y$ 整数除,x与y之整数商$10//3$结果是3
$+x$ x本身
$-y$ y的负值
$x \% y$ 余数,模运算 $10 \% 3$结果是1
$x ** y$ 幂运算,x是y次幂 分隔 ​ 当y是小数时,开方运算 10**0.5是$\sqrt{10}$

数字类型的关系

三种类型存在一种逐渐扩展变宽的关系:

整数 -> 浮点数 -> 复数

字符串

字符串的定义

print("字符串")  # 字符串
print('字符串')  # 字符串 
print('''字符串''')  # 字符串
print("""字符串""")  # 字符串

特殊字符串

\n- 换行

\r - 移至行首

序列

  • 序列的序号存在正向递增和反向递减
  • 序列类型通用操作符
tmp = [1, 2, 3, 4, 5]
# 正向递增序号
print(tmp[3]) # 4
# 反向递减序号
print(tmp[-3]) # 3
操作符及应用 描述
x in s 如果x是序列s的元素,返回True,否则返回False
x not in s 如果x是序列s的元素,返回False,否则返回True
s + t 连接两个序列s和t
s*n 或 n*s 将序列s复制n次
s[i] 索引,返回s中的第i个元素,i是序列的序号
s[i:j] 或 s[i:j:k] 切片,返回序列s中第ijk为步长的元素子序列
tmp = [1, 2, 3, 4, 5]
tmp_a = [1, 2, 3, 4]

print(tmp + tmp_a) # [1, 2, 3, 4, 5, 1, 2, 3, 4]

print(tmp * 2) # [1, 2, 3, 4, 5, 1, 2, 3, 4, 5]

print(tmp[-3])  # 3

print(tmp[1:3]) # [2, 3]

print(tmp[0:4:2]) # [1, 3]

list

  • 可以使用list[-1]获取倒数索引的值
# 遍历文件,打印每一行的数据
tmp = open("F:\\tmp\\test.txt")
for i in tmp:
    print(i.strip("\n"), end=",") # 1,2,3,4,5,6,7,8,9,10,

tuple

  • 元组数据类型,元组以,定义数据
tmp = 1, 2, 3, 4,
print(tmp)
print(type(tmp))

tmp = (1,)
print(tmp)
print(type(tmp))

tmp = (1) 
print(tmp) # 1
print(type(tmp)) # <class 'int'>

集合

  • 集合是多个元素的无须组合
  • 集合类型与数据的集合概念一致
  • 集合之间无须,每个元素唯一,不存在相同元素
  • 集合元素不可更改,不能是可变数据类型
tmp = {1, 1, 1, 2, 3, 4}
print(tmp)  # {1, 2, 3, 4}
print(type(tmp))  #  <class 'set'>


tmp = set()
print(tmp)  # set()
print(type(tmp))  # <class 'set'>
运算 操作符及应用 描述
S|T 返回一个新集合,包括在集合S和T中的所有元素
S-T 返回一个新集合,包括在集合S但不在T中的元素
S&T 返回一个新集合,包括同时在集合S和T中的元素
S^T 返回一个新集合,包括集合S和T中非相同元素
  S<=T 或 S<T 返回Ture/False,判断S和T的子集关系
  S>=T 或 S>T 返回True/False,判断S和T的包含关系

增强操作符

操作符及应用 描述
S|=T 更新集合S,包括在集合S和T中的所有元素
S-=T 更新集合S,包括在集合S但不在T中的元素
S&=T 更新集合S,包括同时在集合S和T中的元素
S^=T 更新集合S,包括集合S和T中的非相同元素
tmp = {1, 1, 1, 2, 3, 4}
print(tmp)  # {1, 2, 3, 4}
print(type(tmp))  # <class 'set'>

tms = {3, 'a'}

tmp -= tms
print(tmp)  # {1, 2, 4}
print(type(tmp))  # <class 'set'>

数据组织的维度

一维数据

由对等关系的有序或无序数据构成,采用线性方式组织

[3, 4, 5, 6]

对应列表、数组和集合等概念

二维数据

由多个一维数据构成,是一维数据到组合形式

一个列表的元素也是列表。

排名 总分
1 100分
2 49
3 45
4 1

高维数据

仅利用最基本的二元关系展示数据间的复杂结构

{
    'name': '二狗',
    'info':{
        'age': 18,
    	'sex': '男'
           }
}

第三方库

pip安装

安装Python的第三方库的主要方法

适合WInodws、Mac和Linux等操作系统

未来获取第三方库的方式,目前的主要方式

适合99%以上情况,需要联网安装

联网安装

  • pip -h - 查看帮助
  • pip install <第三方库名> - 安装指定的第三方库
  • pip install -U <第三方库名> - 使用更新已安装的指定第三方库
  • pip uninstall <第三方库名> -卸载指定的第三方库
  • pip download <第三方库名> - 下载但不安装指定的第三方库
  • pip search <关键字> - 根据关键词在名称和介绍中搜索第三方库

文件安装

  • 某些第三方库pip下载后,需要编译再安装
  • 访问 Python Extension Packages for Windows - Christoph Gohlke (uci.edu)
  • 下载需要安装的第三方库,执行pip install安装

  • 精确模式:把文本精确的切分开,不存在冗余单词
  • 全模式:把文本中所有看你的词语都扫描出来,有冗余
  • 搜索引擎模式:在精确模式基础上,对长词再次切分

jieba.lcut(s)

  • 精确模式,返回一个列表类型的分词结果

jieba.lcut(s, cut_all=True)

  • 全模式,返回一个列表类型的分词结果,存在冗余

jieba.lcut_for_search(s)

  • 搜索引擎模式,返回一个列表类型的分词结果,存在冗余

jieba.add_word(w)

  • 向分词词典增加新词w
import jieba
tmp = "中国是一个伟大的国家"
print(jieba.lcut(tmp)) # 精准模式
# ['中国', '是', '一个', '伟大', '的', '国家']
print(jieba.lcut(tmp, cut_all=True)) # 全模式
# ['中国', '国是', '一个', '伟大', '的', '国家']
print(jieba.lcut_for_search(tmp))  # 搜索引擎模式
# ['中国', '是', '一个', '伟大', '的', '国家']
jieba.add_word(tmp)
print(jieba.lcut(tmp))
# ['中国是一个伟大的国家']

wordcloud

  • wordcloud库把词云当作一个WordCloud对象
  • 可以根据文本词语出现的频率等参数绘制词云
  • 绘制词云的形状、尺寸和颜色都可以设定

w = wordcloud.WordCloud()

  • 创建一个词云对象

  • width - 宽度,默认400像素

  • height - 高度,默认200像素

  • min_font_size - 最小字号,默认4号

  • max_font_size - 最大字号,根据高度自动调节

  • font_step - 指定词云中字体字号的步进间隔,默认为1

  • font_path - 指定字体文件的路径,默认为None,字体文件为ttc文件

  • max_words - 指定词云显示的最大单词数量,默认200

  • stop_words - 排除词集合,既不显示的单词集合

  • background_color - 指定词云的背景颜色,默认为黑色

  • mask - 生成特定形状的词云图片

    • from scipy.misc import imread
      mask = imread('test.png') # test.png是一个白底的五角星图片
      wordcloud.WordCloud(mask=mask)
      

w.generate(txt)

  • WordCloud对象w中加载txt

w.to_file(filename)

  • 将词云输出为图像文件.png.jpg

pymysql

Python对Mysql数据的简单操作学习。

安装pymysql

使用pip安装pymysql,并且从清华大学源下载安装。

pip install -i https://pypi.tuna.tsinghua.edu.cn/simple/  pymysql 

创建连接

使用connect方法进行连接数据库

  • host:ip地址
  • port:端口
  • user:数据库账号
  • password:数据的密码
  • database:连接的库名 注:你对那个库进行增删改查就连接那个库
  • charset:字符集编码 注:选填,有些时候会因为字符集编码而出现问题, utf8没有-
import pymysql
# 连接mysql,返回一个连接对象
connection = pymysql.connect(host="127.0.0.1", port=3306, user="root",
                       password="root",database="databasename", charset="utf8")

# 获取连接对象的游标
cursor = connection.cursor()

释放资源

connection和cursor都有一个close方法释放资源,释放顺序为cursor、connection

import pymysql
# 连接mysql,返回一个连接对象
connection = pymysql.connect(host="127.0.0.1", port=3306, user="root",
                       password="root",database="databasename", charset="utf8")
cursor.close()
connection.close()

执行SQL语句的方法

所有的sql语句都用execute方法执行。

使用格式化参数可以预防SQL注入的安全问题;

注意事项:
  • 不管mysql中什么数据类型,在格式化的源语句中都用%s,不要用%d,%f之类的
  • 编写SQL时不要忘记带结束符;
  • execute:执行SQL的方法
    • query: 执行的SQL语句
      • 类型:str
    • args:格式化参数列表
      • 类型:list
import pymysql  # 导入 pymysql
# 打开数据库连接
connection = pymysql.connect(host="192.168.1.15", user="root",password="123456", db="jccloud", port=3306, charset='utf8')

# 使用cursor()方法获取操作游标
cursor = connection.cursor()
SQL = "SELECT *  FROM user WHERE name=%s AND age=%s"
cursor.execute(SQL, ['张三', 11])

查询的方法

执行查询时,会把查询到的所有记录存储在二维元组里并且返回。

查询多条记录时,指针的初始位置在第一位,如下表中,查询出时,指针指向id为1的数据

常用方法:

  • cursor.fetchall:获取所有数据,并且移动游标到最后一位
  • cursor.fetchone:移动游标到后一位并取出数据

  • cursor.scroll :移动游标
    • value:移动的偏移值。
    • mode:以什么模式移动
      • relative: 以当前位置为起点移动。
      • absolute: 以初始位置为起点移动。
  • cursor.fetchmany:移动偏移值位并取出数据
    • value: 移动的偏移值
    • int类型
ID user age
1 张三 11
2 李四 23

代码

import pymysql  # 导入 pymysql

# 打开数据库连接
connection = pymysql.connect(host="192.168.1.15", user="root",password="123456", db="jccloud", port=3306, charset='utf8')

# 使用cursor()方法获取操作游标
cursor = connection.cursor()
try:
    cursor.execute("select * from user;" )  # 执行sql语句
    results = cursor.fetchall()  # 获取查询的所有记录  results= ((1, '张三', '123456'), (2, '李四', '65431'))
    print("id", "name", "age")
    # 遍历结果
    for row in results:
        print(row[0], row[1], row[2])
except Exception as e:
    raise e
finally:
    cursor.close()  # 释放光标对象资源,免得内存泄漏
    connection.close()  # 释放连接的资源,免得内存泄漏

执行结果:

id name password
1 张三 123456
2 李四 654321

增删改方法

使用pymysql进行增删改的时候,会默认开启一个事务,所以操作时,务必要执行commit方法提交代码。

常用方法:

  • connection.commit:提交的方法,每次执行语句后都要使用该方法
  • connection.rollback:回滚事物的方法
  • cursor.lastrowid:获取插入记录的ID的方法

举例:增

删改两种操作也是一样的步骤

import pymysql  # 导入 pymysql

# 打开数据库连接
connection = pymysql.connect(host="192.168.1.15", user="root", password="123456", db="jccloud", port=3306, charset='utf8')

cursor = connection.cursor() # 使用cursor()方法获取操作游标

try:
    cursor.execute("INSERT INFO user(name,age) VALUES(%s,%s);", ['张三', 80]) # 执行SQL语句
    connection.commit()  # 提交事务
    print('刚刚插入记录的ID是:',cursor.lastrowid)  # 获取刚刚插入的数据的ID,并且打印
except Exception as e:
    connection.rollback()  # 有异常,回滚事务
finally:
    cursor.close()  # 释放光标对象资源,免得内存泄漏
    connection.close()  # 释放连接的资源,免得内存泄漏

执行结果

刚刚插入记录的ID是: 3

计算生态

从数据处理到人工智能

数据分析

Numpy:表达N维数组的最基础库 - 学习地址

  • Python接口使用,C语言实现,计算速度优异
  • Python数据分析及科学计算的基础库,支撑Pandas
  • 提供直接的矩阵运算、广播函数、线性代数功能

Pandas:Python数据分析高层次应用库 - 学习地址

  • 提供了简单易用的数据结构和数据分析工具
  • 理解数据类型和索引的关系,操作索引既操作数据
  • Python最主要的数据分析功能库,基于Numpy开发

SciPy:数学、科学和工程计算功能库 - 学习地址

  • 提供了一批数学算法及工程运算的功能
  • 类似Matlab,可用于如博里叶变换、信号处理等应用
  • Python最主要的科学计算功能库,基于Numpy开发

数据可视化

Matplotlib:高质量的二维数据可视化功能库 - 学习地址

  • 提供了超过100种数据可视化展示效果
  • 通过matplotlib.pyplot子库调用各可视化效果
  • Python最主要的数据可视化功能库,基于Numpy开发

Seaborn: 统计类数据可视化功能库 - 学习地址

  • 提供了一批高层次的统计类数据可视化展示效果
  • 主要展示数据间分布、分类和线性关系等内容
  • 基于Matplotlib开发,支持NumpyPandas

Mayavi:三维科学数据可视化功能库 - 学习地址

  • 提供了一批简单易用的3D科学计算数据可视化展示效果
  • 目前版本是Mayavi2,三维可视化最主要的第三方库
  • 支持NumpyTVTKTraitsEnvisage等第三方库

文本处理

PyPDF2:用来处理pdf文件的工具集 - 学习地址

  • 提供了一批处理PDF文件的计算功能
  • 支持获取信息、分隔/整合文件、加密解密等
  • 完全Python语言实现,不需要额外依赖,功能稳定

NLTK:自然语言文本处理第三方库 - 学习地址

  • 提供了一批简单易用的自然语言文本处理功能
  • 持语言文本分类、标记、语法句法、语义分析等
  • 最优秀的Python自然语言处理库

Python-docx:创建或更新Microsoft Word文件的第三方库 - 学习地址

  • 提供创建或更新.doc .docx等文件的计算功能
  • 增加并配置段落、图片、表格、文字等,功能全面

机器学习

Scikit-learn:机器学习方法工具集 - 学习地址

  • 提供一批统一化的机器学习方法功能接口
  • 提供聚类、分类、回归、强化学习等计算功能
  • 机器学习最基本且最优秀的Python第三方库

TensorFlow:AlphaGo背后的机器学习计算框架 - 学习地址

  • 谷歌公司推动的开源机器学习框架
  • 将数据流图作为基础,图节点代表运算,边代表张量
  • 应用机器学习方法的一种方式,支撑谷歌人工智能应用

MXNet:基于神经网络的深度学习计算框架 - 学习地址

  • 提供可扩展的神经网络及深度学习计算功能
  • 可用于自动驾驶、机器翻译、语音识别等众多领域
  • Python最重要的深度学习计算框架

从Web解析到网络空间

网络爬虫

Requests:最友好的网络爬虫功能库 - 学习地址

  • 提供了简单易用的类HTTP协议网络爬虫功能
  • 支持连接池、SSLCookiesHTTP(S)代理等
  • Python最主要的页面级网络爬虫功能库

Scrapy: 优秀的网络爬虫框架 - 学习地址

  • 提供了构建网络爬虫系统的框架功能,功能半成品
  • 支持批量和定时网页爬取、提供数据处理流程等
  • Python最主要且最专业的网络爬虫框架

pyspider: 强大的Web页面爬取系统 - 学习地址

  • 提供了完整的网页爬取系统构建功能
  • 支持数据库后端、消息队列、优先级、分布式架构等
  • Python重要的网络爬虫类第三方库

Web信息提取

Beautiful Soup: HTML和XML的解析库 - 学习地址

  • 提供了解析HTMLXMLWeb信息的功能
  • 又名beautifulsoup4bs4,可以加载多种解析引擎
  • 常与网络爬虫库搭配使用,如Scrapyrequests

Re: 正则表达式解析和处理功能库 - 学习地址

  • 提供了定义和解析正则表达式的一批通用功能
  • 可用于各类场景,包括定点的Web信息提取
  • Python最主要的标准库之一,无需安装

Python-Goose: 提取文章类型Web页面的功能库 - 学习地址

  • 提供了对Web页面中文章信息/视频等元数据的提取功能
  • 针对特定类型Web页面,应用覆盖面较广
  • Python最主要的Web信息提取库

Web网站开发

Django: 最流行的Web应用框架 - 学习地址

  • 提供了构建Web系统的基本应用框架
  • MTV模式:模型(model)、模板(Template)、视图(Views)
  • Python最重要的Web应用框架,略微复杂的应用框架

Pyramid: 规模适中的Web应用框架 - 学习地址

  • 提供了简单方便构建Web系统的应用框架

  • 不大不小,规模适中,适合快速构建并适度扩展类应用

  • Python产品级Web应用框架,起步简单可扩展性好

Flask: Web应用开发微框架 - 学习地址

  • 提供了最简单构建Web系统的应用框架
  • 特点是:简单、规模小、快速
  • Django > Pyramid > Flask

网络应用开发

WeRoBot: 微信公众号开发框架 - 学习地址

  • 提供了解析微信服务器消息及反馈消息的功能
  • 建立微信机器人的重要技术手段

aip: 百度AI开放平台接口 - 学习地址

  • 提供了访问百度AI服务的Python功能接口
  • 语音、人脸、OCRNLP、知识图谱、图像搜索等领域
  • Python百度AI应用的最主要方式

MyQR: 二维码生成第三方库 - 学习地址

  • 提供了生成二维码的系列功能
  • 基本二维码、艺术二维码和动态二维码

从人机交互到艺术设计

图形用户界面

PyQt5: Qt开发框架的Python接口 - 学习地址

  • 提供了创建Qt5程序的Python API接口
  • Qt是非常成熟的跨平台桌面应用开发系统,完备GUI
  • 推荐的Python GUI开发第三方库

wxPython: 跨平台GUI开发框架 - 学习地址

  • 提供了专用于Python的跨平台GUI开发框架
  • 理解数据类型与索引的关系,操作索引即操作数据
  • Python最主要的数据分析功能库,基于Numpy开发

PyGObject: 使用GTK+开发GUI的功能库 - 学习地址

  • 提供了整合GTK+WebKitGTK+等库的功能
  • GTK+:跨平台的一种用户图形界面GUI框架
  • 实例:Anaconda采用该库构建GUI

游戏开发

PyGame: 简单的游戏开发功能库 - 学习地址

  • 提供了基于SDL的简单游戏开发功能及实现引擎
  • 理解游戏对外部输入的响应机制及角色构建和交互机制
  • Python游戏入门最主要的第三方库

Panda3D: 开源、跨平台的3D渲染和游戏开发库 - 学习地址

  • 一个3D游戏引擎,提供PythonC++两种接口
  • 支持很多先进特性:法线贴图、光泽贴图、卡通渲染等
  • 由迪士尼和卡尼基梅隆大学共同开发

cocos2d: 构建2D游戏和图形界面交互式应用的框架 - 学习地址

  • 提供了基于OpenGL的游戏开发图形渲染功能
  • 支持GPU加速,采用树形结构分层管理游戏对象类型
  • 适用于2D专业级游戏开发

虚拟现实

VR Zero: 在树莓派上开发VR应用的Python库 - 学习地址

  • 提供大量与VR开发相关的功能
  • 针对树莓派的VR开发库,支持设备小型化,配置简单化
  • 非常适合初学者实践VR开发及应用

pyovr: Oculus RiftPython开发接口 - 学习地址

  • 针对Oculus VR设备的Python开发库
  • 基于成熟的VR设备,提供全套文档,工业级应用设备
  • Python+虚拟现实领域探索的一种思路

Vizard: 基于Python的通用VR开发引擎 - 学习地址

  • 专业的企业级虚拟现实开发引擎
  • 提供详细的官方文档
  • 支持多种主流的VR硬件设备,具有一定通用

图形艺术

Quads: 迭代的艺术 - 学习地址

  • 对图片进行四分迭代,形成像素风
  • 可以生成动图或静图图像 - 简单易用,具有很高展示度

ascii_art: ASCII艺术库 - 学习地址

  • 普通图片转为ASCII艺术风格
  • 输出可以是纯文本或彩色文本 - 可采用图片格式输出

turtle - 学习地址

  • 很流行的绘制图像的函数库
  • 在一个横轴为x、纵轴为y的坐标系原点,(0,0)位置开始,它根据一组函数指令的控制,在这个平面坐标系中移动
# 绘制同切园
import turtle
turtle.pensize(2) # 设置画笔宽度
turtle.circle(10) # 画圆,半径为正(负),表示圆心在画笔的左边(右边)画圆
turtle.circle(40)
turtle.circle(80)
turtle.circle(160)

# 绘制一个五角星
from turtle import *
color('red', 'red') # 设置画笔颜色为red, 填充颜色为red
begin_fill() # 准备开始填充图形
for i in range(5):
    fd(200) # 填充
    rt(144) # 顺时针移动
end_fill()

turtle

turtle(海龟)库是turtle绘图体系的Python实现

-turtle绘图体系:1969年诞生,主要用于程序设计入门

Python语言的标准库之一

入门级的图形绘制函数库

turtle.setup

  • 作用:生成一个窗口 or 设置宽度高度
    • 参数1是整数的宽
    • 参数2是整数的高
    • 参数3是整数的起始x轴位置
    • 参数4是整数的起始y轴位置

绝对坐标:以画布中间的坐标为锚点,围绕着这个锚点定的坐标

海龟坐标:以海龟为锚点,海龟前后左右就是相应的前后左右。海龟被创建出来后,头是默认向左。绝对坐标函数无法改变朝向

turtle.goto

  • 以绝对坐标移动进行移动
    • 参数1是整数的x轴
    • 参数2是整数的y轴

turtle.bk

  • 让海龟后退运行
    • 参数1是整数的长度

turtle.fd

  • 让海龟前进
    • 参数1是整数的长度

turtle.circle

  • 以海龟当前位置左侧的一个点为圆心曲线运行
    • 参数1是整数的圆心
    • 参数2是整数的长度

image-20210509100254905

turtle.seth

  • 以角度坐标来,改变海龟的方向
    • 参数1是整数的度数

turtle.left

  • 海龟向左旋转角度
    • 参数1是整数的度数

turtle.right

  • 海龟向右旋转角度
    • 参数1是整数的度数

turtle.penup

  • 抬起画笔,画笔不在画布上画画,但是可以移动

turtle.pendown

  • 放下画笔,画笔在抬起后放回画布上画画

turtle.pensize

  • 设置画笔宽度
    • 别名函数:turtle.witdh
    • 参数1是宽度

turtle.colormod

  • 修改RGB色彩模式
    • 参数1接收1.0则变为RGB小数值模式,接收255则接收RGB证书值模式

turtle.pencolor

  • 设置画笔颜色
    • 参数1
      • 小写字符串的颜色英文
    • 参数1,参数2, 参数3:三个小数参数的RGB小数值
      • 元组类型的RGB整数值

turtle.done

  • 程序不自动退出,需要手动关闭窗口

turtle.write(str, font=("Arial",16, normal))

  • 画出str
import turtle
turtle.write('test', font=("Arial",16 normal))
import turtle

# 作用:生成一个宽800,高800,起始点在屏幕最左上方的画
turtle.setup(800, 800, 0, 0) 

# 向上移动100
turtle.goto(0, 100)

# 向左转头90度
turtle.left(90)

# 向右转头180度
turtle.right(180)

# 向角度坐标转头90度
turtle.seth(90)

# 设置画笔粗细
turtle.pensize(10)

# 设置画笔颜色为棕色
turtle.pencolor("purple")

# 设置画笔颜色为红色
turtle.pencolor(1, 0, 0)

# 向后移动100
turtle.bk(100)

# 抬起画笔
turtle.penup()

# 向前移动100
turtle.fd(100)

# 放下画笔
turtle.pendown()


# 以左侧的100为圆心移动100
turtle.circle(100, 100)

# 以右侧的100为圆心移动100
turtle.circle(-100, 100)

python目录结构

  • Pycharm可以指定文件夹的类型,
    • 选中文件夹右键 - Mark Directory as - 选择类型
      • Soures Root :源代码文件
      • Resoure Root: 资源文件
      • Excluded: 删除的文件
      • Template Folder:模板文件
  • 项目根目录
    • resource - 资源目录
    • sources - 源代码目录

Python自带函数

__init__()   实例化这个类的时候,这个函数会自动执行

__call__()   使类能够想函数一样背调用,同时不影响实例本身的生命周期(__call__()不影响一个实例的构造)。
网址:https://www.cnblogs.com/yeer-xuan/p/13497494.html

__globals__  以字典的形式返回当前类的全局变量,包含类名、文件地址、等


示例代码:
class a():·

    def __init__(self):
        print("这是init函数")

    def __call__(self):
        print('这是call函数')

    def print_a(self):
        print("这是普通的函数")

test = a()
test()
test.print_a()

打印结果:
这是init函数
这是call函数
这是普通的函数

命名

  • 包名 - 应小写英文单词,以下划线进行分割
    • 例子:test_packge
  • 模块名 - 应小写英文单词,以下划线进行分割
    • 例子:test_module
  • 类名 - 大驼峰式
    • 例子:TestClass
  • 方法名 - 小写英文单词,以下划线进行分割
    • 例子:test_function
  • 类的变量 - 大写英文单词
    • 例子:TEST_CLASS_ATTRIBUTES
  • 方法变量
    • 例子:test_function_attributes
  • 不希望访问的属性或方法命名,前面加一个下划线
    • 例子:_test_attributes
    • 例子:_test_function
  • 不希望被子类重写、调用的属性和方法,前面加两个下划线(私有方法)
    • 例子:__test_attributes
    • 例子:__test_function
  • python自身调用的方法
    • 它只是python调用的hook
    • 例子:__xx__

对象

  • 父类继承子类时,子类重写类父类调用的方法,父类会直接调用子类的方法

    • 例子:

    • class teas:
          # 父类实际想调用的方法
          def test_function(self):
              print("SUPER_FUNCTION")
          	
          # 父类调用了子类重写的方法
          def testa(self):
              self.test_function()
          
      class test(teas):
          # 父类实际调用了子类的方法
          def test_function(self):
              print("SON_FUNCTION")
          
      test().testa()
      
    • 结果

    • SON_FUNCTION
      
    • 避免方法:把test_function变为私有方法,父类的test_funcion名前面加两个下划线

多线程编程

学习地址:https://www.runoob.com/python/python-multithreading.html
  • _thread模块
  • 这是个快被废弃的模块
  • start_new_thread()
    • function
      • 传入一个方法,不要加括号,加入括号是调用方法
    • args[, kwargs]
      • 传递给线程函数的参数,他必须是个tuple类型。请看上面数据类型的元组类型数据类型
      • kwargs - 可选参数。
import _thread
# 定义一个方法
def a(param):
	print(param)
    
# 创建一个子线程运行该方法
_thread.start_new_thread(a, ("test",))

lambda表达式

  • 可定义匿名函数,作用是让代码更好阅读

  • 可以有参数也可以无参数

  • 有参数形式:

    • x = lambda x:x +1
      
  • 无参数形式:

    • lambda: print("test")
      

with关键字

  • 使用with关键字可以,在发生异常的的时候自动关闭资源

  • 下面是自己定义的类,使用with关键字执行,他会帮我自动关闭资源,他会自动调用__exit__方法

  • 它会帮你调用exit方法进行资源释放,exit方法如果是自己写的类需要你自己实现。

  • 发生异常的情况也会帮你释放
  • 可以当作匿名函数使用
class Test(object):
    def __init__(self, name):
        self.name = name

    def __enter__(self):
        print("进入enter")
        return self

    def do_self(self):
        print(self.name)

    def __exit__(self, exc_type, exc_value, traceback):
        print("退出exit")
        print(exc_type, exc_value)


if __name__ == '__main__':
    print("这是with关键字调用的")
    with Test('test') as mc:
        mc.do_self()

print("\n\n这是自己调用的")
Test('test').do_self()
这是with关键字调用的
进入enter
test
退出exit
None None


这是自己调用的
test

生成器

学习地址:https://www.liaoxuefeng.com/wiki/897692888725344/923029685138624
  • 一边循环一边计算的机制,称为生成器(Generator)
  • 循环的过程中不断推算出后续的元素,不必创建完整的list,从而节省大量的空间
  • 只有一些算法代码,用来得出该算法可得出的所有对象

yield关键字

  • 该关键字可以把函数变成可迭代的对象,相当于生成器

  • yield可以把函数分段执行,每段共享函数的资源如:变量等,

  • yield可以返回值,每次执行完一段如果有需要返回值就可以使用yield执行,也可以没有返回值,默认返回None

  • 把使用该关键字修饰的代码若要连续执行可用迭代器来执行,如下方语法糖中的for循环语法糖就是一个迭代器

  • 实例代码:

  • def a():
        c = 1
        print("这是第一次执行next时候,执行后会自动把指针指向这个yield到下一个yield之间")
        d = yield c
        print("现在打印的是d变量的值:", d, "因为之前yield关键字把c的值返回了,所以它现在是None")
        yield
      
    
  • 执行方法

  • s = a()
    print(type(s))
    print(next(s))
    print(next(s))
    
  • s = a()
    print(type(s))
    for i in s:
        print(i)
    
  • 执行结果

  • <class 'generator'>
    这是第一次执行next时候,执行后会自动把指针指向这个yield到下一个yield之间
    1
    现在打印的是d变量的值: None 因为之前yield关键字把c的值返回了,所以它现在是None
    None
    

语法糖

学习网址:https://www.zhihu.com/search?type=content&q=for%20i%20in%E8%AF%AD%E6%B3%95%E7%B3%96%E5%AE%9E%E7%8E%B0

赋值骚操作:

使用判断进行赋值

  • 实例代码

  • a = 0
      
    a = 1 if False else 2
    print("a:", a)
    
  • 运行结果

  • a: 2
    

for循环语法糖

学习网址:https://www.zhihu.com/question/24868112/answer/29257569
  • 语法糖代码

    • #  该语法糖对可迭代对象进行迭代
      tmp = [1, 2, 3]
      for _ in tmp:
          pass
      
  • 实现语法糖代码

    • tmp = [1, 2, 3]
      while True:
          try:
              _ = next(tmp)
          except StopIteration:
              break
      
  • 原理

    • 每个可迭代对象都实现了next方法,可用next取到当前对象,把指针前进到下一结果
    • 如:例子中的tmp对象就可以取到3个对象,执行三次next方法
    • 在第三次的时候会导致报错因为没有指针没有办法把指针前进到下一结果,就会抛出个异常,这时候接收到后进行跳出取元素的操作就行了。
  • 列表推导式

    • 实例代码

    • tuple_a = (i for i in range(3))
      for i in tuple_a:
          print("tuple_a:", i)
      
    • 运行结果

    • tuple_a: 0
      tuple_a: 1
      tuple_a: 2
      

**kwargs

  • 描述:这是python的不定长参数,表示该方法接收多个参数,并且接收后以字典形式存储,可使用迭代器遍历取出

  • 普通使用

    • def test(ds, **kwargs):
          # items方法返回键和值
          for i in kwargs.items():
              print(i)
          
          
      test("a", test1="one", test2="two")
      
    • 输出

    • ('test1', 'one')
      ('test2', 'two')
      
  • 当该语法糖与默认参数相遇时

    • def test(ds, test1="test", test2="two"):
          print("test1", test1)
          print("test2", test2)
          
          
      params_dict = {"test1": "我是语法糖自动取到的test1数据", "test2": "我是语法糖自动取到的test2数据"}
      # 这个地方的*号是重点,如果入参是字典,并且前面带了两个**,python就会自动获取
      test("a", **params_dict)
      
    • 输出:

    • test1 我是语法糖自动取到的test1数据
      test2 我是语法糖自动取到的test2数据
      

Python方法的参数

对象可以作为参数
函数可以作为参数
方法可以作为参数
数值可以作为参数

可变参数
*arg 这代表有多个参数,以列表形式存储
**kargs 这代表有多个参数,以字典形式存储

若要使用的不用加前面的*

使用可变参数的字典形式接收参数

1603036796350

接收字典形式的参数后,直接取出,不用写循环来取出

1603036781219

Python安装

whl文件安装
使用pip install 文件      pip命令安装
如果报amd64.whl is not a supported wheel on this platform错
可能是版本不对
解决方法:
去编辑器执行下列代码,打印的信息就是对应版本  然后找对应版本的whl包安装  
import pip._internal
print(pip._internal.pep425tags.get_suppported())

可能是名称问题,改一下名字 比如:
cx_Oracle-7.3.0-cp38-cp38-win_amd64.wh改成:cx_Oracle-7.3.0-cp38m-cp38-win_amd64.wh

Python命令行运行

cmd运行Python程序:
在环境变量中添加一个名为:PYTHONPATH的变量
然后把项目根目录添加进该变量,然后退出终端再次运行就可以了
如果有多个项目就用;分隔


解释网址:https://blog.csdn.net/qq_35304570/article/details/78151545
解释:Python搜索模块的路径:
(1)、程序的主目录
(2)、PTYHONPATH目录(如果已经进行了设置)
(3)、标准连接库目录(一般在/usr/local/lib/python3.X/)
(4)、任何的.pth文件的内容(如果存在的话).新功能,允许用户把有效果的目录添加到模块搜索路径中去.pth后缀的文本文件中一行一行的地列出目录。(有需要的话也会在Lib\site-packages目录下建一个.pth的文件)
这四个组建组合起来就变成了sys.path了

Python正则表达式

# 使用正则表达式需要导入一个包 re包

# 正则匹配的方法
findall('正则表达式',需要正则匹配的值)  返回值:列表  

# 正则表达式
        
1.匹配指定字符 
# toall等单词中只会取出to  小技巧:可以在两旁加空格 to 。  
findall('to',text)		# 匹配到text中 所有to
        
2.匹配任意字符 
# 在正则中.代表任意单个字符包括空格,特殊符号,等例子:ta,tb,tc 在这段中下面的代码会取到ta tb tc放入列表中 
findall('t.',text)  # 匹配到text中,前面是t 后面是任意一个字符的  两个字符    
    
3.匹配限定字符
# 在正则中,[a-z] 是限定单字符只能匹配到a~z 之中的字符,,包括a和z 如:a,b,c,d,e,f 等
findall('t[a~z]c',text) 	# 匹配到text,前面是t 中间是a~z任意一个字母 c在后面的 三个字符     
        
4.括号
# toall等单词中只会取出to  小技巧:可以在两旁加空格 to 。  
findall(' (to) ',text)		# 返回一个列表 只返回to,不返回两旁的空格 
    
5.花括号
{n}
n 是一个非负整数。匹配确定的 n 次。例如,'o{2}' 不能匹配 "Bob" 中的 'o',但是能匹配 "food" 中的两个 o。        
str = "fsaf fsfasd dfsa"
re.findall("f(.w{2})",str)

{n,}
n 是一个非负整数。至少匹配n 次。例如,'o{2,}' 不能匹配 "Bob" 中的 'o',但能匹配 "foooood" 中的所有 o。'o{1,}' 等价于 'o+'。'o{0,}' 则等价于 'o*'。

{n,m}
m 和 n 均为非负整数,其中n <= m。最少匹配 n 次且最多匹配 m 次。例如,"o{1,3}" 将匹配 "fooooood" 中的前三个 o。'o{0,1}' 等价于 'o?'。请注意在逗号和两个数之间不能有空格。

6.?
匹配前面的子表达式零次或一次。例如,"do(es)?" 可以匹配 "do" 或 "does" 。? 等价于 {0,1}。

当该字符紧跟在任何一个其他限制符 (*, +, ?, {n}, {n,}, {n,m}) 后面时,匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串。例如,对于字符串 "oooo",'o+?' 将匹配单个 "o",而 'o+' 将匹配所有 'o'。

7.+
匹配前面的子表达式一次或多次。例如,'zo+' 能匹配 "zo" 以及 "zoo",但不能匹配 "z"。+ 等价于 {1,}。

8.*
匹配前面的子表达式零次或多次。例如,zo* 能匹配 "z" 以及 "zoo"。* 等价于{0,}。

9.\d
匹配一个数字字符。等价于 [0-9]。

10.\w
匹配字母、数字、下划线。等价于'[A-Za-z0-9_]'。
import re

处理字符串的方法

  • format

    • 可以用来格式化字符串

      • ad = {"a": "b", "b": "a"}
        ads = "str{a}".format(**ad)
        ads = "111{a}".format(**ad)
        print(ads)
        
      • 输出

      • 111b
        
    • 若是需要输出的参数为可迭代对象的情况

      • print("网站名:{name}, 地址 {url}".format(name="菜鸟教程", url="www.runoob.com"))
              
        # 通过字典设置参数
        site = {"name": "菜鸟教程", "url": "www.runoob.com"}
        print("网站名:{name}, 地址 {url}".format(**site))
               
        # 通过列表索引设置参数
        my_list = ['菜鸟教程', 'www.runoob.com']
        print("网站名:{0[0]}, 地址 {0[1]}".format(my_list))  # "0" 是必须的
        
      • 输出结果

      • 网站名:菜鸟教程, 地址 www.runoob.com
        网站名:菜鸟教程, 地址 www.runoob.com
        网站名:菜鸟教程, 地址 www.runoob.com
        
str = ”da das“
str.replace("da","das",2)   替换da为das  替换次数为2次 ,int型第三个数字选传 不传就全部替换


格式化输出%(s,d,f)
	%s 格式化字符串
	%d 格式化整数
	%f 格式化浮点数字,可指定小数点后的精度 %.0.2f表示小数点后只显示两位
	%% 带%的字符串是格式化的字符串,如果要输出%这个字符,就要用两个%%来输出
	
	string = '我叫%s,身高:%d,存款余额:%f',"sorry",181,2.51'
	print(string % ('sorry',181,2.51)) #我叫sorry,身高:181,存款余额:2.510000

# 格式化字符串
str = "我是一个%s,而且我很%s"
# 定义一个元组
tuple = ("猪", "肥")
# 对字符串格式化 使用元组
str = str % tuple
# 打印字符串
print(str) # 我是一个猪,并且我很肥

分割字符串
str.split(str="", num=string.count(str)).
str -- 分隔符,默认为所有的空字符,包括空格、换行(\n)、制表符(\t)等。
num -- 分割次数。默认为 -1, 即分隔所有。

装饰器

教程地址:https://www.bilibili.com/video/BV11s411V7Dt?t=579
教学地址:https://www.zhihu.com/question/26930016/answer/1047233982
好处:可以不改动代码,实现比较额外的
弊端:不修改原本代码,只是对代码外层增加一层作用

下列中装饰器名,wrapper返回是类本身,可以查询到类变量,类路径等地址

下方中*args中第一个值就是类本身

inspect.getcallargs(func[, *args][, **kwds]):将args和kwds参数到绑定到为func的参数名,作为func函数形参的值;
该方法可以以字典形式返回方法对应参数名及其值;



模板
def 装饰器名(func):
	def wrapper(*args):
        # 执行被装饰方法之前执行的代码

        # 被装饰的方法
        result = func()

        # 被装饰的方法之后执行的代码
		return result
	return wrapper


例1:  无返回无入参
def 装饰器名(func):
    def wrapper():
		# 执行被装饰方法之前执行的代码
		t1= time.time()
		# 被装饰的方法,要在哪里执行被装饰的方法写func()
		 func()
		# 被装饰的方法之后执行的代码
		t2 = time.time()
		# 打印被装饰方法的开始时间-结束时间=总共耗时(精确到小数点4位)
		print("Total time:{:.4} s".format(t2-1))
	return wrapper

例2: 有返回值,无入参
def 装饰器名(func):
    def wrapper():
		# 执行被装饰方法之前执行的代码
		t1= time.time()
		# 被装饰的方法,要在哪里执行被装饰的方法写func(),因为被装饰的方法有返回值,才会被赋值给变量返回
		result = func()
		# 被装饰的方法之后执行的代码
		t2 = time.time()
		# 打印被装饰方法的开始时间-结束时间=总共耗时(精确到小数点4位)
		print("Total time:{:.4} s".format(t2-1))
		# 返回被装饰的方法的返回值
		retrun result
		# 固定写法
	return wrapper


例3:
def 装饰器名(func):
	def wrapper(*args): # 如果没有参数可以不填*args  *args表示有多少参数接收多少参数
		# 执行被装饰方法之前执行的代码
		t1= time.time()
		# 被装饰的方法,要在哪里执行被装饰的方法写func(),因为被装饰的方法有返回值,才会被赋值给变量返回
		result = func(*args)
		# 被装饰的方法之后执行的代码
		t2 = time.time()
		# 打印被装饰方法的开始时间-结束时间=总共耗时(精确到小数点4位)
		print("Total time:{:.4} s".format(t2-1))
		# 返回被装饰的方法的返回值
		return result
	# 固定写法
	return wrapper


例4:
from functools import wraps
class Decorator:
    """装饰器类"""
    # 定义一个带参数的装饰器
    @classmethod
    def ThrowException(cls, messge):
        """被该方法装饰的类,如果报错,就会提示messge
        Args:messge (str):如果该方法报错,应该提示什么
        Returns:
        """
        def decorator(func):
            @wraps(func)
            def wrapper(*args, **kargs):
                try:
                    return func(*args, **kargs)
                except Exception as e:
                    raise Exception("%s%s" % (messge, "步骤发生错误")) from e;
            return wrapper
        return decorator



实例:def display_time(func):
	def wrapper(*args):
		t1= time.time()
		result = func()
		t2 = time.time()
		print("Total time:{:.4} s".format(t2-1))
		return result
	return wrapper
	
	

各种运算符

算数运算符

先乘除后加减
同级运算符是从左至右计算
可以使用()调整计算的优先级

** 优先级最高
* / % // 优先级次高
+ - 优先级最低

// 取整除 返回触发的正数部分(商) 9//2 输出结果4
%  取余数 返回触发的余数9%2=1
** 幂    又称次方、乘方  2**3 =8


isinstance(参数1, 数据类型)  # 判断数据类型的
在python中 None,  False, 空字符串"", 0, 空列表[], 空字典{}, 空元组()都相当于False

is 用于判断两个变量引用对象是否为同一个
== 用于判断引用变量的值是否相等
is not 用于判断两个变量是否引用自不同的对象
!= 用于判断引用变量的值是否不等
not False 取反
not in 判断元素是否在列表或者字典中 if a not in b
运算的时候可以加(),括号括起来的先计算

数学运算中
True是1
False是0
 
字符串*正数可以得到重复的字符串 
print("狼" * 5)  # 狼狼狼狼狼 
判断数据类型函数  
arg=123
# 判断数据类型是否是int
isinstance(arg, int)    # 输出True
# 判断数据类型是否是字符串
isinstance(arg, str)    # 输出False
# 判断数据类型是否包含tuple或者列表
isinstance(arg, (tuple, list))    # 输出False

运算的时候可以加(),括号括起来的先计算

Python的继承

https://blog.csdn.net/qq_38889350/article/details/105844870

循环用函数

enumerate() # for循环中如果需要打印当前循环次数(下标)就可以用,从0开始
# 例子
list_int = [1, 2, 3]
for i, line in enumerate(list_int):
    print(i, line)
# 运行结果
# 0 1
# 1 2
# 2 3    

# zip() 从多个不同列表依次取出元素合成元组
list1 = (1, 2, 3)
list2 = [9, 8, 7]
list3 = ['a', 'b', 'c']

for (a, b, c) in zip(list1, list2, list3):
    print(a, b, c)
# 运行结果
# 1 9 a
# 2 8 b
# 3 7 c

MySQL

通用方法

在构造器中定义MySQL连接对象的时候try时不要finally不要关闭连接,否则函数如果不可以调用,并且报错
pymysql.err.InterfaceError: (0, '') 

Pymysql如果不能查询建立连接后的插入的数据

# 连接MySQL数据库的包
import pymysql

# 进行连接,返回一个对象   host是数据库所在的ip地址   port是端口  user是用户名   password是密码  database是你需要连接哪个数据   charset指定字符集
conn = pymysql.connect(host="192.168.1.21", port=3306, user="root", password="root", database="jccloud", charset="utf8")

# 这个方法返回一个指针对象,当你需要进行操作时就需要调用这个对象
cursor = conn.cursor()

sql = "INSERT INTO USER1(name, age) VALUES (%s, %s);"
# 执行SQL语句的方法  使用第二个值可以预防SQL注入 不管什么类型的值都可以传,但是都写作%s,不要写%d,%f等
# str类型的sql语句   如果是增删改就需要commit 如果只是查就不用
cursor.execute(sql, ["值1","值2"])  # 返回一个int型的数据 改变了多少行

# 批量执行SQL语句的方法  使用第二个值可以预防SQL注入
#str类型的sql语句   如果是增删改就需要commit 如果只是查就不用
cursor.executemany(sql, [("值1", "值2"), ("值1", "值2")])  # 返回一个int型的数据 改变了多少行

# 提交的方法,如果是增删改的sql语句就需要写这个
conn.commit()

# 回滚的方法
conn.rollback()

# 释放资源的方法
conn.close()
cursor.close()


注意事项
传值的类型要和数据库中的字段的类型匹配

# 默认情况下指针指着第一位
# 光标按照相对位置(当前位置)移动1
cursor.scroll(1, mode="relative")

# 光标按绝对位scroll(1, mode="absolute")置移动1
cursor.scroll(1, mode="absolute")

# 取一条数据  适合查询单条数据时使用
cursor.fetchone()  # 获取当前指针指向的位置,返回元组  获取数据后把指针向后移动一位

# 取多条
# 不传值情况下等同fetchone()方法  传值则取指定数量的数据
# 获取从指针开始的三条数据,返回二维元组  获取数据后把指针向后移动到第三条数据之后一位
cursor.fetchmany(3)  

# 获取所有数据
cursor.fetchall()  # 获取查询的所有记录  二维元组 并且在把指针移到最后一行
#查询操作

import pymysql  #导入 pymysql  
  
#打开数据库连接  
db= pymysql.connect(host="localhost",user="root",  
    password="123456",db="test",port=3307)  
  
# 使用cursor()方法获取操作游标  
cur = db.cursor()  
  
#1.查询操作  
# 编写sql 查询语句  user 对应我的表名  
sql = "select * from user"  
try:  
    cur.execute(sql)    #执行sql语句  
  
    results = cur.fetchall()    #获取查询的所有记录  
    print("id","name","password")  
    #遍历结果  
    for row in results :  
        id = row[0]  
        name = row[1]  
        password = row[2]  
        print(id,name,password)  
except Exception as e:  
    raise e  
finally:  
    db.close()  #关闭连接

# 获取插入的数据id的方法  光标对象获取
cursor.lastrowid
# 导入连接mysql的包
import pymysql
# 进行连接,返回一个对象   host是数据库所在的ip地址   port是端口  user是用户名   password是密码  database是你需要连接哪个数据   charset指定字符集
conn = pymysql.connect(
    host="192.168.1.21", 
    port=3306, user="root", 
    password="root", 
    database="jccloud", 
    charset="utf8")
# 这个方法返回一个光标对象,当你需要进行操作时就需要调用这个对象
cursor = conn.cursor()
name = "名称"
age = "年龄"
SQL = "INSERT INFO USER1(name,age) VALUES(%s,%s);"
try:
	# 调用指针对象的execute方法执行sql语句 插入一条数据
    cursor.execute(sql, [username, age])
    # 提交事务
    conn.commit()
    # 提交之后,获取刚插入的数据的ID
    last_id = cursor.lastrowid
except Exception as e:
    # 有异常,回滚事务
    conn.rollback()
# 释放光标对象资源,免得内存泄漏
cursor.close()
# 释放连接的资源,免得内存泄漏
conn.close()

# 导入pymysql模块
import pymysql
# 连接database
conn = pymysql.connect(host=“你的数据库地址”, user=“用户名”,password=“密码”,database=“数据库名”,charset=utf8)
# 得到一个可以执行SQL语句的光标对象
cursor = conn.cursor()
sql = "DELETE FROM USER1 WHERE id=%s;"
try:
    cursor.execute(sql, [4])
    # 提交事务
    conn.commit()
except Exception as e:
    # 有异常,回滚事务
    conn.rollback()
cursor.close()
conn.close()

# 导入pymysql模块
import pymysql
# 连接database
conn = pymysql.connect(host=“你的数据库地址”, user=“用户名”,password=“密码”,database=“数据库名”,charset=utf8)
# 得到一个可以执行SQL语句的光标对象
cursor = conn.cursor()
# 修改数据的SQL语句
sql = "UPDATE USER1 SET age=%s WHERE name=%s;"
username = "Alex"
age = 80
try:
    # 执行SQL语句
    cursor.execute(sql, [age, username])
    # 提交事务
    conn.commit()
except Exception as e:
    # 有异常,回滚事务
    conn.rollback()
cursor.close()
conn.close()

sphinx

Pycharme:
Pycharme设置:
出处:https://www.zhihu.com/question/44780888/answer/934159625
1.Pycharme开启设置输入三个单引号可以生成注释
去File | Settings | Tools | Python Integrated Tools | Docstring format 这里改成你想要的格式,然后再回去看看你的三个引号。默认的可能是plain也就是空的

出处:https://blog.csdn.net/dkjkls/article/details/88933950
2.Pycharme开启输入三个单引号,生成注释带类型占位符
Pycharme中在Settings中搜索“Insert type placeholders in the documentation comment stub”然后勾选搜索到选项

自动生成注释的方法在def()下输入三个单引号或者双引号,然后点击回车

Pycharme主页点击Tools》Sphix Quickstart可以实现生成Python文档



所处路径为生成的source文件上一级目录中
命令:sphinx-quickstart  生成一个文档目录结构

# 生成获取项目的模块所在的类的rst(只需一次),执行时根据rst文件获取注释
命令: sphinx-apidoc -o ./source 项目根目录/  
如:sphinx-apidoc -o ./sourceE:\pythonDemo\Test\ 

命令:make html  生成文档,若已存在不做改变 需要用make clean命令清除才能生成新文档

命令:make clean 清除生成的html文档
根据注释生成文档的类库
参考地址:https://www.cnblogs.com/-wenli/p/12290545.html
参考地址:https://blog.csdn.net/sinat_29957455/article/details/83657029
使用步骤:
1.新建一个X文件夹,打开cmd窗口,cd到X文件夹 (专门用来存放生成的文档目录)
2.cmd执行sphinx-quickstart,然后在选项中选择根据1.0.1的选择
3.在生成的文件夹source中找到config.py,加入1.0.2的代码
4.在X文件夹的根目录(有make.bat文件),执行cmd命令:sphinx-apidoc -o ./source 项目根目录/ 
(生成rst文件)
5.然后执行make html生成注释文档 ,生成的文档在..\build\html\index.html中
安装主题:pip install -i https://pypi.tuna.tsinghua.edu.cn/simple/  sphinx_rtd_theme
config文件中导入:
import sphinx_rtd_theme

# 将 html_theme = "alabaster"改成如下,在加上html_theme_path
html_theme = "sphinx_rtd_theme"
html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]

# 然后在执行一次make html就变好看了

1.0.1

Welcome to the Sphinx 3.1.1 quickstart utility.

Please enter values for the following settings (just press Enter to
accept a default value, if one is given in brackets).

Selected root path: .

You have two options for placing the build directory for Sphinx output.
Either, you use a directory "_build" within the root path, or you separate
"source" and "build" directories within the root path.
> Separate source and build directories (y/n) [n]: y

The project name will occur in several places in the built documentation.
> Project name: Doc
> Author name(s): Doc
> Project release []: 1.0

If the documents are to be written in a language other than English,
you can select a language here by its language code. Sphinx will then
translate text that it generates into that language.

For a list of supported codes, see
https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-language.
> Project language [en]: zh_cn

1.0.2

import os
import sys
sys.path.insert(0, os.path.abspath('项目的根目录'))

#原本已经有的,替换成这个
extensions = ['sphinx.ext.autodoc',
    'sphinx.ext.doctest',
    'sphinx.ext.intersphinx',
    'sphinx.ext.todo',
    'sphinx.ext.coverage',
    'sphinx.ext.mathjax',
    'sphinx.ext.napoleon']
"""提供两种方法,二选一即可"""
class Test():
    """测试类"""

    def test01(self,name,password):
        """测试方法

        Args:
            name (str): 用户名
            password (str): 密码

        Returns:
            str: 用户
        """
        return ""
        
    def numpy_style(arg1, arg2):
        """函数功能.

        函数功能说明.

        Parameters
        ----------
        arg1 : int
            arg1的参数说明
        arg2 : str
            arg2的参数说明

        Returns
        -------
        bool
            返回值说明

        """
        return True

Excel

# 操作文件模块openpyxl
# Excel文件进行操作


# 打开一个已有的Excel表格
workbook = load_workbook(filename='表格文件路径')    

# 通过sheet名称获取表格
sheet = workbook['sheet名称']

# 打开唯一的一张sheet
sheet = workbook.activce  

# 获取A1格子
call = sheet['A1']

# 通过行数列数获取格子
sheet.cell(row=行数,column=列数)

# 获取一系列的格子
cells = sheet['A1:A5'] 
	"""参数列表
	# 'A1:A5' 返回A1到A5五个格子元素
	# 'A'     返回A列所有有数据的格子
    # 'A:C'   返回A列到C列所有有数据的格子
    # 5       返回第五行的所有有数据的格子
    # 5:6	  返回第五行到第六行所有有数据的格子
	"""
# 按行获取一系列格子   指定行和列的范围,按行获取 入参全为int型
sheet.iter.rows(
	min_row=最小的行数, 
	max_row=最高行数, 
	min_col=最低列数,
    max_col=最高列数)
    
# 按行获取一系列格子   指定行和列的范围,按列获取 入参全为int型
sheet.colr.(
	min_row=最小的行数, 
	max_row=最高行数, 
	min_col=最低列数,
    max_col=最高列数)  

# 获取所有行
sheet.rows


# 获取格子的数据
cell.value

# 获取格子的行数
cell.row

# 获取格子的列数
cell.columu

# 获取格子的坐标
cell.coordinate

# 获取表格文件内的sheet名称
workbook.sheetnames   

# 获取表格的尺寸大小
sheet.dimensions

```python dkjkcjjl
# 保存Excel表格 所有操作都要到最后都要保存这一步
workbook.save(filename=’表格路径全名称’)
# 往cell中写入值
cell.value = ‘值’

在Excel表格已有数据后面插入数据

# (不会覆盖之前新建的数据,假设A行有数据,就会在B1,B2和C1,C2中插入二狗,1和三狗,2)
sheet.append(
[
[‘二狗’,1]
[‘三狗’,2]
]
)

插入公式

sheetp[‘A1’] = ‘AVERAGE(F2:F1001)’

查看支持的公式

from openpyxl.utils import FORMULAE
print(FORMULAE)

插入列 ,在idx列的左边插入一列 不指定amount参数则只插入一列

sheet.insert_cols(idx=第几列, amount=要插入的列数)

插入行 ,在idx列的上面插入一行 不指定amount参数则只插入一行

sheet.insert_cols(idx=第几行, amount=要插入的行数)

删除列 ,在idx列的左边删除一列 不指定amount参数则只删除一列

sheet.insert_cols(idx=第几列, amount=要删除的列数)

删除行 ,在idx列的上面删除一行 不指定amount参数则只删除一行

sheet.insert_cols(idx=第几行, amount=要删除的行数)

”"”移动格子
rows(int): 正整数为向下 负整数为向上
cols(int): 正整数为向右 负整数为向左
“””
sheet.move_range(“C1:D4”, rows=2, cols=-2)

创建sheet

workbook.create_sheet(‘sheet名称’)

删除sheet 参数是一个sheet实例

workbook.remove(sheet)

复制sheet 参数是一个sheet实例

workbook.copy_worksheet(sheet)

修改sheet名称

sheet.title = ‘修改后的名称’

新建一个Excel表格文件, 创建后之后要保存

workbook = Werokbook()
```

1593233165307

demo


APPium

APPIUM下载地址:https://github.com/appium/appium-desktop/releases

flutter网址:http://lemfix.com/topics/44332

Flutter-driver的官方文档:https://github.com/truongsinh/appium-flutter-driver

apiium-Flutter-driver定位需要通过key来定位,key需要前端定义,所以如果前端没有定义key就用xpath吧


appium的官方文档:http://appium.io/docs/en/writing-running-appium/ios/ios-xctest-mobile-gestures/index.html#mobile-swipe

pytest

pytest-中文文档:https://www.cnblogs.com/luizyao/archive/2019/10/31/11771740.html
# 不加@也可以使用
# pytest学习网址:https://blog.csdn.net/python012/article/details/80246480
# pytest学习网址:https://blog.csdn.net/maoxuexue/article/details/106114771
# Pytest的特性:https://www.cnblogs.com/hp1991/p/11238559.html
# @pytest.mark.skip(‘跳过原因’)   解:跳过该用例
# pytest.skip('跳过原因')   可以用于测试函数里,跳过测试用例
# @pytest.mark.skipif(condition='条件',reason='跳过原因') 可以用于测试函数外,有条件地跳过测试用例
# pytest.skip('skip all tests', allow_module_level=True) 跳过当前模块里所有的测试用例。
# pytest.mark.xfail() 使用xfail标记测试用例预期失败,如果测试用例运行实际成功则显示XPASS,实际失败则显示XFAIL

# @pytest.mark.name    name是标签名,可以是中文,自己定义,可在方法或者类上面定义
#使用标签的话要在conftest中定义这个方法,若有多个标签就定义多个config.addinivalue_line
def pytest_configure(config):
    config.addinivalue_line("markers", '标签名称')

# @pytest.fixture(scope='package',)




# 执行时输入 --ff / --failed-first:先执行上次失败的测试用例
# 执行时输入 --lf / --last-failed:只执行上次失败的测试用例
# 执行时输入 -x / --exitfirst:遇到测试用例fail,就结束测试
# 执行时输入-maxfail=num:遇到num条测试用例fail, 就结束测试
import pytest

def setup_module(module):
    """
    这是一个module级别的setup,它会在本module(test_website.py)里
    所有test执行之前,被调用一次。
    注意,它是直接定义为一个module里的函数"""
    print()
    print("-------------- setup before module --------------")

    
@pytest.mark.parametrize('param1', ['full', 'lisa'])
def test_other(param1):
    print('param1 = ' + param1)
    pass
    
@pytest.mark.parametrize('param1 ,param2', [('full','1'), ('lisa','2')])
def test_other(param1,param2):
    allure.attach('param1 ={},param2 ={}'.format(param1,param2),'param')
    pass

def teardown_module(module):
    """
    这是一个module级别的teardown,它会在本module(test_website.py)里
    所有test执行完成之后,被调用一次。
    注意,它是直接定义为一个module里的函数"""
    print("-------------- teardown after module --------------")

    
    import pytest


def setup_module():
	"""模块初始方法"""
	print("模块初始方法")

def teardown_module():
	"""模块结束时执行的方法"""
    print("模块的测试用例环境执行完成后自动执行")

def setup_function():
	"""方法初始化,不在类中"""
    print(每个方法之前执行)


def teardown_function():
	"""方法结束,不在类中"""
    print(每个方法之后执行)


class Test_RemoteStickIn_Case:

    def setup_class(self):
        """pytest的类初始化方法,创建类的时候执行一次"""
        print("每个类都会执行该方法")

	def teardown_class(self):
		"""pytest的类结束方法,该类测试方法结束的时候执行的方法"""
    
    def setup(self):
        """pytest的函数初始化方法,执行函数之前首先执行该方法"""
        print("每个函数都会执行")

    def test_demo(self):
    	"""以test_name或name_test命名的函数会被pytest执行,pytest认为他是一个用例"""
        print("这个是测试用例")

	def test_demo
    
    

if __name__ == '__main__':
 pytest.main([
        '-s',  # 打印信息到控制台
        'app_case.py', # 只运行该文件中的case
        # '--reruns=1', # 失败重跑一次
        "--alluredir", "./allure-results"  # 测试报告框架,执行完生成测试报告数据,需要用alluer进行转html
     	
        # '--self-contained-html',  # 读取项目的配置文件contained,优化pytest-html测试报告
        # '--css='+app_log_html_path+'\\assets\\style.css', # pytest-html使用该文件css
        # '--html=' + path + '.html' \\ pytest-hmtl生成报告放置地址
    ])

pytest-fixture

学习fixture:https://www.cnblogs.com/huizaia/p/10331469.html

@pytest.fixture()

被@pytest.fixtrue()装饰器装饰的方法,可以变成前置方法,

如果使用直接把fixtrue当作参数传入来调用的话,可以传入多个fixtrue方法,并且可以取到fixtrue的返回。下面有示例

有四个参数:

  • scope参数,接收字符串,定义前置方法在什么范围执行
    • function: 每一个函数或方法都会调用
    • class: 每一个类调用一次,一个类中有多个方法
    • module:每一个.py文件调用一次,该文件又有多个function和class
    • session:是多个文件调用一次,可以跨.py文件调用,每个.py文件就是module 该方法要写在第一个.py文件中,pytest查找文件时线性的,从上面第一个,到下面最后一个。
  • autouse:
    • 如果True,则默认开启每个方法都会调用这个前置步骤,若为False则需要手动调用这个前置步骤。
    • 手动调用的方法就是该前置步骤的方法当参数,放入放入方法中
  • params:一个可选的参数列表,它将导致多个参数调用fixture功能和所有测试使用它。
  • ids:每个字符串id的列表,每个字符串对应于params这样他们就是测试ID的一部分。如果没有提供ID它们将从params自动生成,每条用例的id,如果id一样pytest就会自行提供索引。该参数可以在运行时用-k的来过滤指定的id运行。
  • name:fixture的名称。这默认为装饰函数的名称。如果fixture在定义它的统一模块中使用,夹具的功能名称将被请求夹具的功能arg遮蔽,解决这个问题的一种方法时将装饰函数命令”fixture_"然后使用"@pytest.fixture(name='')"。有该参数的时候调用fixture装饰时就要传该name,不能直接传函数名称来调用fixture
import pytest


# a文件


@pytest.fixture(scope="session", autouse=True)
def dasdaf():
    print("这是整个过程唯一一次调用")


@pytest.fixture(scope="module", autouse=True)
def dsadsd():
    print("这是test1模块唯一一次调用")


@pytest.fixture(scope="function")
def setupa():
    print("需要手动调用的前置步骤1")
    return "前置步骤1参数1"

@pytest.fixture(scope="function")
def setupb():
    print("需要手动调用的前置步骤2")


@pytest.fixture(scope="function", autouse=True)
def setup():
    print("每个方法都会调用的前置步骤")


def test_1():
    print("test1_1")


# 手动调用前置步骤方法1
def test_2(setupa):
    print("test1_2")
    a = setupa
    print(a)


# 手动调用前置步骤方法2,传入需要调用的前置步骤名称,该方法可以同时调用多个前置,先执行的放底层,后执行的放上层。
@pytest.mark.usefixtures("setupb")
@pytest.mark.usefixtures("setupa")
def test_3():
    print("test1_3")


pytest.main(["-s"])

执行结果:
这是整个过程唯一一次调用
这是test1模块唯一一次调用
每个方法都会调用的前置步骤
test1_1
.每个方法都会调用的前置步骤
需要手动调用的前置步骤1
test1_2
前置步骤1参数1
.每个方法都会调用的前置步骤
需要手动调用的前置步骤1
需要手动调用的前置步骤2
test1_3
.

Pytest-fixture参数化

  • 该装饰器可以使用params参数来实现整个模块或者整个类的参数化

  • params:一个可选的参数列表,它将导致多个参数调用fixture功能和所有测试使用它。

    • 被带params参数装饰的方法要用request进行接收对象
    • request对象中有个param值就是参数化的参数
  • ids:每个字符串id的列表,每个字符串对应于params这样他们就是测试ID的一部分。如果没有提供ID它们将从params自动生成

    • 我整个模块的测试用例在执行前有个前置的步骤,必须得该步骤后剩下的用例才可以执行

    • # 整个模块的所有用例会运行四次,每次的参数都不一样
      @pytest.fixture(scope="module", autouse=True, params=["mod1", "mod2", "mod3", "mod4"])
      def module_fixture(request):
          # request是一个对象,如果使用fixture的params参数就要接收request对象,不然会报错
          print("模块的测试方法")
          # request的param属性是参数化的参数
          return request.param
          
          
      class TestCase:
          @pytest.fixture(scope="class", autouse=True, params=["mod1", "mod2"])
          def prinas(self, request):
              param = request.param
              print("类的测试方法")
              return param
          
          def test_b(self):
              # 这个方法不需要module_fixture的返回值,可以不接收module_fixturd的方法
              print("testb")
          
          def test_b(self, prinas, module_fixture):
              # 该方法接收模块的fixture和类的前置步骤的参数,因为模块和类已经触发过了,现在就不会重复触发代码,可以直接获取返回值
              # 打印模块前置步骤的返回值
              print(module_fixture)
              # 打印类前置步骤的返回值
              print(prinas)
              print("....................")
              print("测试方法test_b")
      
    • 执行结果:

    • 下列中,模块的测试方法被调用了四次,类方法被调用了8次,每调用一次模块就会调用两次类

    • 普通方法也是各八次

    • ............................................
      ............................................
      模块的测试方法
      **************************************
      类的测试方法
      testa
      .测试方法test_b接收的参数: 模块: mod1 类: mod1
      .**************************************
      类的测试方法
      testa
      .测试方法test_b接收的参数: 模块: mod1 类: mod2
      .
          
      ............................................
      ............................................
      模块的测试方法
      **************************************
      类的测试方法
      testa
      .测试方法test_b接收的参数: 模块: mod2 类: mod1
      .**************************************
      类的测试方法
      testa
      .测试方法test_b接收的参数: 模块: mod2 类: mod2
      .
          
      ............................................
      ............................................
      模块的测试方法
      **************************************
      类的测试方法
      testa
      .测试方法test_b接收的参数: 模块: mod3 类: mod1
      .**************************************
      类的测试方法
      testa
      .测试方法test_b接收的参数: 模块: mod3 类: mod2
      .
          
      ............................................
      ............................................
      模块的测试方法
      **************************************
      类的测试方法
      testa
      .测试方法test_b接收的参数: 模块: mod4 类: mod1
      .**************************************
      类的测试方法
      testa
      .测试方法test_b接收的参数: 模块: mod4 类: mod2
      

fixture参数化互相调用

  • fixture可以进行定制化测试流程

  • 可以解决以下情况:

    • 一个测试用例,两个fixture,B_fixture要调用A_fixture才可以进行使用
    • B_fixture第一次执行需要调用A_fixture,之后不在调用A_fixture方法
    • 这时候可以用作用域或者fixture互相调用解决问题
  • fixture互相调用:

    • import pytest
          
          
      # A_fixture,B_fixture前置步骤,需要执行该方法才能执行B_fixutre
      @pytest.fixture(scope="module", params=["初盘", "复盘"])
      def a(request):
          c = request.param
          print("前置", "-"*50)
          yield c
          print("后置", "*"*50, "\n\n")
          
          
      # B_fixture, 该模块的前置步骤,每次执行都要A方法执行成功才需要执行
      # B_fixture是整个模块的前置步骤,这个前置步骤要执行两次,第一次执行B_fixture这个前置步骤时要先执行A_fixture
      @pytest.fixture(scope="module", autouse=True, params=["dsa", "asd"])
      def b(a, request):
          print(request.param)
          
      # 测试用例
      def test_one():
          print("test_one")
          
      
    • 执行结果

    • 前置 --------------------------------------------------
      dsa
      test_one
      .asd
      test_one
      .后置 ************************************************** 
          
          
      前置 --------------------------------------------------
      asd
      test_one
      .dsa
      test_one
      .后置 ************************************************** 
      

pytest-mark.parametrize

  • @pytest.mark.parametrize((‘参数名1’,‘参数名2’), [(1,2), (3,4)]) 同时传多个参数,生成多条用例

  • @pytest.mark.parametrize(‘参数名1’ [1, 4]) 同时传多个参数,生成多条用例 参数化测试

  • 参数化堆叠使用

    • @pytest.mark.parametrize(‘参数名a’, [值1,值2])

    • @pytest.mark.parametrize(‘参数名b’, [值3, 值4])

    • 示例代码:

    • import pytest
          
      @pytest.mark.parametrize('a', [0, 1])
      @pytest.mark.parametrize('b', [2, 3])
      def test_case(a, b):
      	print(a, b)
      
    • # 运行结果
      结果: 0 2
      结果: 1 2
      结果: 0 3
      结果: 1 3
      

pytest.param

  • pytest.param方法可用于为@pytest.mark.parametrize或者参数化fixture指定一个具体的实参

  • 它有一个关键字参数marks,可以接收一个或一组标记,用于标记这块测试的用例;

  • 使用方法

  • @pytest.mark.parametrize(("ad", "bd"), [
                                          pytest.param(0, 0, marks=pytest.mark.xfail(), id='XPASS'),
                                          pytest.param(1, 2, marks=pytest.mark.xfail(raises=AssertionError), id='XFAIL'),
                                          pytest.param(1, 3, marks=pytest.mark.skip("我跳过了")),
                                          pytest.param(1, 3, marks=pytest.mark.skipif(1 + 1 == 2, reason="1+1等于二跳过"))
                                          ])
    def test_params(ad, bd):
        assert ad == bd, "失败"
    

pytest.hookimp

pytest.hookimp(hookwrapper=True, tryfirst=True)

  • 学习地址:https://www.cnblogs.com/vevian/articles/12631555.html

  • 该插件作用域pytest的钩子函数上,可以获取到测试用例不同阶段执行的结果(steup, claa, teardown)

  • 可以获取钩子方法的调用结果(返回一个result对象)和调用结果的测试报告(返回一个report对象)

  • 用处

    • 做测试log和测试report
  • 实例代码:

    • def pytest_runtest_makereport(item, call):
        """
        每个测试用例执行后,制作测试报告
        :param item:测试用例对象
        :param call:测试用例的测试步骤
                  先执行when=’setup’ 返回setup 的执行结果
                  然后执行when=’call’ 返回call 的执行结果
                  最后执行when=’teardown’返回teardown 的执行结果
        :return:
        """
         # 获取钩子方法的调用结果,返回一个result对象 
        out = yield 
        # # 获取调用结果的测试报告,返回一个report对象, reportd对象的属性包括when(steup, call, teardown三个值)、nodeid(测试用例的名字)、outcome(用例的执行结果,passed,failed)
        report = out.get_result() 
      

pytest.skip

skip的跳过是因为在一开始搜索用例的时候就直接不搜集了,而不是要执行该用例的时候在去skip

  • @pytest.mark.skip装饰器

    • 可以装饰function和类

    • 可选参数reason:str

      • 表明跳过原因
    • 如果要跳过模块的话,把下面的一行代码写在文件的前几行

    • pytestmark = pytest.mark.skip('作用于模块中的每一个用例,所以 pytest 共收集到两个 SKIPPED 的用例。')
          
      
  • pytest.mark.skipif装饰器

    • 可以装饰function和类
    • 参数
      • condition:bool
        • 若是True则代表则skip生效,用例本次跳过执行
        • 若是False则代表skip失效,用例本次不跳过执行
      • reascon:str
        • 原因
  • pytest.skip方法

    • 在fixture作用域执行该方法,则代表跳过该作用域剩余的用例和代码

    • 参数:

      • msg:str

        • 原因
      • allow_module_level:

        • 表明是否允许在模块中调用这个方法,如果置为True,则跳过模块中剩余的部分;

        • 下面代码写在需要需要跳过的前几行

        • pytest.skip('在用例收集阶段就已经跳出了,所以不会收集到任何用例。', allow_module_level=True)
          
    • 作用域:

      • module:

        • 直接跳过剩余的逻辑和module中所有的测试用例,如果有参数化就会跳过

        • @pytest.fixture(scope="module", autouse=True)
          def module_fixture():
              print("模块的测试方法")
              pytest.skip("后面的用例无法执行", allow_module_level=False)
              # request的param属性是参数化的参数
                  
                  
          class TestCase1:
              @pytest.fixture(scope="function", autouse=True)
              def prinas(self, ):
                  print("**************************************")
                  print("类的测试方法")
                  
              def test_a(self):
                  print("类1的testa")
                  
              def test_b(self):
                  print("类1的测试方法test_b")
                  
                  
          class TestCase2:
              @pytest.fixture(scope="function", autouse=True)
              def prinas(self, ):
                  print("**************************************")
                  print("类的测试方法")
                  
              def test_a(self):
                  print("类2的testa")
                  
              def test_b(self):
                  print("类2的测试方法test_b")
          
        • 执行结果

        • 模块的测试方法
          ssss
          
      • class:

        • 直接跳过剩余的逻辑和class中所有的测试用例,如果有参数化就会跳过

        • @pytest.fixture(scope="module", autouse=True)
          def module_fixture():
              print("模块的测试方法")
              # request的param属性是参数化的参数
                  
                  
          class TestCase1:
              @pytest.fixture(scope="class", autouse=True)
              def prinas(self, ):
                  print("**************************************")
                  print("类的测试方法")
                  pytest.skip("后面的用例无法执行", allow_module_level=False)
                  
              def test_a(self):
                  print("类1的testa")
                  
              def test_b(self):
                  print("类1的测试方法test_b")
                  
                  
          class TestCase2:
              @pytest.fixture(scope="class", autouse=True)
              def prinas(self, ):
                  print("**************************************")
                  print("类的测试方法")
                  
              def test_a(self):
                  print("类2的testa")
                  
              def test_b(self):
                  print("类2的测试方法test_b")
          
        • 执行结果

        • 模块的测试方法
          **************************************
          类的测试方法
          s**************************************
          类的测试方法
          s**************************************
          类的测试方法
          类2的testa
          .**************************************
          类的测试方法
          类2的测试方法test_b
          
      • function:

        • 直接跳过剩余的逻辑,和用例

        • class TestCase2:
              @pytest.fixture(scope="function", autouse=True)
              def prinas(self, ):
                  print("**************************************")
                  print("function的测试方法")
                  pytest.skip("后面的用例无法执行", allow_module_level=False)
                  
              def test_a(self):
                  print("类2的testa")
                  
              def test_b(self):
                  print("类2的测试方法test_b")
          
        • 执行结果:

        • **************************************
          function的测试方法
          s**************************************
          function的测试方法
          s
          

pytest-html

# 写在conftest.py文件,直接新建一个py命名为conftest.py,pytest框架会自动读取,创建driver的时候给该模块的driver赋值
from py.xml import html
import pytest

driver = None
"""pytest-html官方文档:https://pypi.org/project/pytest-html/"""


@pytest.mark.hookwrapper
def pytest_runtest_makereport(item):
    """
    当测试失败的时候,自动截图,展示到html报告中
    :param item:
    """
    pytest_html = item.config.pluginmanager.getplugin('html')
    outcome = yield
    report = outcome.get_result()
    extra = getattr(report, 'extra', [])

    if report.when == 'call' or report.when == "setup":
        xfail = hasattr(report, 'wasxfail')
        if (report.skipped and xfail) or (report.failed and not xfail):
            file_name = report.nodeid.replace("::", "_") + ".png"
            screen_img = _capture_screenshot()
            if file_name:
                html = '<div><img src="data:image/png;base64,%s" alt="screenshot" style="width:410px;height:738px;" ' \
                       'onclick="window.open(this.src)" align="right"/></div>' % screen_img
                extra.append(pytest_html.extras.html(html))
        report.extra = extra
        report.description = str(item.function.__doc__)


def _capture_screenshot():
    """截图保存为base64,展示在html中"""
    return driver.get_screenshot_as_base64()


@pytest.mark.optionalhook
def pytest_html_results_table_header(cells):
    """测试报告新增一列,用例的描述"""
    cells.insert(1, html.th('Description'))


@pytest.mark.optionalhook
def pytest_html_results_table_row(report, cells):
    """执行测试用例的时候,获取到用例的描述,写入测试报告Description列中"""
    cells.insert(1, html.td(report.description))

allure

装饰器 作用
@allure.epic() 项目
@allure.feature() 实现的功能 学习地址:http://www.likecs.com/show-100725.html
@allure.story() 子功能
@allure.tag() 标签,从上(epic)到下(tag)四层
@allure.description() 描述
@allure.issue() BUG链接
@allure.line() 链接
@allure.title() 标题
@allure.severity() 优先级/严重等级 学习地址:https://www.cnblogs.com/jodie2019/p/13235278.html
@allure.attach() 可以添加一些描述,添加到allure报告中的
@allure.step() 步骤
@allure.description_html() 网页描述
@allure.dynamic. 该装饰器可以在类中使用,可以直接获取到方法的参数
allure可以通过{}获取fixture的参数 方法的参数,如有形参a,b ,可以通过allure.tag(“{a}旁边是获取到的形参”)

allure参数化

  • allure的名称可以通过{}获取pytest的参数化的参数

    • 代码

      • import allure
        import pytest
              
              
        @pytest.fixture(scope="session", autouse=True, params=[{"test1": "te1", "test2": "te2"}])
        def a(request):
           pass
              
              
        @allure.title("参数是{a}")
        def test_b(a):
            print("测试步骤2")
            print("\ntest_b")
        
    • 执行结果

      • 测试步骤2
              
        test_b
        .
        
  • allure是直接通过底层触发器获取参数,并非获取返回值

  • 源码

  • 1608710912407

用命令行方式运行时,可以指定运行某个story或者feature
运行某个story:pytest tests.py --allure-stories story_1,story_2

运行某个feature:pytest tests.py --allure-features feature2 --allure-stories story2

运行指定参数epic:--allure-epics

通过命令行参数运行指定severity的测试用例
运行指定severity:pytest tests.py --allure-severities normal,critical
import os

import pytest
import allure

@allure.epic('购物车功能')  # 用feature说明产品需求,可以理解为JIRA中的Epic
class TestShoppingTrolley(object):

    @allure.feature('加入购物车')  # 用story说明用户场景,可以理解为JIRA中的Story
    def test_add_shoppig_trolley(self):
        """错误"""
        login('刘春明', '密码')  # 步骤1,调用“step函数”
        create_inventroy_number('抽盘')
        with allure.step("浏览商品"):  # 步骤2,step的参数将会打印到测试报告中
            allure.attach('笔记本', '商品1')  # attach可以打印一些附加信息
            allure.attach('手机', '商品2')
        with allure.step("点击商品"):  # 步骤3
            pass
        with allure.step("校验结果"):  # 步骤4
            allure.attach('添加购物车成功', '期望结果')
            allure.attach('添加购物车失败', '实际结果')
            assert 'success' == 'failed'

    @allure.story('修改购物车')
    def test_edit_shopping_trolley(self):
       print('修改购物车')

    @pytest.mark.skipif(reason='本次不执行')
    @allure.story('删除购物车中商品')
    def test_delete_shopping_trolley(self):
        print('删除购物车中商品')

queue

  • 学习网址:https://www.cnblogs.com/nul1/p/9226766.html

  • queue模块是python的标准库,queue俗称队列
  • queue模块有三种队列
  1. FIFO队列

    class queue.Queue(maxsize)

    该队列是先进先出的队列

  2. LIFO类似于堆,既先进后出,

    class queue.LifoQueue(maxsize)

    该队列是最后进来的数据,在取的时候最快取出来,先进来的被压在底下

  3. 优先级别越低越先出来

    class queue.PriorityQueue(maxsize)

requests

  • python请求模块

  • 可以发出请求,接收请求

  • 注意事项:

    • post方法会在url中取值,但是优先级没有在body中取值的高
  • 共有参数

    • # 共有代码
      import requests
      def getToken(host, prot, username, password):
          url = "http://{}:{}/auth-service/oauth/token".format(host, prot)
          params = {"username": username, "password": password, "grant_type": "password"}
          # 特有代码所在行
          
      getToken("q.9-can.com", "1211", "xiaochen", "111111")
      
    • data

      • 传入字典,自动把字典转成入参格式,放置在请求体里

      • 实例:

        • 特有代码

        • r = requests.post(url, data=params, headers=headers)
          
        • 请求体,url中无任何数据

        • username=xiaochen&password=111111&grant_type=password
          
    • params

      • 传入字典,自动把字典转成入参格式,拼接url中

      • 实例

        • 特有代码:

          r = requests.post(url, params=params, headers=headers)
          
        • 接口请求url, 请求体中无任何数据:

        • POST http://q.9-can.com:1211/auth-service/oauth/token?username=xiaochen&password=111111&grant_type=password HTTP/1.1
          
    • json

      • 传入python对象,自动把python对象转成json格式,放置在请求体中

      • 实例

        • 特有代码

        • r = requests.post(url, json=params, headers=headers)
          
        • 接口请求的请求体

        • {"username": "xiaochen", "password": "111111", "grant_type": "password"}
          
    • files

      • 学习地址:

        https://www.cnblogs.com/angle6-liu/p/11724850.html
        
      • 传入文件的二进制流,上传文件使用

      • 实例

        • 特有代码

        • file = open('E:\\testdoc\\Script\\kettle\\jcrios_kettle\\out\\' + filename + '', 'rb')
          rp = requests.post(url, files=data, headers=header)
          
      • 注意事项:

        • 使用该参数时,不要指定Content-Type请求头

          • 原因:Content-Type请求头后面会携带一个boundary=分隔符号

          • 使用files上传文件时,reuqest模块会自动调用encode_multipart_formdata()分隔文件,分隔文件时的分隔符自动生成。若是指定请求头Content-Type,那就造成分隔符号与Content-Type不符。

          • 若是非要使用Contet-Type,代码如下:

          • import requests
            from pip._vendor.urllib3 import encode_multipart_formdata
                      
            # 指定Content-Type ,并且指定分隔符
            headers = {"Content-Type": "multipart/form/-data; boundary=eb9381dfbcc1ea83f3f820585a0d3227"}
            data = {"user": 123, "321": "321"}
            # 对数据进行分隔,并且指定分隔符,可以传入文件二进制
            test_data = encode_multipart_formdata(fields=data, boundary="eb9381dfbcc1ea83f3f820585a0d3227")
            requests.post(url="www.baidu.com", data=test_data, headers=headers)
            print(test_data)
            
  • 常用方法

    • post
      • 发出一个post请求
    • get
      • 发出一个get请求

selenium

  • Web的UI测试框架,可以进行使用CSS、XPATH等语法进行定位元素进行测试

WebDriverWait

学习地址:https://www.cnblogs.com/fcc-123/p/10942883.html
  • selenium的显示等待,该等待会在固定的时间取检测界面是否出现元素
  • 实例化参数
    • driver: 传入WebDriver实例
    • timeout: 超时时间,等待的最长时间(同时要考虑隐性等待时间)
    • poll_frequency: 调用until或until_not中的方法的间隔时间,默认是0.5秒
    • ignored_exceptions: 忽略的异常,如果在调用until或until_not的过程中抛出这个元组中的异常, 则不中断代码,继续等待,如果抛出的是这个元组外的异常,则中断代码,抛出异常。默认只有NoSuchElementException。
  • 方法
    • until
      • method: 在等待期间,每隔一段时间(__init__中的poll_frequency)调用这个传入的方法,直到返回值不是False
      • message: 如果超时,抛出TimeoutException,将message传入异常
    • until_not
      • 与until相反,until是当某元素出现或什么条件成立则继续执行,
      • until_not是当某元素消失或什么条件不成立则继续执行,参数也相同,不再赘述。

expected_conditions

学习网址:https://blog.csdn.net/weixin_42575593/article/details/83304005
  • 场景判断模块,可判断一些元素是否存在,是否可以点击

  • 类:

    • presence_of_all_elements_located

      • 根据By枚举类,进行元素定位的类,

      • 参数

        • locator
          • tuple
          • 定位器,元组中下标0是By类的枚举,下标1是该枚举的语法语法
      • return list of WebElement

      • from selenium.webdriver.support import expected_conditions as EC
        from selenium.webdriver.common.by import By
        EC.presence_of_all_elements_located((By.CSS_SELECTOR, "body"))
        

目 录