• 函数


    1、函数的基本知识

    1.1 、break

    跳出当前执行的循环体;

    1.2 、return

    跳出当前执行的函数,结束一个函数;
            return
    return None 基本不用
    return 返回1个值
    return 多个值----:return value1,value2....,多个返回值用多个变量进行接收,有多少个返回值就得用多少个变量接收
    多个变量可以用一个变量进行接收,这时候这个变量接收值以后就是元组,其实返回值就是一个元组
    元组是可以解包的: a,b,c = (1,3,4),那么a = 1,b = 2,c = 4

    1.3 、站在形参角度上

    按照位置传参,按照参数的位置一一对应去赋值传实参
    按照关键字传参,就是形参里面是什么名称,调用函数传实参的时候就用什么名称
    混着用可以:但是 必须先按照位置传参,再按照关键字传参数
    不能给同一个变量传多个值

    1.4、站在实参角度上

    位置参数:必须传,且有几个参数就传几个值
    默认参数: 可以不传,如果不传就是用默认的参数,如果传了就用传的,默认的参数就是函数的形参里面已经定义实参的那种
    先定义位置参数,后定义默认参数
    动态参数 : 可以接受任意多个参数,
    参数名之前加*,习惯参数名args,但关键字参数接收不了,接收的是按位置传参数的值,组织成一个元组
    参数名之前加**,习惯参数名kwargs,接收的是按关键字传参数的值,组织成一个字典

    1.5、函数放参数的顺序

    函数放参数顺序:位置参数,*args,默认参数,**kwargs

    1.6、动态参数的另一种传参方式

    第一种:可变位置参数*args

    1 def sum(*args):
    2     n = 0
    3     for i in args:
    4         n+=i
    5     return n
    View Code

    结果:

    1 3
    2 6
    3 10
    View Code

    第二种:可变关键字参数**kwargs

    1 def func2(**kwargs):
    2     print(kwargs)
    3 func2(a = 1, b = 2, c = 3)
    View Code

    结果:

    1 {'a': 1, 'b': 2, 'c': 3}
    View Code

    下面代码结果是

    1 def func3(*args,**kwargs): #组合式动态形参函数,那么先args后kwargs,且传实参也得是这个顺序
    2     print(args,kwargs)
    3 
    4 func3(1,2,3,a = 5,c = 9)
    5 func3(1,2,3,a = 5,c = 9)

    结果:

    1 (1, 2, 3) {'a': 5, 'c': 9}
    2 (1, 2, 3) {'a': 5, 'c': 9}
    View Code

    下面代码结果是

    1 def func4(*args):
    2     print(args)
    3 L = [1,2,3,4]
    4 func4(*L) 

    结果:

    1 #从实参角度上看,给一个序列加上*,就是将这个序列按照顺序打散
    2 (1, 2, 3, 4)
    3 {'a': 2, 'b': 8}
    View Code

    下面代码结果是:

    1 def func5(**kwargs):
    2     print(kwargs)
    3 l5 = {'a':2,'b':8}
    4 
    5 func5(**l5)

    结果是:

    1 {'a': 2, 'b': 8}
    View Code

    1.7、函数的注释

    1 def func():
    2     '''
    3     这个函数是实现什么功能
    4     参数1:
    5     参数2:
    6     参数3:
    7     :return: 返回的是什么
    8     '''

    1.8、默认参数的陷阱问题

    总体原则:当默认参数是一个可变数据类型(可哈希)时候,那么每一次调用函数的时候,如果不传值就共用这个数据类型的资源

    下面代码结果是:

    1 def func2(l = []):
    2     l.append(1)
    3     print(l)
    4 func2()   
    5 func2([])  
    6 func2()    
    7 func2()   
     1 def func2(l = []):
     2     l.append(1)
     3     print(l)
     4 func2()    #不传参数,那么用默认的参数
     5 func2([])  #传了个自己的空列表,那么不用默认的空列表
     6 func2()    #不传参数,那么接着用默认的参数
     7 func2()    #不传参数,那么接着用默认的参数
     8 
     9 结果:
    10 [1]
    11 [1]
    12 [1, 1]
    13 [1, 1, 1]
    View Code

    下面代码的结果是:

    1  def func2(l = {}):
    2     l['k'] = 'v'
    3      print(l)
    4  func2()    
    5  func2()   
    6 func2()    

    结果:

    1 #如果是空字典,那么里面其实是重复把key的值固定为v
    2 {'k': 'v'}
    3 {'k': 'v'}
    4 {'k': 'v'}
    View Code

    下面代码的结果是:

    1 def func2(k,l = {}):
    2     l[k] = 'v'
    3     print(l)
    4 func2(1)   
    5 func2(2)    
    6 func2(3)   

    结果:

    1 {1: 'v'}
    2 {1: 'v', 2: 'v'}
    3 {1: 'v', 2: 'v', 3: 'v'}
    View Code

     1.9  函数的命名空间

    #命名空间 有三种
    #内置命名空间 —— python解释器
    # 就是python解释器一启动就可以使用的名字存储在内置命名空间中
    # 内置的名字在启动解释器的时候被加载进内存里
    #全局命名空间 —— 我们写的代码但不是函数中的代码
    # 是在程序从上到下被执行的过程中依次加载进内存的
    # 放置了我们设置的所有变量名和函数名
    #局部命名空间 —— 函数
    # 就是函数内部定义的名字
    # 当调用函数的时候 才会产生这个名称空间 随着函数执行的结束 这个命名空间就又消失了

    #在局部:可以使用全局、内置命名空间中的名字
    #在全局:可以使用内置命名空间中的名字,但是不能用局部中使用
    #在内置:不能使用局部和全局的名字的

    #依赖倒置原则:(内置的名字空间 (全局的名字空间 (局部的名字空间) ) ):内部的可以到上层找,但上层不能到更里层找

    #在正常情况下,直接使用内置的名字
    #当我们在全局定义了和内置名字空间中同名的名字时,会使用全局的名字
    #当我自己有的时候 我就不找我的上级要了
    #如果自己没有 就找上一级要 上一级没有再找上一级 如果内置的名字空间都没有 就报错
    # 多个函数应该拥有多个独立的局部名字空间,不互相共享
    1 def input():
    2     print('in input now')
    3 def func():
    4     # input = 1
    5     print(input)
    6 func()
    这段代码打印的是什么呢
    1 <function input at 0x00000000004D2F28>
    结果
    # 对于不可变数据类型 在局部可是查看全局作用域中的变量
    # 但是不能直接修改
    # 如果想要修改,需要在程序的一开始添加global声明
    # 如果在一个局部(函数)内声明了一个global变量,那么这个变量在局部的所有操作将对全局的变量有效


    # 作用域两种
    # 全局作用域 —— 作用在全局 —— 内置和全局名字空间中的名字都属于全局作用域 ——globals()
    # 局部作用域 —— 作用在局部 —— 函数(局部名字空间中的名字属于局部作用域) ——locals()

    1 a = 1
    2 def func():
    3     global a
    4     a += 1
    5 func()
    6 print(a)

    代码的结果是;

    1 结果就是:2
    结果是
    1 a = 1
    2 b = 3
    3 def func2():
    4     x = 'aaa'
    5     y = 'ccc'
    6     print(locals())
    7 func2()
    1 {'y': 'ccc', 'x': 'aaa'}
    结果是
    1 a = 1
    2 def func3():
    3     global a #这里会代替外面全局的变量a,这样名字实际被改了
    4     a = 2
    5 func3()
    6 print(a)
    7 print(globals()) #globals永远打印全局的名字
    8 print(locals()) #locals放在全局,那么它的局部就是全局;如果放在局部,那么就是局部
    1 2
    2 {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000000000275BBA8>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'E:/Python Project/05/Day10/函数的命名空间.py', '__cached__': None, 'a': 2, 'func3': <function func3 at 0x00000000020B2F28>}
    3 {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000000000275BBA8>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'E:/Python Project/05/Day10/函数的命名空间.py', '__cached__': None, 'a': 2, 'func3': <function func3 at 0x00000000020B2F28>}
    结果是

     1.10 函数的嵌套

    函数的嵌套:内部函数可以使用外部函数的变量

    1 def outer():
    2     def inter():
    3         print(2)
    4     inter()
    5 outer()
    1 2
    结果是
    1 def outer():
    2     b = 5
    3     def inter():
    4         print(b)
    5         print('in the inter')
    6     inter()
    7 outer()
    1 5
    2 in the inter
    结果是
    定义为gloabl的函数中的变量,那么该变量是全局的变量,局部变量如果同名那么是没有修改的
    不可变数据类型在它的下级函数不能被修改,只能查看
     1 b = 2
     2 def outer():
     3     b = 5
     4     def inter():
     5         print(b)
     6         c = 4
     7         print('in the inter')
     8         def interb():
     9             #c += 1  #不可变数据类型在它的下级函数不能被修改,只能查看
    10             global b
    11             b += 1
    12             print(c)
    13             print(b)
    14             print('in the interb')
    15         interb()
    16     inter()
    17 outer()
    18 print(b)
    1 5
    2 in the inter
    3 4
    4 3
    5 in the interb
    6 3
    结果是

    1.10.1  nonlocal的使用

    onlocal声明了上面一层的局部变量,离被使用b最近的局部变量,即往外找找到最近一层的那个变量b,只能用于局部变量
    如果往上找没找到局部的变量那么报错,全局的变量是不行的,即nonlocal对全局变量无效。
     1 b = 2
     2 def outer():
     3     b = 5
     4     def inter():
     5         print(b)
     6         print('in the inter')
     7         def interb():
     8             nonlocal b 
     9             b +=1
    10             print(b)
    11             print('in the interb')
    12         interb()
    13     inter()
    14     print(b)
    15 outer()
    16 print(b)
    1 5
    2 in the inter
    3 6
    4 in the interb
    5 6
    6 2
    结果是

    1.10.2 一个函数的函数名就是一个内存地址

    1 def fun():
    2     print(33)
    3 fun2 = fun
    4 fun2()
    5 lis  = [fun,fun2] #函数名可以作为容器类型的元素
    6 print(lis)
    7 for i in lis:
    8     i()
    1 33
    2 [<function fun at 0x00000000003E2F28>, <function fun at 0x00000000003E2F28>]
    3 33
    4 33
    结果是

    1.10.3   函数可以作为另一个函数的参数

    1 def func():
    2     print(44)
    3 def func2(f):
    4     f()
    5 func2(func)
    1 44

    1.10.4 函数名可以作为另一个函数的返回值

    1 def func():
    2     print(44)
    3 def func2(f):
    4     f()
    5     return f   #函数名可以作为函数的返回值
    6 a = 0
    7 a = func2(func) #函数名可以作为函数的参数
    8 print(a)
    9 a()
    1 44
    2 <function func at 0x0000000001D22F28>
    3 44
    结果是

    1.10.5 一类对象(first-class objet)指

    1 1、可在允许期创建
    2 2、可用作函数参数或返回值
    3 3、可存入变量的实体

     1.11 闭包

    闭包:嵌套函数,内部函数调用外部函数的变量;其实就是一个函数A里面嵌套了另一个函数B,并且函数B里面使用了函数A的变量,那么函数B为闭包;  如果函数B没有使               用函数A里面的变量,但使用了全局变量,那么函数B就不是闭包。

    检测一个函数是否为闭包的形式:
    print(inner.__closure__) #这是检测inner()是否为闭包
    1 def outer():
    2     b = 2
    3     def inner():
    4         print(b) 
    5     inner()
    6     print(inner.__closure__) 
    7 outer()
    8 print(outer.__closure__)
    1 2
    2 (<cell at 0x00000000003FEEB8: int object at 0x000000001D8E60C0>,) #表示inner()函数是闭包
    3 None #表示outer()函数不是闭包
    4 
    5 函数中如果没有print(b)这句话,即调用上一层变量这么个操作的 话,那么inner()函数就不是闭包
    结果&解析
    1 b = 1
    2 def outer():
    3     def inner():
    4         print(b) #这里调用的是全局表里的b,所以不是闭包
    5     print()
    6 outer()

    1.11.1 闭包的常用形式:

    在函数外部使用函数内部的函数,在在函数外部使用嵌套的函数。

    闭包的作用:在多次调用同一函数时候,可以节省空间的作用

    1 def func():
    2     a = 77
    3     def func2():
    4         print(a)
    5     return func2
    6 func3 = func()
    7 func3()
    1 77
    2 分析:实际上func3()就等价于调用了func2()
    View Code
    1 from urllib.request import urlopen
    2 def func():
    3     url = 'http://www.ifeng.com/'
    4     def get():
    5         ret = urlopen(url).read()
    6         print(ret)
    7     return get
    8 get_net = func()
    9 get_net()
    1 b'<!DOCTYPE html>
    <html xmlns:wb="http://open.weibo.com/wb">
    <head>
        <meta charset="utf-8">
    
    2 ...........
    3 ...........
    4 还有很多,不再写出来
    5 其实结果就是网页的源码
    6 这里如果我们多次调用嵌套函数get()时候就可以起到调用的时候才生成ural这个常量的空间,用完就释放空间的作用,这样起到节省空间的作用
    结果&分析




  • 相关阅读:
    linux 创建python虚拟环境
    dic1.update(dic2)和{**dic2, **dic1}的区别
    redis
    电脑开机一卡一卡的,重启就好了
    股东大会和董事会的区别
    word空白框打钩
    计划资产回报
    成本法为什么要转权益法
    租赁负债
    AIDA64序列号
  • 原文地址:https://www.cnblogs.com/xiaofei1106/p/10640284.html
Copyright © 2020-2023  润新知