五、python的函数

函数的作用

  • 实现代码的重复利用
  • 实现代码的模块性
  • 确保代码的可扩展性

函数的定义

  • 函数代码块以 def 关键词开头,后接函数标识符名称和圆括号()。
  • 任何传入参数和自变量必须放在圆括号中间。圆括号之间可以用于定义参数。
  • 函数体的第一行语句可以选择性地使用文档字符串—用于存放函数说明。
  • 函数内容以冒号起始,并且缩进。
  • return [表达式]结束函数,选择性地返回一个值给调用方。不带表达式的return和没有return相当于返回 None。

定义格式:

def functionname( parameters ):
   "函数_文档字符串"
   function_suite
   return [expression]

注意在 python 中,strings, tuples, 和 numbers 是不可修改的对象,而 list,dict 等则是可以修改的对象。

  • 不可变类型:变量赋值 a=5 后再赋值 a=10,这里实际是新生成一个 int 值对象 10,再让 a 指向它,而 5被丢弃,不是改变a的值,相当于新生成了a。
  • 可变类型:变量赋值 la=[1,2,3,4] 后再赋值 la[2]=5 则是将 list la 的第三个元素值更改,本身la没有动,只是其内部的一部分值被修改了。

将不可变对象a作为参数传入函数内,进行处理并不会影响函数外a的值;
将可变对象b作为参数传入函数内,进行处理会影响函数外b的值;

函数的调用

函数调用格式: 函数名()
实质是先通过函数名找到内存地址,在执行内存地址中的函数体代码

函数的参数

函数在def定义的时候,指明需要的参数,称这些参数为形参,不会占用内存空间。

函数在被引用的时候,传递给形参的参数,称之为实参,会占用内存空间

根据传递给形参时的不同方法,又分以下几类:
关键字参数:函数引用时,形参和实参的通过(形参=实参)建立传递关系;

位置参数:函数引用时,如果没有通过关键字参数建立传递关系,则他们通过位置顺序一一对应。
注意传递参数时,关键字参数不能在位置参数前面

默认参数:在函数定义的时候,可以为形参设的默认的值(形参=1),这个特别的形参称之为默认参数;默认参数的特点,调用函数的时候,默认参数可以不传递实参

动态参数:当无法确定形参数量的时候,可以在定义函数中使用参数组

*把函数引用时传递而来多个位置参数转换为一个元组

def test(*args)
	print(args)

test(1234)
args为一个元组=(1234)

**把函数引用时传递而来的多个关键字参数,转换为字典

def stu_register(name,age,*args,**kwargs): # *kwargs会把多传入的关键字参数变成一个dict形式
    print(name,age,args,kwargs)

stu_register("Jack",32,"CN","Python",sex="Male",province="ShanDong")
#输出
Jack 32 ('CN', 'Python') {'province': 'ShanDong', 'sex': 'Male'}

命名空间

内置命名空间: python解释器
用于存放python解释器启动就能使用的内置名字,在启动解释器时内置的名字就被加载进内存;无法调用全局、局部命名空间中的名字.

全局命名空间: 我们写的代码但不是函数中的代码
用于放置我们定义的所有变量名和函数名,在程序从上到下被执行的过程中依次加载进内容;在全局命名空间中可以调用内置名字空间的名字,但不能调用局部命名空间中的名字

局部命名空间: 函数中的代码
用于放置函数内部定义的名字,在函数被调用的时候才加载进内存;在局部命名空间中可以使用全局和内置命名空间中的名字;多个函数拥有多个独立的局部命名空间,相互独立。

作用域

全局作用域
在全局可用,内置命名空间和全局命名空间属于全局作用域。
globals() 查看全局作用域中的变量

局部作用域
只有在局部(函数、类内)可用,局部命名空间在相依的局部作用域中可用。
locals() 查看局部作用域中的变量

全局变量
在整个程序生效,列表,字典,和集合等可变对象可以在函数内被修改

局部变量
只在局部范围内生效,多用于函数内;函数内使用并修改全局变量(字符串和数值),需先global声明其为全局变量
注意:全局变量一定要在函数外声明,且不建议在函数内修改全局变量。

嵌套函数

在一个函数体内再调用一个函数,这就是嵌套函数;

内部函数可以引用外部函数的变量,但不能修改外部函数变量的值。
想要修改上一层函数的变量,使用nonlocal先声明该变量。

nonlocal表⽰示在局部作⽤用域中, 调⽤用⽗父级命名空间中的变量.上一层没有则会再向上一层寻找,直到全局。

global表⽰不再使⽤局部作用域中的内容了. ⽽改用全局作⽤用域中的变量.

闭包函数

在嵌套函数中,内部函数有调用外部函数的变量,那么这个内部函数就是闭包函数,外部被调用的变量是自由变量。

def out():
    c=[5]
    def inner():
        c[0]+=1
        return c
    return inner

foo=out()  ##因为out函数中的return inner;故等号右边先执行,out()执行后foo指向了内部函数inner,且c=[5].
print(foo(),foo())  ##输出7,7
##print会等待()中的函数全部执行完毕才打印.
##第一个foo()返回名为c的内存单元,第二个仍返回名为c的内存单元。待打印时
##名为c的内存单元以及经过两次foo函数执行,其存放的值已变为7
print(foo())		#输出8

上面就是闭包的一种应用;通过外部函数中,return内部函数。此时可以在嵌套函数外调用内部函数,而且不会重复在内存中为外部函数变量a开辟空间。

递归函数

在函数内部调用函数自己,这个函数就称为递归函数,递归函数最多递归999次,其特性如下:
1、必须要有一个明确的结束条件
2、每次进入更深一层时,问题规模相比上次有所减少
3、递归效率不高,递归层次过多会导致栈溢出

def calc(n):
    print(n)
    if int(n/2) ==0:
        return n
    return calc(int(n/2))
 
calc(10)
输出:
10
5
2
1

匿名函数

lambda 参数列表:函数处理表达式
lambda x:x**2

(lambda x:print(x**2))(4)
前面的括号用于定义命名函数;第二个括号表达传递参数调用此匿名函数

高阶函数

将一个函数作为实参传递给另一个函数的形参。

def add(x,y,f):
    return f(x) + f(y)
 
res = add(3,-6,abs)
print(res)

或者函数的输出是一个函数

def counter(base):
    def inc(step=1):
        nonlocal base
        base += step
        return base
    return inc

f1=counter(5)()
print(f1)
发布了40 篇原创文章 · 获赞 2 · 访问量 2067

猜你喜欢

转载自blog.csdn.net/weixin_42155272/article/details/93869819