Python的函数

目录

1.函数的作用域

2.函数的执行过程

3.链式调用

4.局部变量的函数栈帧

5.函数的递归

6. 函数形参的默认值

7.函数的关键字参数


1.函数的作用域


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

x,y=getPoint()
print(x,y)

变量的作用域:一个变量名有效范围是一定的,只是在一个固定的范围内生效。

函数内部的变量名,只能在函数内部生效,出了函数就无效了。

函数内部和函数外部是可以使用同名的变量的,虽然变量名相同,但是是不同的变量。

x=10

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

test()

在函数体里面找不到x就会在全局变量中查找

可以用global关键字声明全局变量x

#使用这个函数,把全局变量x改成20
def test():
    x=20

test()
print(f'x={x}')
#使用这个函数,把全局变量x改成20
def test():
    global x
    x=20

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

没有global,此时就会把x=20,当作是函数内部创建了一个局部变量x

而实际上是要修改全局变量x,为了让函数知道里面的x是个全局变量,就使用global关键字声明一下。


if,else,while,for这些关键字也会引入代码块,但是这些代码块不会对变量的作用域产生影响,在上述语句代码块内部定义的变量,可以在外面被访问。

例子:

for i in range(1,11):
    print(i)

print('--------------------------')
print(i)
if True:
    x=10

print(x)

2.函数的执行过程

执行到函数调用的时候,就会跳转到函数体内来进行执行。

当函数内部执行完毕(运行完了/遇到return),就回到之前调用的位置,继续往下执行。

代码调试:调试执行,相比于正常的运行,最大的区别就是可以随时停下来,方便程序员观察程序的中间过程。

step into 就是单步运行,并且遇到咱们自己的函数,能进入到函数里面。

3.链式调用

用一个函数的返回值作为一个函数的参数。

链式调用:先执行()里面的函数,后执行外面的函数,调用一个函数,就需要先对他的参数求值。

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

def add(x,y):
    return x*y


#result =isOdd(10)
#print(result)

print(isOdd(add(5,5)))

4.嵌套调用(一个函数体内部调用其他函数)

def a():
    print('函数 a')

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

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

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

d()

 先打印在调用


先调用再打印

def a():
    print('函数 a')

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


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


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

d()

 

4.局部变量的函数栈帧

调试器的左下角,能够看到函数之间的调用栈

每一层的调用关系就称为“函数的栈帧”,每个函数的局部变量就在这个栈帧中体现。

每一层的栈帧,你选中之后,都能看到里面的局部变量,每个函数的局部变量都保存在对应的栈帧中。

调用函数,则生成对应的栈帧。函数结束,则对应的栈帧消亡(里面的局部变量也就没了)

def a():
    num=10
    print('函数 a')

def b():
    num=20
    a()
    print('函数 b')


def c():
    num=30
    b()
    print('函数 c')


def d():
    num=40
    c()
    print('函数 d')

d()

这几个num虽然同名,但不是一个变量。

每个变量也是保存在各自的栈帧中的,每个栈帧也是保存在内存上的。

变量本质就是一块内存空间。

5.函数的递归

函数递归:一个函数自己调用自己

写一个函数求n的阶乘:

#写一个函数,来求n的阶乘(n是正整数)
#循环的方法
def factor(n):
    result =1
    for i in range(1,n+1):
        result *=i
    return result


#递归的方法 n! =>n*(n-1)!
#1! =>1
def factor(n):
    if n==1:
        return 1
    return n*factor(n-1)


print(factor(5))

递归代码的两个要素:

1.递归的结束条件

2.递归的递推公式

递归的缺点:

1.执行过程非常复杂,难以理解。

2.递归代码容易出现“栈溢出”的情况。

代码不小心写错了,导致每次递归,参数不能正确的接近递归的结束条件,出现无限递归的情况。

3.递归代码一般都是可以转换成等价的循环代码的,并且,循环的版本通常运行速度要比递归版本有优势。(函数调用也是有开销的)

递归的优点:

代码非常简洁!(处理一些问题本身就是通过递归方式定义的)

6. 函数形参的默认值

在函数内部加上打印信息,方便我们进行调试

但是调试信息我们希望在正式发布的时候不要有,加上一个布尔类型debug

def add(x,y,debug):
    if debug:
        print(f'x={x},y={y}')
    return x+y

#开启打印
result =add(10,20,True)
print(result)
def add(x,y,debug=False):
    if debug:
        print(f'x={x},y={y}')
    return x+y

#开启打印
result =add(10,20)
print(result)

def add(x,y,debug=False):
    if debug:
        print(f'x={x},y={y}')
    return x+y

#开启打印
result =add(10,20,True)
print(result)

debug=False

形参的默认值,带有默认值的形参,就可以在调用函数的时候,不必传参。


要求带有默认值的形参,得在形参列表的后面,而不能在前面/中间。

7.函数的关键字参数

关键字传参:按照形参得名字来进行传参!

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

test(x=10,y=20)

 非常明显的告诉程序员,你的参数要传给谁!

另外可以无视形参和实参的顺序!


位置参数和关键字参数还能混着用,只不过混着用的时候要求位置参数在前,关键字参数在后。

一个函数,可以提供很多的参数,来实现对这个函数内部功能做出一些调整设定,为了降低调用者的使用成本,就可以把大部分参数设定出默认值。

当调用者需要调整其中一部分参数的时候,就可以搭配关键字参数来进行操作。

函数小结:

函数的定义

函数的调用

函数的参数传递流程

函数的执行流程

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值