首页 > 代码库 > 函数+装饰器+迭代器+生成器

函数+装饰器+迭代器+生成器

闭包函数
闭包:定义在内网函数,包含对外部作用域而非全局作用域
范围:一个函数套用1或n个函数
from urllib.request import urlopen  #urlopen模块 作用:爬网页
#闭包函数,内部get函数调用外部page函数
def page(url):                                  #调用url
    def get():                                  #下载
        return urlopen(url).read()              #爬网页
    return get                                  #返回url值
baidu=page("http://www.baidu.com")              #函数page的值,手动写的url(url可变)
#print(baidu.__closure__[0].cell_contents)      #看oldboy函数包裹的元素
#print(baidu.__closure__)                       #看oldboy函数有几个值
print(baidu())                                  #显示百度网页
 
#如下效果相同,不是闭包函数,不灵活,(不能写baidu=page("http://www.baidu.com")的形式,)
def get(url):                       #下载
    return urlopen(url).read()
print(get("http://www.baidu.com")) #定义url    
#显示返回网页

装饰器
装饰器:装饰代码
必须遵守2个原则
最好不要修改源代码
最好不要修改调用方式
调用方式
functools模块(保存源代码的注释,更新到装饰后的程序)
import time
def timer(func):                    #func相等于index
    def wrapper(*args,**kwargs):    #wrapper等于indiex 所有要赋值
        start_time=time.time()      #计算第一次执行时间
        res=func(*args,**kwargs)    #定义func的值给res
        stop_time=time.time()       #计算第二次执行时间
        print("run time is %s" %(start_time-stop_time))
        return res                   #定义子函数的返回值
    return wrapper                  #返回子函数的值
@timer                  #index=timer(index) 注:把正下方的函数值给timer
def index():
    time.sleep(3)                    #沉睡3秒
    print("welcome to index")
index()    #显示是装饰后的值
#3秒后显示如下
#welcome to index
#run time is -3.0002331733703613
(函数增加功能,用户认证通过后执行函数,否则提示报错信息)
def Gavin(guolm):
    aa = ["guolm", "admin_1234"]
    def wrapper(*args,**kwargs):
        select= input("peales your writer your user>>>:")
        if select==aa[0]:
            print("ok")
            select1 = input("peales your writer your pass>>>:")
            if select1 ==aa[1]:
                res=guolm(*args,*kwargs)
                return res
            else:
                print("pass error")
        else:
            print("user error")
    return wrapper
@Gavin
def guolm():
    print("hello man")
    return guolm
guolm()                            #相当guolm= Gavin(guolm) 获取

用户认证+第二次不需要输入认证信息
logon_user={"user":None,STATUS:False}
def auth2(driver="file"):
    def ahth(func):
        def wrapper(*args,**kwargs):
            if driver=="file":
                if logon_user["user"] and logon_user["status"]:   #如果user有值并且statis是True,继续执行,#注释第一遍执行时,值不存在,所以执行else,第二次循环则成立
                    res=func(*args,**kwargs)                      #定义了函数func可n个元组,列表和n个字典
                    return res                                    #第三层函数的返回值
                else:
                    name=input(">>>:")
                    password=input(">>>:")
                    if name == "egon" and password == "123":    #如果认证成立继续执行
                        logon_user["user"]="egon"               #改变logon_user的user值, 为上个if判断做铺垫
                        logon_user["status"]=True               #改变logon_user的status值,为上个if判断做铺垫
                        res=func(*args,**kwargs)
                        return res                              #第三层函数的返回值
                    else:
                        print("error")
            elif driver == "mysql":
                print("show mysql")
                return func(*args,**kwargs)
            elif driver=="ldap":
                print("=====ldap认证")
            else:
                print("无效认证")
        return wrapper
    return  ahth
@auth2("file")                                  #index函数值为file,执行如下函数#相当于调用auth2下的ahth下的wrapper函数
def index():
    print("welcome to index page")
@auth2(driver="mysql")                          #home("egon")函数值为mysql,执行如下函数
def home(name):                                 #相当于调用auth2下的ahth下的wrapper函数
    print("%s welcome to home page" %name)      #name是 输入home("egon")的传参 就是egon
index()         #wrapper
home("11")       #输入11也能实现 有点不懂

迭代器
为什么要有迭代器?    对于没有索引的数据类型,必须提供一种不依赖索引的迭代方式
迭代的概念:    每次执行的结果作为下一次迭代的初始值
优点 : 提供一种不依赖下标的迭代方式,且迭代器更省内存空间(因为每次读取1行)
缺点:  不能获取迭代器对象的长度,且不如序列类型取值灵活,是一次性的,只能向后取值,不能向前
for循环也属于迭代器

可迭代的对象: 能执行.__iter__()方法为True
迭代器对象:能执行.__iter__()方法为True和执行__next__()是方法为True
可迭代对象: 只有__iter方法, 执行该方法可得到迭代器对象,只有可使用__next__方法

#数字不是迭代对象
#只是文件是迭代器,其他都可迭代对象

[1,2].__iter__()                #列表
"hello".__iter__()              #字符串
(1,2,).__iter__()               #元组
{"a":"1","b":"2"}.__iter__()    #列表
{1,2,3}.__iter__()              #集合

f=open("a.txt","w")          #文件
f.__iter__() 
#判断是否为可迭代对象
print(isinstance([1,2],Iterable))                 #返回True
print(isinstance("hello",Iterable))               #返回True
print(isinstance((1,2,),Iterable))                #返回True
print(isinstance({"a":"1","b":"2"},Iterable))    #返回True
print(isinstance({1,2,3},Iterable))                #返回True
print(isinstance(f,Iterable))                #返回True
#判断是否为迭代器对象
print(isinstance([1,2],Iterator))                 #返回False
print(isinstance("hello",Iterator))               #返回False
print(isinstance((1,2,),Iterator))                #返回False
print(isinstance({"a":"1","b":"2"},Iterator))    #返回False
print(isinstance({1,2,3},Iterator))               #返回False
print(isinstance(f,Iterator))                      #返回True

例如:
iter确定是迭代器  next取出值
i=[1,2,4].__iter__()

print(i)
print(i.__next__())                            #列表的值有3个 执行next每次只能取一个值
print(i.__next__())
print(i.__next__())
print(i.__next__())                            #因为只有3个值,执行4个会报错
#####
<list_iterator object at 0x0000003FC1E0E2E8>   #迭代器的内存地址 
1
2
4
或
dic={"a":1,"b":2,"c":3,}
i=dic.__iter__()            #确定dic可迭代
while True:
    try:                    #尝试实现如下信息
        key=i.__next__()    #迭代i的值给key
        print(dic[key])
    except StopIteration:   #except是抛出异常 遇到异常StopIteration,执行break
        break
 

生成器yield
yield的功能:
1    使用yield把函数变成迭代器 ,(相当于为函数封装好__iter__和__next__)
2    yield能返回多次,每次返回都会讲函数暂停,下一次next会从上一次暂停的位置继续执行,而return返回一次值,函数就终止

生成器操作
def foo():
    print("first")
    yield 1         #之前的值
    print("second")
    yield 2
    print("fifth")
g=foo()
print(g)            #看g的内存地址
print(next(g))
print(next(g))
#print(next(g))   #因为fifth没有加生成器yield 使用迭代器执行会保存
#或如下执行
for i in g:
    print(i)

生成器中使用计数器
def counter(n):
    print("start")
    i = 0
    while i< n :
        yield i
        i+=1
    print ("end")
g=counter(3)        #g是函数调用

for i in g:          #for循环显示生成器的值
    print(i)
#显示
start
0
1
2
end
显示文件,执行内容
#1,创建a.txt文件
#2执行python
#3,在db文件中输入值,最后一行开始计算,包含python的行会显示,不包含的行不显示
import time             #时间模块
def tail(file):
    with open(file,encoding="utf-8") as f:  #读取file(函数1定义的file),读取为utf-8
        f.seek(0,2)                         #文件最尾部操作
        while True:
            line=f.readline().strip()
            if line:                      #如果line值成立,则...
                yield line                #返回line值,并再次从新执行函数
            else:
                time.sleep(0.2)           #沉睡0.2秒
def grep(pattern,lines):                  #定义了2个参数
    for i in lines:
        if pattern in i:                  #pattern相当于python
            print(i)
g=grep("python",tail("a.txt"))          #g= grep函数的第二个参数是tail函数和tail调用文件,a.txt可改
for i in g:                             #循环显示值
    print(i)

 

1.    名称空间与作用域

1. 全局作用域:      

    范围: 内置名称空间,全局名称空间
    有效期:全局有效,在任何地方都可用, 不删除长期有效
    查找顺序:         局部名称空间 -->全局名称空间-->内置名称空间
    x=1000
    def func():
    x=1
    def f1():
    pass
     
    print(globals()) #显示全局变量中定义的名称空间的名字
    print(locals()) #在全局中是看全局,在局部中是看局部
     
    print(globals() is locals() )
    #True              #说明此时在全局名称空间

 

1.1    内置名称空间

(随着python解释器的启动而产生)

    print(sum)
    #<built-in function sum>    #内置函数
     
    import builtins            #查看内置参数的模块
    for i in dir(builtins): #查看有哪些内置函数
    print(i)

 


1.2.    全局名称空间

在全局变量中定义的名称空间
    #文件执行会产生全局名称空间,指定是文件级别定义的名字都会放入改空间
    #如下全是全局定义, 如下有小区别
     
    import time #模块级别定义
    name="guolm" #文件级别定义
    def func(): #函数级别定义
    print("hello man")
    print(func())
    class foo: #类级别定义
    pass

 

2. 局部作用域:

 
    范围:    局部名称空间
    有效期:局局有效,在局部可用, 函数调用时有效,调用结束后失效
    查找顺序:         局部名称空间 -->全局名称空间-->内置名称空间
    x=1000
    def func(c):
    x=2
    print(locals())     #查看局部名称空间
    func(1)
    {x: 2, c: 1}        #这是局部名称空间

 

2.1.   局部名称空间

在调用函数时,会产生局部名称空间,只在函数调用时有效,函数结束时失效
    def func():
    x=1            #局部名称空间
    def f1():
    pass

 

 

递归 

最大递归层次 999层
    def calc(n):    #整除到1
    print(n)
    if int(n/2) >0:
    calc(int(n/2))
    print(n)
    print(calc(10))

 

 
递归 2分查找 (从N个有序数据中找到想要的值,注:无序不能查找)
    #data = http://www.mamicode.com/[ 1,2,4,6,7,8,9,11,14,16,18,19,20,22,25,29]
    data = http://www.mamicode.com/range(1,4200000000)
    def binary_search(find_str,data_set,count):
    mid = int(len(data_set)/2)
    if mid==0:#代表列表只剩下一个值了,没必要继续找了
    if data_set[mid] == find_str:
    print("find it finally",find_str,count)
    else:
    print("cannot find this num in list",find_str,count)
    return
    if data_set[mid] == find_str:
    print("find it",find_str,mid)# find_str in left side
    elif data_set[mid] > find_str:
    print("going to search in left ",data_set[mid],data_set[0:mid])
    binary_search(find_str,data_set[0:mid],count+1)
    else:#find_str in right side
    print("going to search in right ",data_set[mid], data_set[mid+1:])
    binary_search(find_str, data_set[mid+1:],count+1)
    binary_search(13354245, data,0)

 

1 内置函数
      1. type    判断类型
      2.     name =("a","b")
            print(type(name)) #看name类型 获取类
            #<class ‘tuple‘>
      3. bool(name)            0 空格,None都是False,其他都是True
      4.     name =("a","b")
            print(bool(name))

         

      5. len(name)               显示数据类型长度
      6. name =("a","b")
        print(len(name))

         

      7. abs()    #返回值为正数
      8.     print(abs(-1)) #返回1
            print(abs(2)) #返回2
            print(abs(-0.1)) #返回0.1

         

      9. all()    #判断为True或False
      10.     print(all([1,2,3,4,5])) #值为True
            print(all([1,0])) #值为False, 值包含0,None,空都为False,其他都为True
            print(all([])) #值为True, 注意这是特殊情况,

         

      11. 二,八,十,十六进制
      12.     >>>bin(10) 二进制
            0b1010
            >>> 10 十进制(默认)
            10
            >>> oct(10) 8进制
            0o12
            >>> hex(10) 16进制
            0xa a表示10 b表示11 以此类推

         

      13. callable    可调用对象
      14.     #不是函数就不可被调用返回False
            def func():
            pass
            print(callable(func)) #返回True

         

      15. chr和ord
      16.     ascii码是美国默认字符集编码
            print(chr(68)) #数字转换成ascii码 
            #D
            print(ord("D")) #ascii码转换数字
            #68

         

      17. dir 查看可用参数(权限) (有5种数据类型+set等)
      18.     b={"1":"2"}
            print(dir(b))

         

      19. divmod   用于分页功能
      20.     print(divmod(100,3)) #取整数+余数
            (33, 1)

         

      21. eval 把字符串里的命令或数据类型提取使用
      22.     #提取命令
            cmd=print("三哥威武")
            eval(cmd)
            #三哥威武
             
            提取数据类型
        
            #定义列表
            keys_one=[
            {"backend":"www.wy.org"},
            ["server","1.1.1.3","1.1.1.3",{"weight","20"},{"maxconn","3000"}],
            ["server","1.1.1.4","1.1.1.4",{"weight","20"},{"maxconn","4000"}],
            ]
            #把列表写入练习文件,
            with open("练习","w",encoding="utf-8") as f:
            f.write(str(keys_one)) #转成字符串形式写入 #文件写入只能是字符串形式
            with open("练习","r",encoding="utf-8") as f:
            dic=f.read()
            print(type(dic)) #字符串形式,(因为写入是就是字符串形式)
            dic=eval(dic) #使用eval提取出字符串中的数据类型,
            print(type(dic)) #列表类型
            print(dic[1]) #可以查询列表内容
        
             
             

         

      23. frozenset    定义不可变集合
      24.     s=frozenset({1,2}) #s=({1,2}) 这是可变集合
            s.add(3)
            print(s) #会报错 因为s现在是不可变集合

         

      25. format    字符串格式化
      26.     s="name:{},age:{},height:{}".format("guolm",23,"183")
            print(s)
            #name:guolm,age:23,height:183

         


      27. hash   获取哈希,(2个字符串相同,哈希值相同)
      28. #效果:校验的内容相同 返回的值就一致 
        #以后会用hash模块,略过
         
        print(hash("aaaaa"))
        print(hash("aaaaa"))
        -3564166969462102491
        -3564166969462102491

         

         
      29. id   取内存地址
      30.     #身份运算符
            x=1
            y=x
            print(id(x),id(y))
            #1508750464 1508750464
            print(x is y) #s 是 y
            #True

         

      31. pow 求余数
      32.     print(pow(10,2,6))
            #4
            #取余数 相当于10的2平方 除以6 得到的余数是4

         

      33. reversed 取反转结果
      34.     a=["a",2,3,4]
            for i in reversed(a):
            print(i)
            #显示的值是反向输出
            b=["a",2,3,4]
            print(list(reversed(b)))
            #[4, 3, 2, ‘a‘]    #list也是迭代器 所以值可以反转

         

      35. round 保留小数
      36.     one=round(3.14159,4) #最后4表示保留4位小数,第4位小数四舍五入计算
            print(one)
            #3.1416
            one=round(3.14159,3) #最后4表示保留4位小数,第4位小数四舍五入计算
            print(one)
            #3.142
        
            one=round(3.14159)    #不输入保留位数,默认保留整数
            print(one)
            #3

         

      37. zip #两个相同长度的字符串,元组,列表组合成字典
      38.     #2个不同类型也可以组合
            s=("hello")
            a=[1,2,3,4,5]
            z=zip(s,a)
            print(z)
            #<zip object at 0x0000004021D90608> z变成迭代器
            for i in z:
            print(i)

         

      39. __import__() #以字符串的形式导入模块
      40.     import time
            import time
            m=__import__("time")
            m.sleep(3) #沉睡2秒
            print("Gacvin Kwok is super man")

         

      41. sum 求和
      42.     a=sum([1,2,3,4]) #相当于1+2+3+4
            print(a)
            10

         

      43. bytearray 字符串改值(在原内存空间更改.不是删除后增加)
      44.     a="guolm 你好"
            print(ascii(a)) #ascii码
            a=a.encode() #改成utf-8格式
            b2=bytearray(a) #可直接修改字符串
            b2[0]=98 #这是g(字节)改成b(字节)
            print(b2)
            #‘guolm \u4f60\u597d‘
            #bytearray(b‘buolm \xe4\xbd\xa0\xe5\xa5\xbd‘)

         

      45. map 运算
      46.     a= map(lambda x:x*x,range(10)) #类似三元运算 实现x=x*x 显示每次结果 运算值是0-10
            #a= map(lambda x:x+1,range(10)) #类似三元运算 实现x=x+1 显示每次结果 运算值是0-10
            for i in a:print(i)

         

      47. reduce 运算求加,减,乘,除
      48.     from functools import reduce
            a= reduce(lambda x,y:x+y,range(10))  
            #计算0-9的总和 +号可改为 * / - range中的值也可改
            print(a)
            #45

         

      49. memoryview    在原内存空间直接修改数据
如下对比 memoryview比默认方式速度快的一个等级
import time
#默认方式 原内存空间垃圾回收,开辟新内存空间,
for n in (200000,400000):
data=b"x"*n
start = time.time()
b=data
while b:
b=b[1:]
print("memoryview",n,time.time()-start)
#memoryview 200000 1.3159432411193848 #表示1.3秒
#memoryview 400000 5.632980585098267   #表示5.6秒
print("========================================")
#memoryview在原内存空间直接修改
for n in (200000,400000):
data=b"x"*n
start = time.time()
b=memoryview(data)
while b:
b=b[1:]
print("memoryview",n,time.time()-start)
#memoryview 200000 0.04102897644042969 表示0.04秒
#memoryview 400000 0.08105683326721191 表示0.08秒

 

函数+装饰器+迭代器+生成器