可以参考文章:https://blog.csdn.net/woailuohui/article/details/84604251:大佬写的很详细
is:比较两个变量是否指向了同一个内存地址
而==比较的是对象所指代的value值是否相等
break语句用来终止循环语句,即循环条件没有False条件或者序列还没被完全递归完,也会停止执行循环语句。
break语句用在while和for循环中。
如果您使用嵌套循环,break语句将停止执行最深层的循环,并开始执行下一行代码。
for letter in 'Python': # 第一个实例
if letter == 'h':
break
print '当前字母 :', letter
var = 10 # 第二个实例
while var > 0:
print '当前变量值 :', var
var = var -1
if var == 5: # 当变量 var 等于 5 时退出循环
break
print "Good bye!"
continue 语句跳出本次循环,而break跳出整个循环。
continue 语句用来告诉Python跳过当前循环的剩余语句,然后继续进行下一轮循环。
continue语句用在while和for循环中。
for letter in 'Python': # 第一个实例
if letter == 'h':
continue
print '当前字母 :', letter
var = 10 # 第二个实例
while var > 0:
var = var -1
if var == 5:
continue
print '当前变量值 :', var
print "Good bye!"
{}、[]、set()、False、()、0、‘’、None
方式一:
a,b,c= 1,2,3
a=b=c=3
方式二:
a=b=c=2
c=1.1
d=2.2
print(c+d) 3.3000000000000003
from decimal import Decimal
print(Decimal('1.1')+Decimal('2.2')) 3.3
def fun(number):
if number>=-9 and number<=9:
return number
num=str(number)
if num[0]=='-':
num1=num[1:][::-1]
num1=int(num1)
num1=-num1
return num1
else:
num1=num[::-1]
return num1
print(fun(-1234))
print(sum(range(1,101)))
def fun():
for i in range(1,10):
for j in range(1,i+1):
print('{}*{}={}'.format(i,j,i*j),end='\t')
print()
fun()
-1是最后一个索引,-2是倒数第二个索引
print(sum(range(1,10249)))
python中的运算符:
算术运算符:+、-、*、\、%、//、
比较运算符:>,<, =,<=,>= ,!=
赋值运算符:= += -= *= /= //= **=
逻辑运算符:and or not
成员运算符:in not in
身份运算符:is is not
位运算符:
li=[[x for x in range(1,100)][i:i+3] for i in range(0,100,3)]
print(li)
print(int('1.4')) 报错
print(int(1.4)) 1
IOError:输入输出异常
AttributeError:试图访问一个对象没有属性
ImportError:无法引入模块和包,,基本是路径的问题
IndentationError::语法错误,代码没有正确的对齐
IndexError:下标索引超出序列边界
KeyError:试图访问字典中不存在的键
SyntaxError:代码逻辑语法错误,不能执行
NameError:使用一个还未赋予对象的变量
import json
d={"laker":"詹姆斯"}
dd=json.dumps(d,ensure_ascii=False)
print(dd)
with open('1.txt','r',encoding='utf-8') as f:
content=f.readlines()
for line in content:
print(line)
但是,当完成这一操作时,readlines() 方法(read() 也一样)会将整个文件加载到内存中。在文件较大时,往往会引发 MemoryError(内存溢出)。
with open('1.txt','r',encoding='utf-8') as f:
while True:
content=f.readline()
for line in content:
if not line:
break
print(line)
def read_in_chunks(file_obj,chunk_size=2048):
'''
逐件读取文件
默认块大小:2kb
'''
while True:
data=file_obj.read(chunk_size) #每次读取指定的长度
if not data:
break
yield data
with open('1.txt','r',encoding='utf-8') as f:
g=read_in_chunks(f)
print(g.__next__())
print(g.__next__())
print(g.__next__())
print(g.__next__())
with open('1.log','r') as f:
count=0
txt=f.read()
print(txt)
for item in txt:
if item.isupper():
count+=1
print(count)
with open('c:\ scores.txt','a') as f:
f.write('输入内容')
try中的代码没有抛出错误
如果使用常规的f.open()写法,我们需要try、except、finally,做异常判断,并且文件最终不管遇到什么情况,都要执行finally f.close()关闭文件。
执行with这个结构之后。f会自动关闭。相当于自带了一个finally。
但是with本身并没有异常捕获的功能,但是如果发生了运行时异常,它照样可以关闭文件释放资源。
f=open('./1.txt','w')
try:
f.write("hello")
except:
pass
finally:
f.close()
使用with方法
with open('a.txt') as f:
print(f.read())
os.remove('3.log')
rm file
try:把可能出现的异常代码放进try中,代表异常处理即将要处理的代码段。
except xxx:捕获异常,xxx表示异常类型,如果你大概知道代码会报出什么异常,那么我们可以直接把具体异常类型类型填上。执行过程中,出现了xxx异常,那么该段代码就会执行。
else:当try段代码能够正常执行,没有出现异常的情况下,会执行else段代码。
finally:不管有没有异常,最终都会执行。
print(os.path.abspath(__file__)) #当前文件的路径
print(os.path.dirname(__file__)) #当前文件所在目录
print(os.path.basename(__file__)) #当前文件的名称
with open('1.log','r') as f:
lit=[]
txt=f.readlines()
print(txt)
num=len(txt)
for i in range(1,num+1):
lit.append(txt[num-i])
print(lit)
[‘erwer\n’, ‘wrtwer\n’, ‘fsd\n’, ‘fsdf\n’, ‘sdfG\n’, ‘sdfg\n’, ‘GHG\n’, ‘ER’]
[‘ER’, ‘GHG\n’, ‘sdfg\n’, ‘sdfG\n’, ‘fsdf\n’, ‘fsd\n’, ‘wrtwer\n’, ‘erwer\n’]
def get_line():
with open('1.log','r') as f:
while True:
data=f.readlines(6)
if data:
yield data
else:
break
f=get_line()
print(next(f))
print(next(f))
print(next(f))
print(next(f))
print(next(f))
print(next(f))
print(next(f))
1 os.path 主要是用于对系统路径文件的操作。
2 sys.path 主要是对Python解释器的系统环境参数的操作(动态的改变Python解释器搜索路径)。
https://blog.csdn.net/YZL40514131/article/details/125609673?spm=1001.2014.3001.5501
def fun(p):
list=os.walk(p)
for path,dir_path,file_path in list:
for file in file_path:
txt=os.path.join(path,file)
print(txt)
for dir in dir_path:
d=os.path.join(path,dir)
print(d)
fun(r'D:\second_hand_car\SecondHand_list_query')
赋值(=),就是创建了对象的一个新的引用,修改其中任意一个变量都会影响到另一个。
list():表示创建了一个对象,但是并没有创建引用
d=list():表示创建了一个对象,并且创建了一个对象的引用
a=b:表示创建了一个对象的引用,但是没有创建对象
浅拷贝:创建一个新的对象,但它包含的是对原始对象中包含项的引用(如果用引用的方式修改其中一个对象,另外一个也会修改改变){1,完全切片方法;2,工厂函数,如list();3,copy模块的copy()函数}
class Person:
def __init__(self,name):
self.name=name
if __name__ == '__main__':
p1=Person('kobe')
p2=Person('james')
l1=[p1,p2]
p1.name='jorden'
l2=list(l1) #浅拷贝
print(l2[0].name) #jorden
print(id(l1)) #2278620394368
print(id(l2)) #2278620429056
深拷贝:创建一个新的对象,并且递归的复制它所包含的对象(修改其中一个,另外一个不会改变),因此,新对象和原对象没有任何关联。{copy模块的deepcopy()函数}
class Person:
def __init__(self,name):
self.name=name
if __name__ == '__main__':
p1=Person('kobe')
p2=Person('james')
l1=[p1,p2]
l3=copy.deepcopy(l1)
p1.name='curry'
print(l3[0].name) #kobe
print(id(l1)) #2351425281088
print(id(l3)) #2351425358080
random.sample(seq,k):
实现从序列或集合中随机选取k个独立的元素
seq:元组、列表、字符串
k:选取元素个数
import random
lis=[1,2,11,8,23,24,35,7,30]
num=random.sample(lis,3)
print(num)
结果:[23, 2, 11]
random.chioce(seq):
实现从序列或集合中随机选取一个元素
seq:元组、列表、字符串
lis=[1,2,11,8,23,24,35,7,30]
num1=random.choice(lis)
print(num1)
结果:1
import smtplib
from email.mime.application import MIMEApplication
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import os
from common.handle_path import REPORT_DIR
def send_report(report_name):
'''通过qq 邮箱发送测试报告给指定的用户'''
# 第1步,连接qq smtp服务器,模拟登录
# 1.1 todo 连接到qq smtp服务器---smtp.qq.com(官网找)
smtp = smtplib.SMTP_SSL(host='smtp.qq.com', port=465) # 创建一个连接服务器的对象,加断点可以看smtp有很多方法
smtp.login(user='xxxxxx@qq.com', password='xxxxxxx') # gbffgrpvozcnjeag 是开启smtp的时候,qq给的授权码
# todo 第2步:构建一封对象
msg = MIMEMultipart()
msg['Subject'] = report_name[:-5] # 邮件标题
msg['To'] = 'xxxxxx@qq.com'
msg['From'] = 'xxxxxx@qq.com'
# todo 构建发送内容
text = MIMEText('你好附件是测试报告请查收', _charset='utf-8') # 构建文本对象
msg.attach(text) # 把内容添加到邮件中
# todo 上传附件
# todo 读取附件内容,byte格式
report_file = os.path.join(REPORT_DIR, report_name)
with open(report_file, mode='rb') as f:
content = f.read() # 读取内容
report = MIMEApplication(content) # 构造附件对象
# todo 指定附件格式
report.add_header('content-disposition', 'attachment', filename=report_name)
msg.attach(report) # 把构造的附件添加到邮件中
# todo 第3步: 发送邮件 谁发的 #发给谁 列表里可以添加多个qq邮箱
smtp.send_message(msg, from_addr='xxxxxx@qq.com', to_addrs=['xxxxxx@qq.com'])
if __name__ == '__main__':
send_report(report_name='接口自动化测试报告.html')
import random
num=random.randint(1,8)
print(num)
num1=random.random()
print(num1)
print('{:.2f}'.format(num1))
print(round(num1,4))
执行结果:
5
0.6067638026607728
0.61
0.6068
os
sys
re
time
json
datetime
logging
requests
unittest
random
import os
import time
import datetime
import re
import sys
import json
from collections import Counter
num=Counter("kjalfj;ldsjafl;hdsllfdhg;lahfbl;hl;ahlf;h")
print(num)
Counter({‘l’: 9, ‘;’: 6, ‘h’: 6, ‘f’: 5, ‘a’: 4, ‘j’: 3, ‘d’: 3, ‘s’: 2, ‘k’: 1, ‘g’: 1, ‘b’: 1})
import datetime
def fun():
year=input('请输入年:')
month=input('请输入月:')
day=input('请输入日:')
a=datetime.date(year=int(year),month=int(month),day=int(day))
b=datetime.date(year=int(year),month=1,day=1)
c=(a-b).days
return c
print(fun())
sys.path 返回模块的搜索路径,初始化时使用 PYTHONPATH 环境变量的值
sys.stdout 标准输出
sys.stdin 标准输入
sys.stderr 错误输出
pymysql
openpyxl
rest_framework
pytest
filter
Jinja2
SQLALchemy
requests
pywin32
redis
django
selenium
flask
tornade
l=[1,2,3,4]
l1=tuple(l)
print(l1)
l=(1,2,3,4)
l1=list(l)
print(l1)
1、列表可变和元组不可变
2、元组比列表的访问和处理速度快,如果只需要对其中的元素进行访问,而不进行任何修改,建议使用元组而不使用列表
3、因为列表可以修改,元组不可以修改,因此元组比列表具有更高的安全性。
4、列表不可以作为字典的键,元组可以作为字典的键
Python中的序列是索引的,它由正数和负数组成。正的数字使用’0’作为第一个索引,'1’作为第二个索引,以此类推。
负数的索引从’-1’开始,表示序列中的最后一个索引,’ - 2’作为倒数第二个索引,依次类推
d={"a":"kobe","b":"james"}
d2={"c":"curry"}
print(d.keys())
print(d.values())
print(d.items())
d={"a":"kobe","b":"james"}
d1=d.pop("b")
print(d1) james
d={"a":"kobe","b":"james"}
d2={"c":"curry"}
d.update(d2)
print(d) {'a': 'kobe', 'b': 'james', 'c': 'curry'}
li=[1,4,2,6,8,5]
list(set(li))
di={"a":"kobe","c":"curry","b":"james"}
di1=sorted(di.keys(),key=lambda x:x,reverse=True)
d={}
for i in di1:
d[i]=di[i]
print(d)
a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
b=[i for i in a if i%2==1]
print(b)
a=(1,)
b=(1)
c=('1')
print(type(a))
print(type(b))
print(type(c))
执行结果:
a=[1,3,4,5,6]
b=[1,3,56,7,7,5]
c=a+b
a.extend(b)
a.sort()
print(c)
print(a)
l=[[1,2],[3,4],[5,6]]
new_list=[]
for item in l:
for i in item:
new_list.append(i)
print(newlist)
join():括号里面的是可迭代对象,x插入可迭代对象中间,形成字符串,结果一致
x = "abc"
y = "def"
z = ["d", "e", "f"]
x_1=x.join(y)
print(x_1)
x_2=x.join(z)
print(x_2)
[1,2,3,4,5,6]
foo =[-5,8,0,4,9,-4,-20,-2,8,2,-4]
foo1=sorted(foo,key=lambda x:x)
print(foo1)
foo =[-5,8,0,4,9,-4,-20,-2,8,2,-4]
foo1=sorted(foo,key=lambda x:x)
print(foo1)
foo=[{'name':'zs','age':18},
{'name':'li','age':24},
{'name':'ww','age':25},]
按照姓名排序
foo1=sorted(foo,key=lambda x:x['name'])
print(foo1)
按照年领排序
foo2=sorted(foo,key=lambda x:x['age'],reverse=True)
print(foo2)
foo1=[('zs',19),('ls',18),('ww',20)]
foo2=sorted(foo1,key=lambda x:x[0])
print(foo2)
foo3=sorted(foo1,key=lambda x:x[1])
print(foo3)
foo1=[('zs',19),('ls',18),('ww',20)]
foo2=sorted(foo1,key=lambda x:x[0])
print(foo2)
foo3=sorted(foo1,key=lambda x:x[1])
print(foo3)
def dict_sortd(dic):
return sorted(zip(dic.keys(),dic.values()))
d={"kobe":18,"james":20,"curry":19}
print(dict_sortd(d))
执行结果:[(‘curry’, 19), (‘james’, 20), (‘kobe’, 18)]
d={"kobe":18,"james":20,"curry":19}
d1=sorted(d.keys(),key=lambda x:x)
print(d1)
历史博文尽请关注
json.loads()
json.dumps()
l=[1,2,3,4]
l1=[2,4,5,6]
print(list(set(l) ^ set(l1))) #差集
print(list(set(l) & set(l1))) #交集
print(list(set(l) | set(l1))) #并集
[1, 3, 5, 6]
[2, 4]
[1, 2, 3, 4, 5, 6]
import openpyxl
class HandleExcel(object):
"""让读写Excel格式的测试用例更方便
Attributes:
filename: Excel文件的路径。
sheet_name: 要读取的用例在哪个Sheet中,默认是Sheet1
"""
titles = ('id', 'title', 'data', 'expected') # 固定的标题
def __init__(self, filename, sheet_name):
"""创建一个HandExcel对象
args:
filename: excel文件的路径
sheet_name: 要读取的工作表名,如果没有指定默认使用Sheet1当做工作表名
"""
self.filename = filename
self.sheet_name=sheet_name
# if sheet_name is None:
# self.sheet_name = 'Sheet1'
# else:
# self.sheet_name = sheet_name
def read_data(self) -> list: # 返回值是list
cases = [] # 用来存储所有用例
titles = [] # 保存标题
wb = openpyxl.load_workbook(self.filename) # 获取工作簿对象
ws = wb[self.sheet_name]
# 遍历所有行
# 如果是表头,把表头保存到titles列表中,否则把数据添加到cases列表中
for i, row in enumerate(ws.rows):
if i == 0:
for cell in row:
titles.append(cell.value)
else:
cases.append(dict(zip(titles, [cell.value for cell in row])))
return cases
def write_data(self, row, column, value) -> None:
"""把数据写到指定的单元格
args:
row: 行号
column: 列号
value: 要写入的值
returns:
None
"""
wb = openpyxl.load_workbook(self.filename) # 获取一个WorkBook对象
ws = wb[self.sheet_name] # 获取一个WorkSheet对象
ws.cell(row, column, value)
wb.save(self.filename)
return None
if __name__ == '__main__':
excel = HandleExcel(r'C:\Users\api_test\data\apicases.xlsx','register')
for case in excel.read_data():
print(case)
l2=[2,4,5,6]
from random import shuffle
mylist=[x for x in range(10)]
shuffle(mylist)
print(mylist)
join():字符串的拼接,传参类型为可迭代对象,并且可迭代对象中的元素为字符串类型
li=[1,3,5,7]
l=''.join(li)
print(l)
抱错:TypeError: sequence item 0: expected str instance, int found
li=['1','3','5','7']
l=''.join(li)
print(l) 1357
split():字符串的拆分,拆分后为列表,传递的参数为分隔符
a='1357'
print(a.split(' ')) ['1357']
mytuple=3,4,5
print(mytuple)
x,y,z=mytuple
print(x+y+z)
(3, 4, 5)
12
int
float
str
bool
list
tuple
dict
set
int(str)
通过不断的调用__next()__方法能不断的返回下一个值的机制
q=[i*11 for i in range(1,10)]
print(q)
a=[1,2,3,4]
b=[3,4,5,6]
print(list(set(a) & set(b))) [3, 4]
print(list(set(a) | set(b))) [1, 2, 3, 4, 5, 6]
print(list(set(a) ^ set(b))) [1, 2, 5, 6]
global
会
反转字符串
format
1、数字在[ -5 , 256]之间的数字
2、字符串的长度为0或者为1
3、当字符串的长度大于1时,满足只能包含数字、下划线、字母类型的字符
4、编译时进行驻留,而非运行时
split
format
index
find
replace
upper
lower
count
strip
isdigit
isspace
join
encode
endswith
startswith
isalpha
islower
isspace
isupper
append
extend
pop
remove
count
max
min
sort
reverse
insert
clear
copy
index
count
keys
items
values
pop
update
clear
copy
fromkeys
get
将可迭代对象转化为带有索引的数组
lis=[1,2,3,34,54]
for index,value in enumerate(lis):
print(index,value)
print('-----------------------------')
ll={"kobe":"laker","jorden":"bulls"}
for index,value in enumerate(ll):
print(index,value)
0 1
1 2
2 3
3 34
4 54
0 kobe
1 jorden
1.队列可以看成是有2个口的集合一个口叫队头一个叫队尾,只能在对头进行删除操作,在队尾做插入。根据这样的操作。队列特点是先进先出
2.堆栈可以看成是有1个口的集合,这个口叫栈顶。插入和删除操作只能在栈顶操作。根据这样的操作。堆栈的特点是是后进先出.
3.链表是一种存储方式,它可以在 非连续的内存空间里面存储一个集合的元素。
4.和它对应的是数组,数组要在 连续的空间里存储集合的元素
队列、栈是线性数据结构的典型代表,而数组、链表是常用的两种数据存储结构;队列和栈均可以用数组或链表的存储方式实现它的功能
数组与链表:
数组属于顺序存储中,由于每个元素的存储位置都可以通过简单计算得到,所以访问元素的时间都相同(直接访问数组下标);
链表属于数据的链接存储,由于每个元素的存储位置是保存在它的前驱或后继结点中的,所以只有当访问到其前驱结点或后继结点后才能够按指针访问到自己,访问任一元素的时间与该元素结点在链接存储中的位置有关。 链表和数组是常用的两种数据存储结构,都能用来保存特定类型的数据。
链表存放的内存空间可以是连续的,也可以是不连续的,数组则是连续的一段内存空间。一般情况下存放相同多的数据数组占用较小的内存,而链表还需要存放其前驱和后继的空间。
链表的长度是按实际需要可以伸缩的,而数组的长度是在定义时要给定的,如果存放的数据个数超过了数组的初始大小,则会出现溢出现象。
链表方便数据的移动而访问数据比较麻烦;数组访问数据很快捷而移动数据比较麻烦。链表和数组的差异决定了它们的不同使用场景,如果需要很多对数据的访问,则适合使用数组;如果需要对数据进行很多移位操作,则设和使用链表。
1.栈具有数据结构中栈的特点,后进先出,所有存放在它里面的数据都是生命周期很明确(当然要求它不能存放太久,占有的空间确定而且占用空间小),能够快速反应的!所有在Java中它存放的是8个基本数据类型和引用变量的,用完就马上销毁
2.堆可以理解它就是个一个可大可小,任你分配的听话的内存操作单元;因此它的特点就是动态的分配内存,适合存放大的数据量!比如一个对象的所有信息,虽然它的引用指向栈中的某个引用变量;所有Java中堆是存放new出来的对象的。
后端:
1、对于缓冲存储读写次数高、变化少的数据,比如网站首页的信息。应用程序读取数据时,一般是先从缓冲中给读取,如果读取不到或者数据已经失效,再访问磁盘数据库,并将数据再次写入缓冲。
2、异步方式,如果有耗时操作,采用异步,celery
3、代码优化,避免循环和判断次数太多,如果有多个if else判断,优先判断最有可能先发生的情况。
数据库优化
1、如有条件,数据可以存放redis,读取速度快
2、建立索引、外键
前端:
1、html和css放在页面的上部,javascript放在页面下方,因为javascript加载比html和css加载慢,所以要优先加载html和css,以防页面显示不全,性能差,影响用户体验
break
pyc是一种二进制文件,是由py文件经过编译后,生成的文件,是一种byte code,py文件变成pyc文件后,加载的速度有所提高,而且pyc是一种跨平台的字节码,是由Python的虚拟机来执行的
aStr[::-1]
a='k:1|k1:2|k2:3|k3:4'
def fun(str):
d={}
for i in a.split("|"):
key,value= i.split(":")
d[key]=value
print(d)
fun(a)
ss=s.replace(' ','')
print(ss)
import datetime
class fun_time:
def __init__(self,file_name,level):
self.file_name=file_name
self.level=level
def __call__(self,func, *args, **kwargs):
def write(*args,**kwargs):
now_time = datetime.datetime.now()
result=func(*args,**kwargs)
time.sleep(3)
end_time = datetime.datetime.now()
print(end_time-now_time)
with open(self.file_name,'a',encoding='utf-8') as f:
f.write('函数运行时间为:{}'.format(end_time-now_time))
return result
return write
@fun_time(file_name='1.txt',level='info')
def fun_work():
sum=0
for i in range(1,1001):
sum+=i
return sum
if __name__ == '__main__':
print(fun_work())
在 result = a and b 运算中:
当a为假时,无论b为真或假,结果都为假,此时b的运算就不会进行,结果直接为a即可;
当a为真时,结果还得看b,b为真则真,b为假则假,此时结果即为b;
在result = a or b 运算中:
如果a 为真则无论b为什么结果都会是真,结果即为b
如果a 为假则看b的情况了,b为真则结果为真,b为假则结果为假,即结果为b
可以大大加快数据的检索速度,这也是创建索引的最主要的原因。
创建索引可以在查询的过程中,提高系统的性能
通过创建唯一性索引,可以保持数据库表中每一行数据的唯一性
时间方面:创建索引和维护索引要消耗时间,
空间方面:索引需要占用物理空间
主键索引:数据不允许重复,不允许为null,一个表只能有一个主键
唯一索引:数据列不允许重复,允许为null值,数据列不允许重复,允许为NULL值,一个表允许多个列创建唯一索引。
普通索引:基本的索引类型,没有唯一性的限制,允许为NULL值。
a、不必一条记录所有的字段都进行查询(不要用*)
原子性:一个事务不可再分割,要么都执行要么都不执行。
一致性:一个事务执行会使数据从一个一致的状态切换到另一个一致的状态。
隔离性:一个事物的执行不会受其他事务的干扰。
持久性:一个事务一旦提交,则会永久性的改变。
@classmethod
@staticmethod
@property
@ddt @data
@pytest.mark.parametrize('test_info', plan_data)
pytest数据驱动
@action(method='GET',detail=False)
路由器机制
@cache_page(10, cache='default', key_prefix='mysite')
视图上加缓冲
@pytest.fixture(scope='class')
:表示每条用例执行的前置条件和后置条件
判断某个对象是不是具体的某个数据类型
序列化和反序列操作:
序列化:将模型对象或者查询集对象转化为json格式的数据
反序列化:将json格式的数据转化为其他类型的数据包括模型对象和查询集对象
减少for循环执行次数
多个if elif 语句执行尽量将执行频率高的语句写到最上边
使用生成器对象迭代数据,不用列表或者列表生成器
异步执行任务
class中是方法
class外是函数
python中一切皆对象
@pytest.fixture(scope='class')
def browser():
# todo 1、打开浏览器
browser = webdriver.Chrome("C:\Program Files\Google\Chrome\Application\chromedriver.exe")
browser.implicitly_wait(10)
yield browser
# todo 11、关闭浏览器
browser.quit()
class Person:
def __init__(self,age):
self.__age=age #__age是一个私有属性
#使用属性装饰器,具有只读属性,无法赋值
@property
def age(self):
if self.__age<0:
return 18
return self.__age
#如果希望对一个“属性”进行赋值,那就还需要使用装饰器了
@age.setter
def age(self,value):
self.__age=value
if __name__ == '__main__':
p=Person(20)
print(p.age)
p.age=24
print(p.age)
对象属性的查找顺序:对象自己>>类中>>报错
class Student:
school=''
def choose_course(self):
print(self.school)
print('选课技能')
#定义两个不同的对象
s1=Student()
s2=Student()
#下面打印出来的都是哈佛,因为对象s1和对象s2的名称空间中,都没有school属性,共用类的名称空间中的school属性
print(s1.school)
print(s2.school)
#假设s1同学转学去了牛津了
s1.school='牛津' #对象增加了属性
print(s1.school)
print(s2.school)
print(Student.school)
#对象自己有的属性,优先使用自己的,没有才去类中找,如果类中也没有则报错
对象自己
属性在运行时的动态替换,叫做猴子补丁
作用是在运行的时候,动态替换模块方法。
举例:
class SomeClass(object):
def __init__(self):
self.name = "yoyo"
def speak(self):
return "hello world"
在不改变原来代码的基础上,可以重新定义一个speck方法,替换原来的
def new_speak(self):
return "new hello"
SomeClass.speak=new_speak
替换之后,调用的时候,就会变成新的方法里面内容
some1=SomeClass()
print(some1.speak())
new hello
a={i:i for i in range(1,10)}
print(a)
class A:
def __init__(self):
print("A")
class B(A):
def __init__(self):
print("B")
super().__init__()
class C(A):
def __init__(self):
print("C")
super().__init__()
class D(B, C):
def __init__(self):
print("D")
super().__init__()
D()
print(D.__mro__)
执行结果:
D
B
C
A
class A:
def test(self):
print('A')
class B:
def test(self):
print('B')
class C(A, B):
def __init__(self):
super().test() # 调用A类中的test方法
super(C, self).test() # 调用A类中的test方法
super(A, self).test() # 调用B类中的test方法
C()
print(C.__mro__)
执行结果:
A
A
B
类方法:对象和整个类都可以调用,需要装饰器修饰,第一个参数时cls
实例方法:对象的方法,整个类不可以调用,第一个参数为self
静态方法:整个类和对象都可以调用,不用传递参数,方便管理,需要装饰器进行修饰
class P:
def __init__(self,name,age):
self.name=name
self.age=age
if __name__ == '__main__':
p=P('kobe',19)
print(p.__dict__)
for index,value in enumerate(p.__dict__):
print('序号{},属性{}'.format(index,value))
dir§:查看所有的属性和方法
https://blog.csdn.net/YZL40514131/article/details/120053124
单例模式
PO模式
数据驱动模式
工厂模式
装饰器模式
init
new
str
repr
getattr
add
del
iter
next
call
python采用的是引用计数机制为主,标记-清除和分代收集(隔代回收)两种机制为辅的策略
一个变量指向了内存地址,引用计数为1
两个变量同时指向了一个内存地址,引用计数为2
a=4553223
a=4553223
b=a
c=[a]
c.append(a)
print(sys.getrefcount(a))
del a
def test():
b=667787
test()
函数执行完函数中的引用计数为0,可以进行回收
a,当一个对象的引用计数归零时,它将被垃圾回收机制处理掉。
b,当两个对象a和b相互引用时,del语句可以减少a和b的引用计数,并销毁用于引用底层对象的名称。然而由于每个对象都包含一个对其他对象的应用,因此引用计数不会归零,对象也不会销毁。(从而导致内存泄露)。为解决这一问题,解释器会定期执行一个循环检测器,搜索不可访问对象的循环并删除它们。
举例:v1和v2互相引用,把v1和v2进行del
v1 = [1, 5, 6]
v2 = [6, 9, 2]
v1.append(v2)
v2.append(v1)
del v1
del v2
v1和v2对象被干掉了,但是堆内存中有相互引用,引用计数位为1;可是没有变量去接收,这些内存地址程序员想用都不能用到,并且还占用内存。解决办法就是用标记清除。
c、标记清除
在python的底层中,再去维护一个链表,这个链表中专门放那些可能存在循环引用的对象。
标记清除算法是一种基于追踪回收 技术实现的垃圾回收算法。它分为两个阶段:第一阶段是标记阶段,GC会把所有的『活动对象』打上标记,第二阶段是把那些没有标记的对象『非活动对象』进行回收。
d、分代回收(帮我们回收循环嵌套的引用)
因为, 标记和清除的过程效率不高。清除非活动的对象前它必须顺序扫描整个堆内存,哪怕只剩下小部分活动对象也要扫描所有对象。还有一个问题就是:什么时候扫描去检测循环引用?
为了解决上述的问题,python又引入了分代回收。分代回收解决了标记清楚时什么时候扫描的问题,并且将扫描的对象分成了3级,以及降低扫描的工作量,提高效率。
0代: 0代中对象个数达到700个(阈值),扫描一次。
1代: 0代扫描10次,则1代扫描1次。
2代: 1代扫描10次,则2代扫描1次。
对于Python对象,以下几种情况,都有其独立的私有内存池。(字符串的驻留机制)
1、字符串长度为0或者1
2、符合标识符的字符串(只包含字母数字下划线)
3、字符串只在编译时进行驻留,而非运行时
4、[-5,256]之间的整数数字
答案是 No。每当python退出时,尤其是那些对其他对象具有循环引用的Python模块或者从全局名称空间引用的对象并不总是被解除分配或释放。由于python拥有自己的高效清理机制,无法解除分配保留的那些内存部分会在退出时尝试取消分配/销毁其他所有对象。在 Python 退出时并非完全释放。
1、生成器、迭代器
2、减少循环次数
3、if elif else
4、多线程起步
15. 简述python引用计数机制 (重要)
找对应的作用域关系。查找顺序为: 局部—> 全局 — > NameError
1、内存中加载的数据量过于庞大,如一次从数据库取出过多数据;
2、代码中存在死循环或循环产生过多重复的对象实体。
3、使用的第三方软件中的BUG; 一般引用第三方jar包过多会出现此类问题。
4、启动参数内存值设定的过小
5、集合类中有对对象的引用,使用完后未清空,产生了堆积,使得JVM不能回收;
处理:
第一步,修改JVM启动参数,直接增加内存(-Xms,-Xmx参数一定不要忘记加)
第二步,检查错误日志,查看“OutOfMemory”错误前是否有其 它异常或错误
第三步,对代码进行走查和分析,找出可能发生内存溢出的位置