函数的传递方式

  1. 位置参数

位置参数就是将对应位置的实参赋值给对应位置的形参。

默认值:定义形参的时候,可以给形参指定默认值,如果用户传递了实参,默认值不会发挥任何作用,如果用户没有传递,则采用默认值。

def fn(a,b,c=20):
     print('a = ',a)
     print('b = ', b)
     print('c = ', c)

 fn(1,2)

执行结果:

a =  1
b =  2
c =  20

 

2、关键字参数

关键字参数可以不按照形参定义的顺序去传递,而根据参数名去传递

def fn(a=5,b=10,c=20):

    print('a=',a)

    print('b=', b)

    print('c=', c)

  

fn(b=1,c=2,a=3)

执行结果:

a= 3
b= 1
c= 2

位置参数和关键字参数可以混合使用,混合使用的时候,必须将位置参数写到关键字参数前面:

def fn(a=5,b=10,c=20):

    print('a=',a)

    print('b=', b)

    print('c=', c)

  

fn(1,c=8)

执行结果如下:

a= 1
b= 10
c= 8

 

3、实参的类型

实参可以传递任意类型的对象

 

浅复制:

 

def fn4(a):

    a[0] = 50

    print('a=',a,id(a))

  

c =10

  c = [1,2,3]

fn4(c.copy())

  

  print('c=',c,id(c))

执行结果如下:

a= [50, 2, 3] 2303414788808
c= [1, 2, 3] 2303414788744

如果你传递的是一个可变对象的时候,而又不希望在函数内部的操作影响到函数外部,那么就可以考虑传递一个副本。

 

4、不定长参数

在定义函数时,可以在形参前面加一个*,这个形参就可以获取到所有的实参,所有的实参会保存在元组中(封包)

例如求任意数的和:

def fn5(*a):

    n = 0

    for i in a:

        n += i

    return n

  

  

  print(fn5(1,3,5,7,9))

执行结果如下:

25

不定长参数也可以和其他参数配合使用

def fn2(a,b,*c):

    print('a=',a)

    print('b=', b)

    print('c=', c)

  

fn2(1,2,3,4,5)

执行结果如下:

a= 1
b= 2
c= (3, 4, 5)

不定长参数不是必须写在最后,但是要注意,带*的参数后面的所有参数,必须以关键字参数形式传递。

 

不定长关键字参数:

def fn3(**a):

    print('a = ',a)

  

fn3(b=1,d=2,c=3)

执行结果如下:

a =  {'b': 1, 'd': 2, 'c': 3}

**形参可以接受其他的关键字参数,它会将这些参数统一保存到一个字典当中。

**形参只能有一个,并且必须写在所有参数后面

def fn3(b,c,**a):

    print('a = ',a)

    print('b =',b)

    print('c =',c)

  

fn3(1,2,f=5,d=6,e=7)

执行结果如下:

a =  {'f': 5, 'd': 6, 'e': 7}
b = 1
c = 2

 

5、函数的解包

def fn4(a,b,c):

    print('a = ',a)

    print('b = ',b)

    print('c = ',c)

  

t = (10,20,30)

fn4(*t)

执行结果如下:

a =  10
b =  20
c =  30

传递实参,也可以在序列类型的参数添加*,程序会自动将序列当中的元素依次作为参数传递。序列当中的元素个数必须和形参的个数保持一致。

def fn4(a,b,c):

    print('a = ',a)

    print('b = ',b)

    print('c = ',c)

  

t = {'a':1,'b':2,'c':3}

fn4(**t)

执行结果如下:

a =  1
b =  2
c =  3

6、函数的返回值

返回值就是函数执行以后返回的结果;return后面可以跟任意的对象,甚至可以是一个函数。

如果仅仅写一个return或者不写return则相当于return None

执行return后代表函数结束。

def fn4():
     for i in range(5):
         if i == 3:
             return
         print(i)
     print('循环结束')


 fn4()

 

执行结果如下:

 

fn4和fn4()的区别:

print(fn5) 是函数对象,打印的是函数对象

print(fn5())是在调用函数,实际上在打印fn5()函数的返回值

 

7、文档字符串

Help()可以查询python函数中的用法

语法help(函数对象)

def fn(a:int,b:str,c:bool):
     """
     函数的参数
     :param a: 作用。。。。
     :param b: 作用。。。。
     :param c: 作用。。。。
     :return: int
     """
     return 10

help(fn)

 

执行结果如下:

Help on function fn in module __main__:
 
fn(a: int, b: str, c: bool)
    函数的参数
    :param a: 作用。。。。
    :param b: 作用。。。。
    :param c: 作用。。。。
    :return: int

 

8、函数的作用域

作用域指的是变量生效的区域,在python中有2种作用域

全局作用域:全局作用域在程序执行时创建,在程序结束时销毁,所有函数以外的区域都是全局作用域,在全局作用域中定义的变量,都属于全局变量,全局变量可以在程序中的任意位置访问。

函数作用域:函数作用域在函数调用时创建,在调用结束时销毁,函数每调用一次就会产生一个新函数的作用域,在函数作用域中定义的变量都是局部变量,它只能在函数内部被访问。

def fn2():
     a = 30
     def fn3():
         a = 40
         print('fn3中:','a =',a)
     fn3()

 fn2()

执行结果如下:

fn3中: a = 40

全局变量声明:

a = 20
def fn2():
     global a
     a = 10
     print('函数内部:','a =',a)

 fn2()
print('函数外部:','a =',a)

执行结果如下:

函数内部: a = 10
函数外部: a = 10

 

9、命名空间

命名空间实际上就是一个字典,是一个专门用来存储变量的字典

locals()用来获取当前作用域的命名空间

如果在全局作用域中调用locals()函数则获取全局作用域命名空间,如果在函数作用域中调用locals(),则获取函数命名空间

a = 20
def fn2():
     global a
     a = 10
     print('函数内部:','a =',a)

 fn2()
print('函数外部:','a =',a)
print(locals())

执行结果如下:

函数内部: a = 10
函数外部: a = 10
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0000021279246358>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'D:/MyPython/demo_1.py', '__cached__': None, 'a': 10, 'fn2': <function fn2 at 0x000002127770C1E0>}

 

10、递归

递归式函数就是在函数中调用自己。

递归式函数的两个条件:

  1. 问题可以被分解成最小的问题,当满足基线条件时,递归不再执行了
  2. 递归条件(将问题继续分解的条件)

求数的阶乘

def fn2(n):
     #基线条件
     if n ==1:
         return 1
     #递归条件
     return n * fn2(n-1)

print(fn2(10))

执行结果如下:

3628800