Python系列-函数(下)

Python系列-函数(下)_第1张图片

 个人主页: 会编程的果子君
个人格言:“成为自己未来的主人~”

 

目录

变量作用域

函数执行过程

链式调用

嵌套调用

函数递归

参数默认值

关键字参数

小结


变量作用域

观察下面的代码

 

def getpoint():
    x=10
    y=20
    return x,y
x,y=getpoint()

在这个代码中,函数内部存在x,y,函数外部也有x,y

但是这两组x,y不是相同的变量,而只是恰好有一样的名字

变量只能在所在的函数内部生效

在函数getpoint()内部定义的x,y只是在函数内部生效,一旦出了函数的范围,这两个变量就不生效了。

def getpoint():
    x=10
    y=20
    return x,y
print(x,y)

在不同的作用域中,允许存在同名的变量

 

x=10

def test():
    x=10
    print(f'函数内部={x}')

test()
print(f'函数外部={x}')

 

主意:

  • 在函数内部的变量,也称为“局部变量”
  • 不在任何函数内部的变量,也称为“全局变量” 

如果函数内部尝试访问的变量在局部不存在,就会尝试去全局作用域中查找

x=10

def test():
    print(f'x={x}')

test()

 

如果想在函数内部,修改全局变量的值,需要使用global关键字声明

 

def test():
    global x
    x=10
    print(f'函数内部 x = {x}')

test()
print(f'函数外部 x = {x}')

 

如果此处没有global。则函数内部的x=10,就会被视为是创建一个局部变量x ,这样就和全局变量x不相关了。

if/while/for等语句块不会影响到变量作用域

换而言之,在if/while/for中定义的变量,在语句外面也可以正常使用

for i in range(1,11):
    print(f'函数内部 i ={i}')

print(f'函数外部 i ={i}')

函数执行过程

  • 调用函数才会执行函数体代码,不调用就不会执行
  • 函数体执行结束(或者遇到return 语句),则回到函数调用位置,继续往下执行 
def test():
    print('执行函数内部代码')
    print('执行函数内部代码')
    print('执行函数内部代码')
print("1111")
test()
print("2222")
test()

Python系列-函数(下)_第2张图片 

链式调用

 

def isodd(num):
    if num % 2 ==0:
        return False
    else:
        return True

result = isodd(10)
print(result)

实际上也可以简化写作

 

print(isodd(10))

把一个函数的返回值,作为另一个函数的参数,这种操作成为链式调用

这是一种比较常见的写法

嵌套调用

函数内部还可以调用其他的函数,这个动作称为“嵌套调用”

 

def test():
    print('执行函数内部代码')
    print('执行函数内部代码')
    print('执行函数内部代码')

test函数内部调用了print函数,这就属于嵌套调用

一个函数可以嵌套调用任意多个函数

函数嵌套的过程是非常灵活的

 


def a():
    print('a')

def b():
    print('b')
    a()

def c():
    print('c')
    b()

def d():
    print('d')
    c()

d()

 Python系列-函数(下)_第3张图片

如果把代码稍微调整,打印结果则可能发生很大变化

 


def b():
    a()
    print('b')

def c():
    b()
    print('c')

def d():
    c()
    print('d')
d()

Python系列-函数(下)_第4张图片

注意体会上述代码的执行顺序,可以通过画图的方式来理解

函数之间的调用关系,在Python中会使用一个特定的数据结构来表示,称为 “函数调用栈”,每次函数调用, 都会在调用栈里新增一个元素,称为 栈帧

可以通过PyCharm调试器看到函数调用栈和栈帧

在调试状态下,pycharm左下角一般就会显示出函数调用栈

函数递归

递归是嵌套调用中的一种特殊情况,即一个函数嵌套调用自己

代码示例:递归计算5!

def factor(n):
    if n ==1:
        return 1
    return n *factor(n-1)

result=factor(5)
print(result)

上述代码中,就属于典型的递归操作,在factor函数内部,又调用了factor自身

注意:递归代码务必要保证

存在递归结束条件,比如if n ==1 就是结束条件,当n为1的时候,递归就结束了

每次递归的时候,要保证函数的实参是逐渐逼近结束条件的

如果上述条件不能满足,就会出现无限递归,这是一种典型的代码错误

 


def factor(n):
    return n * factor(n-1)
result=factor(5)
print(result)

 Python系列-函数(下)_第5张图片

如前面所描述,函数调用时会在函数调用栈中记录每一层函数调用的信息

但是函数调用栈的空间不是无限大的,如果调用层数太多,就会超出栈的最大范围,导致出现问题

递归的优点:

递归类似于“数学归纳法”,明确初始条件,和递推公式,就可以解决一系列问题

递归代码往往代码量非常少

递归的缺点:

递归代码往往难以理解,很容易超出掌控范围

递归代码容易出现栈溢出的情况

递归代码往往可以转换成等价的循环代码,并且通常来说循环版本的代码执行效率略高于递归代码

参数默认值

Python中的函数,可以给形参指定默认值

带有默认值的参数,可以在调用的时候不传参

代码示例:


def add(x,y,debug=False):
    if debug:
        print(f'调试信息: x={x},y={y}')
    return x+y
print(add(10,20))
print(add(10,20,True))

此处debug=False即为参数默认值,当我们不指定第三个参数的时候,默认debug的取值即为False

带有默认值的参数需要放到没有默认值的参数的后面

 

def add(x,debug=False,y):
    if debug:
        print(f'调试信息: x={x},y={y}')
    return x+y
print(add(10,20))
print(add(10,20,True))

 

关键字参数

在调用函数的时候,需要给函数指定实参,一般默认情况下是按照形参的顺序,来依次传递实参的,但我们也可以通过关键字参数,来调整这里的传参顺序,显示指定当前实参给哪个形参。

 

def test(x,y):
    print(f'x={x}')
    print(f'y={y}')

test(x=10,y=20)
test(x=20,y=10)

 Python系列-函数(下)_第6张图片

形如上述test(x=10,y=20)这样的操作,即为关键字参数

小结

函数是编程语言中的一个核心语法机制,Python中的函数和大部分编程语言的函数功能都是非常重要的

我们当下最重要的就是三个点:

函数的定义

函数的调用

函数的参数传递

Python系列-函数(下)_第7张图片

 

你可能感兴趣的:(Python,python,开发语言)