zoukankan      html  css  js  c++  java
  • 学习python第四天

    一、闭包

    二、装饰器

    三、迭代器

    四、生成器

    五、函数面相过程

    六、三元表达式

    七、序列化

    一、闭包

    什么是闭包:

    返回的函数对象,不仅仅是函数对象,在该函数外还包裹了一层作用域,这使得,该函数无论在何处调用,优先使用自己外层包过的作用域

    应用领域:延迟计算(原来我们是传参,现在我们是包起来)

    from urllib.request import urlopen

    def index(url):
      def get():
        return urlopen(url).read()
      return get
    baidu=index('http://www.baidu.com')
    print(baidu().decode('utf-8'))

    二、装饰器

    什么是装饰器:

    装饰器他人的器具,本身同样是函数的形式,被装饰者,同样是函数的形式

    装饰器的原则:

    1.不修改被装饰对象的源代码

    2.不修改被装饰对象的调用方式

    1)无参装饰器

    import time
    def timel(func): #设置参数便于出入index函数
    def webapper(*args,**kwargs):#设置接收所有多余的参数
    start_time=time.time()
    res=func(*args,**kwargs)设置res为调用函数的返回值
    stop_time=time.time()
    print("stop time %s" % (start_time-stop_time))
    return res 返回res
    return webapper 返回值设置
    @timel #@timel= index=timel(index) 整下方必须是被装饰体
    def index():
    time.sleep(3)
    print('from index')

    index() 在不改变源代码和调用方式的情况下调用变量

    2)有参装饰器

    def auto(driver='file'): #装饰器中自带参数driver
    def auto2(func):
    def webapper(*args,**kwargs):
    name=input('name:')
    passwd=input('passwd:')
    if driver == 'file':
    if name == 'sunjingguo' and passwd == '123':
    print('login ok')
    res=func(*args,**kwargs) #这里的*,**替代了foo函数中的name,没有的话会报错,确保foo函数从inprint中调取name的值
    return res
    elif driver == 'ldap':
    print('mysql')
    return webapper
    return auto2
    @auto()#参数中自带默认值,可以不填写参数
    def foo(name):
    print(name)
    foo('sunjingguo')

    3)装饰器语法

    被装饰函数的正上方,单独一行
    @deco1
    @deco2
    @deco3
    def foo():
    pass

    foo=deco1(deco2(deco3(foo)))

    练习题:

    编写装饰器,为多个函数加上认证的功能(用户的账号密码来源于文件),要求登录成功一次,后续的函数都无需再输入用户名和密码
    注意:从文件中读出字符串形式的字典,可以用eval('{"name":"egon","password":"123"}')转成字典格式

    def auto(func):
    def webapp(*args,**kwargs):
    file='userinfo.txt'
    name=input('user name: ')
    passwd=input('passwd: ')
    with open('userinfo.txt',encoding='utf-8') as read_f:
    dic=eval(read_f.read()) #eval函数时间字符串转化为列表,字典,元组。前提是字符串是相同格式存储方式
    if name in dic and passwd == dic[name]:
    print('login ok')
    res=func(*args)
    return res
    return webapp
    @auto
    def index():
    print('index')
    @auto
    def home(name):
    print('welcome %s to home' %name)
    home('sunjingguo')#设定函数时,添加了形参,所以调用时也需要添加参数

    阿道夫

    三、迭代器

    迭代器的概念:

    迭代是个重复的过程,每次重复及时一次迭代,并且每次迭代的结果都是下次迭代的初始值

    迭代器使用的场景:

    针对序列类型:字符串,列表,元组取值时我们可以通过下标值来获取相应的值,但对字典,集合,文件这些无序的类型,就没有什么办法了,只能通过迭代器来获取相关的值了。

    什么是可迭代对象:

    可迭代对象是指内置有_iter_方法的对象,即“hello”._iter_

    字符串,元组,列表,字典,文件都属于可迭代对象

    什么是迭代对象:

    可迭代对象执行‘hello’._iter_方法后得到的结果就是迭代对象

    迭代对象具有内置_iter_和_next_方法的,就是迭代对象

    注意:

    迭代对象一定是可迭代对象,可迭代对象不一定是迭代对象

    2)迭代器对象的使用

    dic={'a':1,'b':2,'c':3}
    iter_dic=dic.__iter__() #得到迭代器对象,迭代器对象即有__iter__又有__next__,但是:迭代器.__iter__()得到的仍然是迭代器本身
    iter_dic.__iter__() is iter_dic #True

    print(iter_dic.__next__()) #等同于next(iter_dic)
    print(iter_dic.__next__()) #等同于next(iter_dic)
    print(iter_dic.__next__()) #等同于next(iter_dic)
    # print(iter_dic.__next__()) #抛出异常StopIteration,或者说结束标志

    #有了迭代器,我们就可以不依赖索引迭代取值了
    iter_dic=dic.__iter__()
    while 1:
      try:     #定义捕捉异常
        k=next(iter_dic)
        print(dic[k])
      except StopIteration:     #指定捕捉到异常后的操作
        break

    for 循环的原理与上述问题类似;

    先执行dic._iter_()方法将可迭代对象变成迭代对象,后执行next(iter_dic)将得到的值附给循环变量,执行循环体。重复上述操作,直到try捕捉到stoplteration后为止,结束循环。

    3)迭代器的优缺点:

    优点:

    提供了一种统一的,不依赖与索引的迭代方式

    逐条赋值,节省内存空间

    缺点:

    无法获取长度(只有在next完毕后才知道对象有几个值)

    每次循环,只能依次循环不能回退

    四、生成器

    什么是生成器:

    只要函数内部包括yield关键字,那么执行函数的结果就是生成器,并且不会执行函数内部代码,生成器包含迭代器的特性,所以生成器就是迭代器所以生成器取值的方式与迭代器相同。

     练习:

    1、自定义函数模拟range(1,7,2)

    def my_range(start,stop,step):
    while start < stop:
    yield start
    start+=step
    res=my_range(1,9,2)
    print(next(res))
    print(next(res))
    print(next(res))

    2、模拟管道,实现功能:tail -f access.log | grep '404'

    import time
    def tail(filepath): #设置函数
    with open(filepath,'rb') as read_f: #以RB的方式打开文件
    read_f.seek(0,2) #将鼠标移到文件最后,0表示移动多少位,2,表示从文件结尾开始(0表示从文件开头开始,1,表示从当前位置开始,2,表示从文件末尾开始)
    while True:
    line=read_f.readline() #line等于每行的内容,现在line的形式是字节的形式
    if line: #如果line中有值
    yield line #将line的值返回
    else:
    time.sleep(0.2)
    def grep(pattern,lines):
    for line in lines:
    line=line.decode('utf-8')
    if pattern in line:
    yield line
    for line in grep('404',tail('access.log')): #订制循环将上述函数传值
    print(line,end='')

    3)yield关键字传值

    def eater(name):
    print('%s 准备开始吃饭啦' %name)
    food_list=[]
    while True:
    food=yield food_list
    print('%s 吃了 %s' % (name,food))
    food_list.append(food)

    g=eater('egon')
    g.send(None) #对于表达式形式的yield,在使用时,第一次必须传None,g.send(None)等同于next(g) 第一步初始化参数,否则会有相应的错误提示
    g.send('蒸羊羔')
    g.send('蒸鹿茸')
    g.send('蒸熊掌')
    g.send('烧素鸭')
    g.close() 传值结束,关闭

    总结yield

    1.可以将函数做成迭代器

    2.对比return,可以返回多次值,可以保存函数的运行状态

     五、函数面相过程

    #1、首先强调:面向过程编程绝对不是用函数编程这么简单,面向过程是一种编程思路、思想,而编程思路是不依赖于具体的语言或语法的。言外之意是即使我们不依赖于函数,也可以基于面向过程的思想编写程序

    #2、定义
    面向过程的核心是过程二字,过程指的是解决问题的步骤,即先干什么再干什么

    基于面向过程设计程序就好比在设计一条流水线,是一种机械式的思维方式

    #3、优点:复杂的问题流程化,进而简单化

    #4、缺点:可扩展性差,修改流水线的任意一个阶段,都会牵一发而动全身

    #5、应用:扩展性要求不高的场景,典型案例如linux内核,git,httpd

    #6、举例
    流水线1:
    用户输入用户名、密码--->用户验证--->欢迎界面

    流水线2:
    用户输入sql--->sql解析--->执行功能

    六、三元表达式

    name=input('name')
    res='NB' if name == 'sunjingguo' else 'SB' #三元表达式只针对简单的if判断形势,正确的值放在表达式的左侧,其余条件放在右侧
    print(res)

    egg_list=['egg%s' %i for i in range(10)]

    [expression for item1 in iterable1 if condition1
    for item2 in iterable2 if condition2
    ...
    for itemN in iterableN if conditionN
    ]
    类似于
    res=[]
    for item1 in iterable1:
    if condition1:
    for item2 in iterable2:
    if condition2
    ...
    for itemN in iterableN:
    if conditionN:
    res.append(expression)

    #3、优点:方便,改变了编程习惯,可称之为声明式编程



  • 相关阅读:
    Pandas: 如何将一列中的文本拆分为多行? | Python
    Python项目实战:福布斯系列之数据采集
    Python: Pandas运算的效率探讨以及如何选择高效的运算方式
    Pandas数据处理实战:福布斯全球上市企业排行榜数据整理
    从历史来看印度的裂痕和隐忧 | 阅览群书
    Python库:序列化和反序列化模块pickle介绍
    无法加载 DLL“SQLite.Interop.DLL”: 找不到指定的模块。 (异常来自 HRESULT:0x8007007E)。
    spring 问题笔记
    java 大量数据处理问题记录
    spring mvc 整合swagger
  • 原文地址:https://www.cnblogs.com/sunjingguo/p/7597118.html
Copyright © 2011-2022 走看看