Python知识总汇
python2和python3 的差别
python2:
print('abc') print 'abc' 两种方式都是都可以
range() xrange() 生成器
raw_input() 用户交互
python3:
print('abc')
range() 生成器
input() 用户交互
其他知识:
= 赋值
== 比较值是否相等
is 比较,比较的是内存地址
id(内容) 打印该内容的内存地址
小数据池:为了节省内存空间,数字和字符串在小范围内可共用一个对象
1,数字,字符串有小数据池
数字小数据池的范围 -5 -- 256
字符串:1,不能有特殊字符
2,s*20 还是同一个地址,s*21以后都是两个地址
i1 = 6
i2 = 6
print(id(i1),id(i2)) #两个id内存地址一样,属于小数据池
i1 = 300
i2 = 300
print(id(i1),id(i2)) #两个id内存地址不一样,不属于小数据池
2,剩下的 list dict tuple set 不具有小数据池
l1 = [1]
l2 = [1]
print(l1 is l2) ------>False
深浅copy
a = [11,22] b = [33,44] c=[a,b]
d = c:是将这个新的变量指向之前那个数据的内存地址,d,c的d is c --> Ture,内存地址一样,只是指向之前的内存地址。
e = copy.copy(c) # e和d的内存地址不一样,copy是开辟了一个新空间,但是e[0] ,e[1]的内存地址和c[0],c[1]一样,所以copy的方式只是开辟了一个新内存地址,里面的元素任然是指向之前的元素,就会随着之前的元素改变而改变,即为浅copy
f = copy.deepcopy(c) # f和c的内存地址不一样,f[0],f[1]和c[0],c[1]的内存地址也不一样,完全复制了一份数据,独立于之前的元素,即为深copy。
浅copy,只对表层数据起作用,对嵌套的数据不起作,会随着嵌套内数据的改变而改变
#没有嵌套的列表
# l1 = [1,2,3]
# l2 = l1.copy()
# print(l1,l2)
# print(id(l1),id(l2)) # l1和l2的内存地址不一样
# l1.append('a')
# print(l1,l2) #对l1操作不会影响l2的值
#嵌套的列表
# l1 = [1,2,[4,5,6],3]
# l2 = l1.copy()
#
# print(l1,id(l1)) #1812439743240
# print(l2,id(l2)) # 1812435321608 l1和l2的内存地址不一样
# l1.append('a')
# print(l1) #[1, 2, [4, 5, 6], 3, 'a']
# print(l2) #[1, 2, [4, 5, 6], 3]
# l1[2].append('a')
# print(l1) #[1, 2, [4, 5, 6, 'a'], 3]
# print(l2) #[1, 2, [4, 5, 6, 'a'], 3]
# print(id(l1[2])) #2236254917896
# print(id(l2[2])) #2236254917896 l1[2],l2[2]的内存地址相同
#对列表l1里面嵌套的列表的数值进行操作会改变l2的值
深copy,对于copy出来的内容完全独立,是一个不受父本影响的新的数据容器
# import copy
# l1 = [1,2,[4,5,6],3]
# l2 = copy.deepcopy(l1)
# print(l1,id(l1)) #[1, 2, [4, 5, 6], 3] id: 1741159826824
# print(l2,id(l2)) #[1, 2, [4, 5, 6], 3] id:1741159827336
# l1[2].append('a')
# print(l1) #[1, 2, [4, 5, 6, 'a'], 3]
# print(l2) #[1, 2, [4, 5, 6], 3] 深copy不会在受影响
# l1 = [1,[1],2,3,4]
# l2 = l1[:] #为浅copy
# print(l2)
# l1[1].append('a')
# print(l1) #[1, [1, 'a'], 2, 3, 4]
# print(l2) #[1, [1, 'a'], 2, 3, 4]
闭包:如果在一个内部函数里,对在外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是闭包
a = 1
def outer(a):
def inner():
print(a)
inner()
outer(a)
装饰器:一个函数需要扩展功能,但要遵循封闭开放原则,不能对原函数进行修改,装饰器的存在就是为了在不修改函数的调用方式和代码。就是对函数的装饰,使其在不被修改的原则下有新功能
def wapper(func): #装饰器
def inner(*args,**kwargs): #可以接受任何的参数
res = func(*args,**kwargs)
return res #返回的是my_sum的结果
return inner #返回inner,切记不可写inner()
@wapper #语法糖 相当于 my_sum = my_sum(1,2)
def my_sum(a,b): #被装饰函数
sum1 = 0
sum1= a + b
return sum1
sum = my_sum(1,2) #inner(1,2)
print(sum)
装饰器固定模式:
def wrapper(func): #func == qqxing
def inner(*args,**kwargs):
ret = func(*args,**kwargs) #被装饰的函数
return ret
return inner
@wrapper #qqxing = wrapper(qqxing)
def qqxing():
print(123)
ret = qqxing()
装饰器的进阶:
带参数的装饰器:
#带参数的装饰器需要嵌套三个函数,外层函数可以用来控制是否需要执行装饰器装饰函数的功能
falg = True #控制是否执行装饰器,False表示不执行
def log_sum(falg):
def wrappers_sum(func):
global falg
def inner(*args,**kwargs):
global falg
if falg:
print('----------------')
ret = func(*args,**kwargs)
print('----------------')
#falg = False #多个函数用装饰器的时候,只让其使用一次,再一次功能中登陆账号后,后面再调其他函数时就不需要重新登陆
return ret
else:
ret = func(*args,**kwargs)
return ret
return inner
return wrappers_sum
@log_sum(falg) #log_sum(falg) --->wrappers_sum 先执行log_sum(falg) 得到@wrappers_sum 就是一个装饰器
def my_sum(a,b):
sum = 0
sum = a + b
print('good')
return sum
print(my_sum(1,2))
@log_sum(falg)
def good():
print('sss')
good()
多个装饰器装饰一个函数:
#多个装饰器装饰一个函数
# def wrapper1(func):
# def inner1():
# print('wrapper1 ,before func')
# ret = func()
# print('wrapper1 ,after func')
# return ret
# return inner1
# def wrapper2(func):
# def inner2():
# print('wrapper2 ,before func')
# ret = func()
# print('wrapper2 ,after func')
# return ret
# return inner2
# def wrapper3(func):
# def inner3():
# print('wrapper3 ,before func')
# ret = func()
# print('wrapper3 ,after func')
# return ret
# return inner3
# @wrapper3
# @wrapper2
# @wrapper1
# def f():
# print('in f')
# return '哈哈哈'
# print(f())
打印结果:
wrapper3 ,before func wrapper2 ,before func wrapper1 ,before func in f wrapper1 ,after func wrapper2 ,after func wrapper3 ,after func 哈哈哈
迭代器:
可迭代对象可以使用双下函数来变成一个迭代器。迭代器的优点是可以一个一个的拿出容器中的数据,且可以节约内存空间
可迭代对象有 list tuple str set dict
list = [1,2,3,4] list1 = list.__iter__() #将可迭代对象变为迭代器 print(list1.__next__()) #一个一个去出容器中的数值
迭代对象中有 __iter__函数
迭代器中有__iter__和__next__函数
可以使用dir(数据类型)来看它有哪些双下划函数 如里面有__iter__函数则说明该i数据类型是可迭代对象
可以使用dir(数据类型)来看它有哪些双下划函数 如里面有__iter__和__next__函数则说明该i数据类型是可迭代器
可迭代的对象就可以被for循环来遍历
生成器:
本质:就是一个迭代器
优点:1.节省内存空间
2.好操作,可以一个一个取值,不重复取值
生成器函数:只要有yield关键字的函数就是一个函数表达式
def good(): #good()为一个生成器函数
yeild 'good' #yield 返回值,与return一样,但是不会终止函数
g = good() #调用生成器函数 ,返回一个生成器(g)
生成器取值:
print(g.__next__()) #一个一个的取出生成器的值,每次生成一个不占内存,且取过的值不再取不重复,如果取完了里面的值再次取会报错
for i in g:
print(i) #一次性取出全部的值
a = list(g) #类型强制转换,将生成器中的值全部转换为列表元素,一次取完
生成器表达式
列表推导式:
[每一个元素或者是和元素相关的操作 for 元素 in 可迭代数据类型] #遍历之后挨个处理
[满足条件的元素相关的操作 for 元素 in 可迭代数据类型 if 元素相关的条件] #筛选功能
list1 = [i for i in range(10)] #列表推导式,操作方便 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
list = (i for i in range(10) if i>=5) #list为列表
print(list) #[5,6,7,8,9]
生成器表达式
(每一个元素或者是和元素相关的操作 for 元素 in 可迭代数据类型) #遍历之后挨个处理
(满足条件的元素相关的操作 for 元素 in 可迭代数据类型 if 元素相关的条件) #筛选功能
list = (i for i in range(10) if i>=5) #list为生成器 list.__next__() #5 list.__next__() #6 list.__next__() #7
生成器的进阶: send的取值作用与__next__()一样,只是在获取下一个值的时候,给上一yield的位置传递一个数据
***不能直接再开头使用send取值,因为没有yield可以给赋值,回报错
***也不可以在最后用send,最后一个yield不可以接受赋值
# 获取移动平均值 # avg = sum/count # def average(): # sum = 0 # count = 0 # avg = 0 # while True: # num = yield avg # sum += num # 10 # count += 1 # 1 # avg = sum/count # # avg_g = average() # avg_g.__next__() # avg1 = avg_g.send(10) # avg1 = avg_g.send(20) # print(avg1)
#装饰器和生成器的获取移动平均值
def wrappers(func): #func -->avg_func 该装饰器就是为了第一次使用send不用写__next__
def inner(*args,**kwargs):
ret = func(*args,**kwargs) # ret是一个生成器
ret.__next__() #使用send之前必须先使用__next__()
return ret
return inner
@wrappers #avg_func = wrappers(avg_func)
def avg_func():
sum = 0
count = 0
avg = 0
while 1:
num = yield avg
sum += num
count += 1
avg = sum / count
avg_g = avg_func() #avg_g 是一个生成器 此时avg_func()是inner() 所以返回值为ret即一个生成器
print(avg_g.send(10)) #10.0
print(avg_g.send(20)) #15.0
浙公网安备 33010602011771号