函数的定义

  想把一段代码的功能多次使用,需要对代码进行定义,使之成为函数,如计算字符串的长度

def func():  # 注意定义的格式 def 函数名():  #括号和冒号都不能省哦
    pass

函数的调用

  当一个函数定义之后,可以在任何需要的地方调用,调用函数的方式如下

func()

  函数名加括号进行调用

函数的返回值

  想要一个函数返回运行的结果,需要定义返回值,返回值有3种情况:

  (1)无返回值:

      不写ruturn,只写return,return None这三种情况都没有返回值,但return起什么作用呢?

      当函数执行到return时就会终止

  (2)返回1个值:

      可以返回任意数据类型,只要返回就可以被接收到

  (3)返回多个值:

      当返回多个值被一个变量就收时,接收到的是一个元组

      当返回n个值被n个变量接收时,变量被分别赋值

def func():
    return 1, 2, 3, 4
a = func()
print(a)
q, w, e, r = func()
print(q, w, e, r)

   ps:小知识补充

      元组、列表、字典是可以解包的

a, s, d = [1, 2, 3]
q, w, e = (1, 2, 3)
z, x, c = {1: 'a', 2: 'b', 3: 'x'}
print(a, s, d)
print(q, w, e)
print(z, x, c)

函数的参数

  函数的参数分为形参和实参

def func(a):  # 这里的a就是形参,形参的作用就是在定义的地方接受参数
    print(a)
    return a
func(3)  # 这里的3就是实参,实参就是在调用函数时传递给函数的参数

  函数的参数分为三种情况:

  (1)没有参数

      在定义和调用函数时()不写内容

  (2)有一个参数

      传什么就接收什么

  (3)有多个参数

      位置参数:直接定义参数

def func(a, b):  # 此时a = 2, b = 4,按照位置接受实参的值
    print(a, b)
func(2, 4)

      关键字参数:关键字 = 值

def func(a, b):  # 此时按照关键字传参,b = 2, a = 1
    print(a, b)
func(b=2, a=1)

      默认参数:不传值时使用默认值,如果传了,就使用传的参数

def func(a, b = 0):  # 若一个参数大多是同一个值时可以定义默认参数
    print(a, b)
func(2)  # 默认参数如果不传递值,则会使用默认值
func(2, 4)  # 如果默认参数有传递的值,则会使用传的值

      默认参数的陷阱:如果默认参数的值是一个可变数据类型,那么每次调用该函数,如果不传参就公用这个数据类型的资源

def func(a, l=[]):
    l.append(a)
    print(a, l)
func(1)
func(2)
func(3)
func(4)

      动态参数:可以接受任意多的参数 *args可以接受位置传参的值组成一个元组,

           **kwargs可以接受按照关键字传参的值,组成一个字典

def func(*args, **kwargs):  # 动态参数可以接受任意多个参数
    print(args, kwargs)
func(3, 4, 5, c=2, b=6)

    参数顺序:位置参数、*args、默认参数、**kwargs

    ps:小知识补充

def func(*args):  # 在形参接受时加*可以将参数组合成元组
    print(args)
l = [1, 2, 3, 4]
func(*l)  # 传参时给一个序列前加*是把一个序列打散

函数的注释

  函数的注释和一般代码中的注释格式不同

def func():
    '''
    这个函数实现了什么功能
    参数1:
    参数2:
    ···
    :return: 返回值是字符串或列表,长度?
    '''
    pass

  ps:小知识补充

    三元运算

def func(a, b):
    return a if a>b else b  # 如果条件成立返回a,条件不成立则返回b
print(func(1, 2))

函数的命名空间和作用域

  命名空间分为三部分:

  (1)内置命名空间 

      #python解释器 内置的名字在启动解释器时加载在内存里

      在内置命名空间中不能使用全局和局部命名空间中的名字

  (2)全局命名空间

      不是函数的代码所在的空间,在程序从上到下被执行的过程中依次加载进内存,放置了我们设置的所有变量名和函数名

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

  (3)局部命名空间

      函数内部定义的名字空间,当调用函数时会产生这个空间,函数结束时命名空间会消失

      每个函数都有局部命名空间,互相之间不共享

      在局部空间中可以使用内置和全局空间中的名字

    当我们在全局定义了和内置一样的名字时,会使用全局的名字

    如果自己没有,就找上一级要

  作用域

  全局作用域:作用在全局-->内置和全局空间

    global()查看全局和内置的所有名字,放在哪都是查看全局

    locals()放在全局空间时是查看全局

  局部作用域:作用在局部-->函数(局部空间)

    locals()放在局部时是查看局部定义的所有名字

  对于不可变数据类型来说,在局部可以查看全局作用域中的变量,但是不能直接修改

  如果想要修改,需要提前声明global;如果在局部空间(函数)内定义一个global变量,那么这个变量在局部的所有操作对全局有效

函数的嵌套调用

  在函数中调用函数称为函数的嵌套调用。

  函数的嵌套定义:

def func():
    def inner():
        print('inner')
    inner()
func()

  函数嵌套时有以下情况:

def func():
    a = 1
    def inner():
        print(a)
    inner()
func()

  内部函数是可以使用外部函数的变量的,但要是想要对外部函数的变量(不可变数据类型)进行修改,需要用到 nonlocal

a = 2
def func():
    a = 5
    def inner():
        nonlocal a  # 此时a = 5,不会影响到全局空间中的a
        a += 1
        print(a)
    inner()
func()
print(a)

  nonlocal:只能用于局部变量,找上层中离当前函数最近的一层的局部变量

  声明了nonlocal的内部函数局部变量的修改会影响到离当前函数最近一层的局部变量

  函数名

  函数名的作用类似于普通变量,因此具有与普通变量相同的作用,不同之处在于函数名()可以执行函数

def func():
    print('123')
func2 = func  # 函数名可以赋值
func2()
l = [func, func2]  # 函数名可以作为容器类型的元素
for i in l:
    i()

  总之,函数名可以当成普通的变量名使用

  闭包

  嵌套函数,内部函数调用了外部函数的变量就叫做闭包,调用外部函数的参数也是闭包

def func():
    a = 5
    def inner():
        print(a)
        print(inner.__closure__)  # 当打印的是cell···的时候就是闭包,none就不是
    return inner
f = func()
f()

 

posted on 2018-10-20 08:07  幸福的小耗子  阅读(182)  评论(0编辑  收藏  举报