从零开始学Python(第六天 ——函数)


在这里插入图片描述

第六天

概述:具有名称的能够完成某一特定功能的代码的集合;为了模块化的管理,即将不同功能的代码进行分类,个模块化之间要遵循高内聚,低耦合;

python中函数的定义

def function_name([args...]):
	函数体
	功能的集合
	[return 返回值] 可选

python中函数的调用;注意:调用函数与定义函数间空两行(潜规则)

	function_name()  

6.1 函数分类

定义有没有参数
无参函数
有参函数
函数的参数,要根据实际来决定,是否需要参数

定义是否有返回值
无返回值
有返回值
在函数中,当遇到return关键字的时候,函数会立刻返回

6.2 全局/局部变量

​ 全局变量:定义在模块(.py)中,可以在该模块定义后任何地方都可以访问;从程序的开始到结束都是可以被执行的变量
​ 局部变量:定义在函数内部的变量,作用域只是在当前函数内有效,出了函数,无法访问到

在函数中,能不能访问到全局变量?
	当然可以,但是注意:在python中,函数内不允许修改全局变量
如果确实在函数内,需要修改全局变量,必须要提前申明
	global 全局变量

例1:

name = "Eichi"
def print_best():
	name = "Owen"
	print(name)


print_best()
print(name)

执行结果:
Owen
Eichi

总结:把握就近原则,即在函数内部,会选择最近的局部变量name作为输出,别看两个变量的名称相同,其存储在执行栈的不同位置,下面会做详细的解释

例2:

name = "Eichi"

def print_best():
	name += "Owen"
	print(name)

print_best()
print(name)

执行后就会出错,如下,意思是没有绑定的本地变量错误:赋值前引用了局部变量“name”
Traceback (most recent call last):
  File "Class6全局局部变量.py", line 8, in <module>
    print_best()
  File "Class6全局局部变量.py", line 5, in print_best
    name += "Owen"
UnboundLocalError: local variable 'name' referenced before assignment
    
解决:在函数中对全局变量进行声明,这样就可以在函数内部进行修改了

name = "Eichi"
def print_best():
	global name
	name += "Owen"
	print(name)
    
    
print_best()
print(name)

执行结果:
EichiOwen
EichiOwen

总结:要想在函数中修改全局变量的值就要对全局变量进行声明

6.3 函数的调用

​ 压栈,函数调用本质就是将堆中的函数调用到栈中执行,这个过程被称为压栈,等函数执行完成,会立刻执行出栈(弹栈)

在这里插入图片描述

总结:

  1. 定义的函数是在堆中存储的
  2. 调用函数时,将堆中的存储的内容,放到执行栈中;此过程被称为压栈
  3. 等函数执行完成后,弹出栈,所以函数中的局部变量就被弹出去了,即不能访问,而全局变量从一开始就被压入执行栈中,所以何时都可以进行使用
  • ·此时就可以解释为什么在函数中不能修改全局变量的值了,全局变量存储在执行栈的函数下面,且随着程序的执行一直存储,而函数执行完成后就会被销毁,所以说不能修改,至于就近原则的产生是因为栈的存储结构决定的,即先进后出

6.4 参数

6.4.1 参数传递

  • 值传递:本质就是传递数据值的拷贝,跟原先的那个值没有关系;即弹栈后并不会修改全局变量的值
  • 引用传递:本质是传递指针(地址),所以说实质操作的就是堆,所以局部变量被回收后,由于堆空间的存在,还是可以使用的

例1:值传递

def change(x,y):
	x = 2 * x
	y = 3 * y
	print(x)
	print(y)


num1 = 10
num2 = 20
change(num1,num2)
print(num1)
print(num2)

执行结果:
20
60
10
20

例2:引用传递

def add_user(users):
	users.append("haha")
	users.append("hehe")


#ls本质上存储在堆内存中,所以执行栈中放的是地址
if __name__ == "__main__":
	ls = ["Eichi","Tong","1chen"]
	add_user(ls)
	print(ls)

执行结果:
['Eichi', 'Tong', '1chen', 'haha', 'hehe']

另外说明:

Python中的main函数主要作用:写在main函数的代码并不会被导入到其他模块中
注意:Python中的函数运行返回多个值,以元组形式进行返回

举例:
def change(x,y):
	x = 2 * x
	y = 3 * y
	return x, y


if __name__ == "__main__":
	num1 = 10
	num2 = 20
	res = change(num1,num2)
	print(res)

执行结果:
(20, 60)

6.4.2 参数分类

  • 默认值参数

    ​ 默认值参数,在定义函数时,给定一个最常用的值,在调用的时候,如果有实参,那就用实参,如果没有,就使用默认的

注意:默认值参数,必须放在普通后面!!!

例1:

def get_cricle_area(r, pi=3.14):
	return r * r * pi


print(get_cricle_area(3))
print(get_cricle_area(3,3.14))
print(get_cricle_area(3,3.1415))
print(get_cricle_area(3,3.1415926))

执行结果:
28.26
28.26
28.273500000000002
28.2743334
  • 可变参数

    ​ 顾名思义,参数是根据调用的实参的数量决定的

注意:args以元组的形式保存

例2:

def show(name, age, *args):
	print(name,age,*args)
	return args


res = show("Eichi",16,"love","viva","la","vida")
print(res)

执行结果:
Eichi 16 love viva la vida
('love', 'viva', 'la', 'vida')
  • 命名参数(关键字参数),即keyword参数
    注意:kwargs是以字典的形式保存

例3:

def show2(name, age, **kwargs):
	print(name)
	print(age)
	print(kwargs["address"])
	print(kwargs.get("height"))
	return kwargs

if __name__ == '__main__':
	kw = show2("Eichi", 20, gender="男", address="earth", height=1.90)
	print(kw)

执行结果:
Eichi
20
earth
1.9
{'gender': '男', 'address': 'earth', 'height': 1.9}

组合之万能参数,即扩展性极强

def show3(name, age, gender, *args, **kwargs):
	pass

6.5 函数递归

​ 函数自身调用自身
注意:必须要有终止条件,没有终止条件的递归是一个死循环,直到栈溢出为止

栈溢出:StackOverflowException
Python跑在操作系统中的
Java跑在虚拟机里的

栈空间:比较小的一块,只牵扯到地址的引用,但是递归时整个栈空间被疯狂的使用占据,如下图所示,若函数不停的调用自身,且没有中止条件,则会造成执行栈的空间溢出

在这里插入图片描述

注意:函数的递归在Python中是由限制的,默认不能超过1000次,此默认值可以修改

import sys


# python中规定递归默认不能超过1000次
print(sys.getrecursionlimit())
# 修改递归的默认极限值
sys.setrecursionlimit(10000)


def get_sum(n):
	# 递归必须要有终止条件,如果没有终止条件,递归就是一个死循环
	# 直到栈溢出为止
	if n == 1:
		return 1
	return n + get_sum(n - 1)


res = get_sum(100)
print(res)

执行结果:
1000
5050
import sys


# python中规定递归默认不能超过1000次
print(sys.getrecursionlimit())
# 修改递归的默认极限值
sys.setrecursionlimit(10000)


def get_sum(n):
	# 递归必须要有终止条件,如果没有终止条件,递归就是一个死循环
	# 直到栈溢出为止
	if n == 1:
		return 1
	return n + get_sum(n - 1)


res = get_sum(100)
print(res)

执行结果:
1000
5050

今天的内容到这里就结束了~ 需要做题巩固练习的,请保持关注,持续更新中ing

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值