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

posted on 2019-11-07 21:05  猪·sea  阅读(119)  评论(0编辑  收藏  举报

导航