• 函数复习


    1 什么是函数?
      函数就是具备某一个功能的工具,
        ----需要工具时,需要提前准备好,然后拿来就用且可以重复使用
      所以
        函数需要先定义,再使用


    2 为什么要用函数?
      1,代码的组织结构不清晰,可读性差
      2,遇到重复的功能只能重复编写实现代码,代码冗余
      3,功能需要扩展时,需要找出所有实现该功能的地方修改之,无法统一管理且维护难度极大

    
    
    3 函数的分类:内置函数与自定义函数
      内置函数:python解释器已经为我们定义好了的函数
      自定义函数:我们自己根据需求,事先定制好的我们自己的函数,来实现某种功
    4 如何自定义函数
     
      语法
      def 函数名(参数1,参数2,参数3.......):
          """注释"""
          函数体
          return 返回的值
      # 函数名要能反映其意义
      
      
      函数使用的原则:先定义,再调用
        函数即"变量","变量"必须先定义后引用。未定义而直接引用函数,就相当于在引用一个不存在的变量名
        函数的使用,必须遵循原则:先定义,后调用
       ###我们在使用函数时,一定要明确区分定义阶段和调用阶段###
        #定义阶段
          def foo():
            print('from foo')
            bar()
          def bar():
            print('from bar')
         #调用阶段
           foo()
    定义有参数函数,及有参函数的应用场景
      有参:需要根据外部传进来的参数,才能执行相应的逻辑,比如统计长度等
        def tell_tag(tag,n): #有参数
          print (tag*n)
    定义无参数函数,及无参函数的应用场景
      无参:应用场景仅仅只是执行一些操作,比如用户交互,打印
        def tell_msg(): #无参数
          print ('hello world') 定义空函数,及空函数的应用场景
       设计代码结构

     #结论:
      #1,定义是无参,意味着调用时也无需传入参数
      #2,定义是有参,意味着调用时则必须传入参数
     函数在定义阶段
        只检测语法,不执行代码
          --语法错误在函数定义阶段就会检测出来,而代码的逻辑错误只有在执行时才会知道
    5 调用函数 如何调用函数
        函数的调用:函数名加括号
          1,先找到名字
          2,根据名字调用代码
    函数的返回值
        无return--->None
        return 1个值->返回1个值
        return 逗号分隔多个值 -->返回元组
        
        什么时候该有返回值:
          调用函数,经过一系列的操作,最后拿到一个明确的结果,则必须要有返回值
          通常有参函数需要有返回值,输入参数,经过计算,得到一个最终的结果
      
        什么时候不需要有返回值:
          调用函数,仅仅只是执行一系列的操作,最后不需要得到什么结果,则无需有返回值
          通常无参函数不需要有返回值
       

      函数调用的三种形式
        1,语句形式:foo()
        2,表达式形式:3*len(’hello‘)
        3,当中另外一个函数的参数:range(len(’hello‘))
    函数参数的应用:
        形参和实参
          形参即变量名,实参即变量名,函数调用时,将值绑定到变量名上,函数调用结束,解除绑定
        
        位置参数
    按照从左到右的顺序定义的参数      位置形参:必选参数            位置实参:按照位置给形参传值

        
    关键字参数:按照key=value的形式定义的实参
          无需按照位置为形参传值
          注意的问题:
              1,关键字实参必须在位置实参后面
              2,对同一个形参不能重复传值
        默认参数:形参在定义时就已经为其赋值
          可以传值也可以不传值,经常需要变的参数定义成位置形参,变化较小的参数定义成默认参数(形参)
          注意的问题:
            1,只在定义的时候赋值一次
            2,默认参数的定义应该在位置形参右边
            3,默认参数通常应该定义成不可变类型
    可变长参数:
        可变长指的是实参值得个数不固定
        而实参有按位置和按关键字两种形式定义,针对这两种形式的可变长,形参对应有两种解决方案来完整的存放它们,
       分别是 *args,**kwargs(args,kwargs只是约定俗成的表示,没有特殊意义)
     ===========*args===========
            def foo(x,y,*args):
                print(x,y)
                print(args)
            foo(1,2,3,4,5)
    
            def foo(x,y,*args):
                print(x,y)
                print(args)
            foo(1,2,*[3,4,5])
    
    
            def foo(x,y,z):
                print(x,y,z)
            foo(*[1,2,3])
    
            ===========**kwargs===========
            def foo(x,y,**kwargs):
                print(x,y)
                print(kwargs)
            foo(1,y=2,a=1,b=2,c=3)
    
            def foo(x,y,**kwargs):
                print(x,y)
                print(kwargs)
            foo(1,y=2,**{'a':1,'b':2,'c':3})
    
    
            def foo(x,y,z):
                print(x,y,z)
            foo(**{'z':1,'x':2,'y':3})
    
            ===========*args+**kwargs===========
    
            def foo(x,y):
                print(x,y)
    
            def wrapper(*args,**kwargs):
                print('====>')
                foo(*args,**kwargs)
    
    

      命名关键字参数:

        * 后定义的参数,必须被传值(有默认值得除外),且必须按照关键字实参的形式传递

        可以保证,传入的参数中一定包含某些关键字

    def foo(x,y,*args,a=1,b,**kwargs):
                print(x,y)
                print(args)
                print(a)
                print(b)
                print(kwargs)
    
            foo(1,2,3,4,5,b=3,c=4,d=5)
            结果:
                1
                2
                (3, 4, 5)
                1
                3
                {'c': 4, 'd': 5
          
    6 高阶函数(函数对象)
      函数是第一类对象,即函数可以当做数据传递
      1,函数可以被引用
      2,函数可以当做参数传递
      3,函数的返回值可以是函数
      4,函数可以当做容器类型的元素
     
      利用这些特性,可以取代多分支的if
      
     1 def foo():
     2     print('foo')
     3 
     4 def bar():
     5     print('bar')
     6 
     7 dic={
     8     'foo':foo,
     9     'bar':bar,
    10 }
    11 while True:
    12     choice=input('>>: ').strip()
    13     if choice in dic:
    14         dic[choice]()
      
    7 函数嵌套
      函数的嵌套调用
        
    1 def max(x,y):
    2     return x if x > y else y
    3 
    4 def max4(a,b,c,d):
    5     res1=max(a,b)
    6     res2=max(res1,c)
    7     res3=max(res2,d)
    8     return res3
    9 print(max4(1,2,3,4))
        
    8 作用域与名称空间
      名称空间:存放名字的地方,三种空间:内置名称空间,全局名称空间,局部名称空间    存放的是名字和内存地址的对应关系
     名称空间的加载顺序
    python test.py
    #1、python解释器先启动,因而首先加载的是:内置名称空间
    #2、执行test.py文件,然后以文件为基础,加载全局名称空间
    #3、在执行文件的过程中如果调用函数,则临时产生局部名称空间
    
    
    名字的查找顺序
      局部名称空间--全局名称空间--内置名称空间
       注意:在全局无法查看局部的,在局部可以查看全局的

    作用域:作用域即范围
      -全局范围:(内置名称空间与全局名称空间属于该范围):全局存活,全局有效
      -局部范围:(局部名称空间属于该范围):临时存活,局部有效

    查看作用域: globals(),locas()
      
    1 LEGB 代表名字查找顺序: locals -> enclosing function -> globals -> __builtins__
    2 locals 是函数内的名字空间,包括局部变量和形参
    3 enclosing 外部嵌套函数的名字空间(闭包中常见)
    4 globals 全局变量,函数定义所在模块的名字空间
    5 builtins 内置模块的名字空间
    
    
    
    闭包函数
      内部函数包含对外部作用域而非全局作用域的引用
    1     def index(url):
    2         def get():
    3             return urlopen(url).read()
    4         return get
     1 #闭包的意义:返回的函数对象,不仅仅是一个函数对象,在该函数外还包裹了一层作用域,这使得,该函数无论在何处调用,优先使用自己外层包裹的作用域
     2 #应用领域:延迟计算(原来我们是传参,现在我们是包起来)
     3     from urllib.request import urlopen
     4 
     5     def index(url):
     6         def get():
     7             return urlopen(url).read()
     8         return get
     9 
    10     baidu=index('http://www.baidu.com')
    11     print(baidu().decode('utf-8'))
    9 装饰器
      为什么要用装饰器?
        开放封闭原则:对修改封闭,对扩展开放
      什么是装饰器?
        装饰器本身是任意可调用对象,被装饰着也可以是任意可调用对象
        装饰器的原则:
          1,不修改被装饰对象的源代码
          2,不修改被装饰对象的调用方式
          3,在遵循1和2的前提下,为被装饰对象添加新功能
      装饰器的基本语法:(任何装饰器都可以套用)
     
    def  foo(func):
        def wrappers(*args,**kwargs):
            res = func()
          return res
        return wrappers
    
    
    
       无参装饰器
    import time
    def timmer(func):
        def wrapper(*args,**kwargs):
            start_time=time.time()
            res=func(*args,**kwargs)
            stop_time=time.time()
            print('run time is %s' %(stop_time-start_time))
            return res
        return wrapper
    
    @timmer
    def foo():
        time.sleep(3)
        print('from foo')
    foo()
    
    

      有参装饰器

    def auth(driver='file'):
        def auth2(func):
            def wrapper(*args,**kwargs):
                name=input("user: ")
                pwd=input("pwd: ")
    
                if driver == 'file':
                    if name == 'egon' and pwd == '123':
                        print('login successful')
                        res=func(*args,**kwargs)
                        return res
                elif driver == 'ldap':
                    print('ldap')
            return wrapper
        return auth2
    
    @auth(driver='file')
    def foo(name):
        print(name)
    
    foo('egon')
    
    10 迭代器与生成器及协程函数
      1,迭代器就是迭代的工具,迭代就是一个重复的过程,每次重复就是一次迭代,
    并且每次迭代的结果都是下一次迭代的初始值
      2,为什么要有迭代器?
        对于没有索引的数据类型,迭代器提供了一种不依赖索引的迭代方式
      3,可迭代对象
        内置有__iter__方法的对象,即obj.__iter__
        可迭代对象:字符串,列表,元组,字典,集合,文件
      4,迭代器对象
        可迭代对象执行__iter__得到的结果就是迭代器对象
        迭代器对象指的是既内置有__iter__又内置有__next__方法的对象
        文件类型是迭代器对象
    dic={'a':1,'b':2,'c':3}
    
    iter_dic=dic.__iter__()  #可迭代对象执行__iter__方法得到的结果就是迭代器对象
    #迭代器对象内置有__iter__方法和__next__方法
    iter_dic.__iter__() id iter_dic #  迭代器执行__iter__()得到的仍然是迭代器本身
    print(iter_dic.__next__())
    print(iter_dic.__next__())
    print(iter_dic.__next__()) #等同于next(iter_dic)
    #迭代对象有几个值就需要执行几次,直到没有值可取
    
    print(iter_dic.__next__()) #抛出异常StopIteration,标志迭代对象的值已经全部取出
    迭代器的使用
    
    
    基于for循环,我们可以实现不依赖索引取值
    1 dic={'a':1,'b':2,'c':3}
    2 for k in dic:
    3     print(dic[k]
    
    for循环工作原理
    1,执行in后的对象__iter__()方法,得到一个迭代器对象
    2,执行__next__方法,将得到的值赋值变量,然后执行循环体代码
    3,重复过程2,直到捕捉到异常StopIteration
    for循环原理

    迭代器的优缺点:

      优点:提供了一种不依赖索引的迭代方式

      缺点:无法获取长度

        只能一直往前取,无法往后取

    生成器
      函数内包含有yield关键字
      再调用函数,就不会执行函数体代码,拿到的返回值就是一个生成器对象
      注意::生成器本质就是迭代器,也就是说迭代器的用法就是生成器的用法

    11 三元运算,列表解析、生成器表达式
      三元运算:
        格式:
          为真时的结果 if 判断条件 else 为假时的结果
      例子: print(1 if 5>3 else 0)
      
      列表解析(列表推导式)
        基本形式:[表达式 for 参数 in 可迭代对象]
           或者 [表达式 for 参数 in 可迭代对象 if 条件]
      实例
     1 l = []
     2 for i in range(100):
     3     l.append('egg%s' %i)
     4 print i
     5 
     6 #不带if条件
     7     l = ['agg%s' %i for i in range(100) ]
     8 
     9 #带if条件
    10     l = ['agg%s' %i for i in range(100)  if i>10]
    View Code
    
    

        生成器表达式

          将列表推导式的中括号改为小括号即可

      

      l = ('egg%s' %i  for i in range(100)  if i>10)
    
      print(next(l))
    
      注意:得到的结果为迭代器
    生成器表达式
    12 函数的递归调用
      递归调用是函数嵌套调用的一种特殊形式,函数在调用时,直接或间接调用了自身
    就是递归调用
      递归的两个阶段:
        回溯:往前搜索,以达到目标
            注意:一定要在满足某个条件的情况下结束回溯,否则就是无限递归  
        递推:往回推
     
    1 def age(n):
    2     if n == 1:
    3         return 1
    4     else:
    5         return age(n-1)+2
    6 
    7 print(age(5))
    递归实例
       递归总结:
         递归必须有一个明确的结束条件
         每次进入更深一层递归时,问题规模相比上次递归都应有所减少
         python没有尾递归优化,但是设置了最大递归层数
    13 内置函数
      内置函数就是python解释器定义好的函数

      reduce(func,iterable) 从可迭代系列中循环取值,参与第一个函数参数的计算,最后得到一个结果

    
    
    reduce(lambda x, y: x+y, [1,2,3,4,5]) # 使用 lambda 匿名函数
    
    
    
    
    

      bytes()将unicode指定编码后转化为bytes类型

    
    

      chr()返回值是传入整数对应的ascii字符

    
    

      divmod()将除数和余数的运算结果结合起来,返回一个包含商和余数的元组(a//b,a%b)

    
    
    >>>divmod(7, 2)
    (3, 1)
    >>> divmod(8, 2)
    (4, 0)
    >>> divmod(1+2j,1+0.5j)
    ((1+0j), 1.5j)
    
    
    
    
    

      enumerate()将一个可遍历的数据对象组合为一个索引序列,同时列出数据个数据下标,一般用在for循环

    
    

      

    
    
    >>>seasons = ['Spring', 'Summer', 'Fall', 'Winter']
    >>> list(enumerate(seasons))
    [(0, 'Spring'), (1, 'Summer'), (2, 'Fall'), (3, 'Winter')]
    
    
    
    
    

      eval()执行一个字符串表达式,并返回表达式的值

    
    
    >>>x = 7
    >>> eval( '3 * x' )
    21
    >>> eval('pow(2,2)')
    4
    >>> eval('2 + 2')
    4
    >>> n=81
    >>> eval("n + 4")
    85
    
    
    
    
    

      filter(func,iterable)函数用于过滤序列,过滤掉不符合条件的元素,返回由符合条件元素组成的新列表

    
    

     

    
    
    import math
    def is_sqr(x):
        return math.sqrt(x) % 1 == 0
    newlist = filter(is_sqr, range(1, 101))
    print(newlist)
    
    
    
    
    

      id() 返回参数的内存地址序号

    
    

      input()获取输入

    
    

      iter(object)生成迭代器

    
    

      len()返回参数长度

    
    

      map(func,iterable)第一个参数 function 以参数序列中的每一个元素调用 function 函数,返回包含每次 function 函数返回值的新列表。

    
    

      

    
    
    map(lambda x: x ** 2, [1, 2, 3, 4, 5])  # 使用 lambda 匿名函数
    [1, 4, 9, 16, 25]
    
    >>> map(lambda x, y: x + y, [1, 3, 5, 7, 9], [2, 4, 6, 8, 10])
    [3, 7, 11, 15, 19]
    
    
    
    
    

     

    
    

     max()返回给定参数的最大值,参数可以是系列

    
    
    egon male 18 3000
    alex male 38 30000
    wupeiqi female 28 20000
    yuanhao female 28 10000
    
    with open('db.txt') as f:
        items=(line.split() for line in f)
        info=[{'name':name,'sex':sex,'age':age,'salary':salary} 
              for name,sex,age,salary in items]
    
    print(max(info,key=lambda dic:dic['salary']))
    
    max(iterable, key, default) 求迭代器的最大值,其中iterable 为迭代器,max会for i in … 遍历一遍这个迭代器,然后将迭代器的每一个返回值当做参数传给key=func 中的func(一般用lambda表达式定义) ,然后将func的执行结果传给key,然后以key为标准进行大小的判断
    
    
    
    
    

      min()返回给定参数的最小值,参数可以是系列

    
    

      ord()返回给定参数的十进制数

    
    
    >>>ord('a')
    97
    >>> ord('b')
    98
    >>> ord('c')
    99
    
    
    
    
    

      sorted()对所有可迭代的对象进行排序操作。

    
    
    sort 与 sorted 区别:
    sort 是应用在 list 上的方法,sorted 可以对所有可迭代的对象进行排序操作。
    list 的 sort 方法返回的是对已经存在的列表进行操作,而内建函数 sorted 方法返回的是一个新的 list,而不是在原来的基础上进行的操作。
    
    
    
    
    
    iterable -- 可迭代对象。
    cmp -- 比较的函数,这个具有两个参数,参数的值都是从可迭代对象中取出,此函数必须遵守的规则为,大于则返回1,小于则返回-1,等于则返回0。
    key -- 主要是用来进行比较的元素,只有一个参数,具体的函数的参数就是取自于可迭代对象中,指定可迭代对象中的一个元素来进行排序。
    reverse -- 排序规则,reverse = True 降序 , reverse = False 升序(默认)。
    
    
    >>>a = [5,7,6,3,4,1,2]
    >>> b = sorted(a)       # 保留原列表
    >>> a 
    [5, 7, 6, 3, 4, 1, 2]
    >>> b
    [1, 2, 3, 4, 5, 6, 7]
     
    >>> L=[('b',2),('a',1),('c',3),('d',4)]
    >>> sorted(L, cmp=lambda x,y:cmp(x[1],y[1]))   # 利用cmp函数
    [('a', 1), ('b', 2), ('c', 3), ('d', 4)]
    >>> sorted(L, key=lambda x:x[1])               # 利用key
    [('a', 1), ('b', 2), ('c', 3), ('d', 4)]
     
     
    >>> students = [('john', 'A', 15), ('jane', 'B', 12), ('dave', 'B', 10)]
    >>> sorted(students, key=lambda s: s[2])            # 按年龄排序
    [('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]
     
    >>> sorted(students, key=lambda s: s[2], reverse=True)       # 按降序
    [('john', 'A', 15), ('jane', 'B', 12), ('dave', 'B', 10)]
    >>>
    14 面向过程编程
    #1、首先强调:面向过程编程绝对不是用函数编程这么简单,面向过程是一种编程思路、思想,而编程思路是不依赖于具体的语言或语法的。言外之意是即使我们不依赖于函数,也可以基于面向过程的思想编写程序
    
    #2、定义
    面向过程的核心是过程二字,过程指的是解决问题的步骤,即先干什么再干什么
    
    基于面向过程设计程序就好比在设计一条流水线,是一种机械式的思维方式
    
    #3、优点:复杂的问题流程化,进而简单化
    
    #4、缺点:可扩展性差,修改流水线的任意一个阶段,都会牵一发而动全身
    
    #5、应用:扩展性要求不高的场景,典型案例如linux内核,git,httpd
    
    #6、举例
    流水线1:
    用户输入用户名、密码--->用户验证--->欢迎界面
    
    流水线2:
    用户输入sql--->sql解析--->执行功能
    面向过程编程
    
    
    
     
  • 相关阅读:
    jenkins初始化启动报错导致进入web页面无法安装插件
    redis5.0.7集群搭建
    搭建redis哨兵模式
    Linux服务器安装python3.6
    MySQL绿色版安装
    OSChina中远程GIT仓库同步探索
    Android坡度计
    利用ADB获取APP资源
    实现两台路由器无线桥接
    新体能评定软件开发总结(一)
  • 原文地址:https://www.cnblogs.com/guodengjian/p/8710617.html
Copyright © 2020-2023  润新知