点击上方的“小小白AI”,选择“关注”
重磅知识,第一时间送达
前言
在开始之前首先给大家道个歉,由于前段时间身边发生了很多事,好久没有更新了,对给大家带来的不方便,我想给大家说一声对不起。以后小小白一定
定时更新,望大家监督。
本文摘要
本文将继续在《Python入门06》的基础上给大家说一说python函数那点事~,主要包括:函数的定义、函数参数详解、作用域等三个部分。
一、函数的定义
1、python为什么要定义函数
每个人都时很懒的,作为一个优秀的程序猿,同样再写程序的时候也是,比如在某些场景下,需要多次计算一个等差数列,传统的方法是,每到需要的地方就写一个等差数列,如下所示,当程序中出现的次数比较多的时候,程序中将出现很多的重复的代码,即增加了我们的工作量,也降低了代码的可读性。
d=2
for i in range(10):
print(i+2)
那么为了能够解决上面这个问题,就出现了自定义函数这一概念。有了函数,你就可以根据名字直接调用它,给定输入得到想要的输出,免得自己重复去写冗长的代码,而且这样还可以增强代码的可读性。
2、怎么定义一个函数?
函数的定义主要是采用def关键字,例如要定义一个输出hello word的函数:
def helloword():
print(“helloword”)
当你在程序中,直接写helloword()的时候,当程序执行到这里的时候,你就会看到屏幕上会打印出来一行“hello word”。
二、函数参数详解
1、什么是函数的参数?
在def语句中,位于函数名后面的变量通常称为形参,而调用函数时提供的值称为实参,但这里基本上不对此做严格的区分,大家懂的形参和实参的概念就可以了。
2、上面的函数也没有输入输出啊,当给入输入需要输出的时候怎么办呢?
在定义函数的时候可以直接定义好输出,然后再程序中采用return关键字给出输出。例如,定义一个函数,输入为一个数字,输出为这个数字的二位的数。
def doublex(n):
return2*n
根据上面函数的定义,在调用函数的时候,需要有一个参数来接收函数doublex计算得到的值:例如在实际程序中可以这么写:
x=doublex(3)
print(x)
此时打印出来的数字就是:6
3、是不是所有的python函数都有返回值:
答案是确定的,当你没有告诉他们该返回什么的时候,那么它们将会返回None值。
重点提示:为了不让这么默认的行为带来麻烦,如果你在if之类的语句有返回值,请务必保证其分支也有返回值,以免再调用者期望函数返回一个序列时,不小心返回的时None。
4、什么是关键字参数?
我们前面使用的都是位置参数,一个参数在什么位置,都有这个参数的意思,但是python还有另外一种参数,那就是关键字参数:即使用参数的名称指定参数的数值,它主要的作用是有助于澄清各个参数的作用,这样函数的调用不再像下面这样怪异而神秘:
movetoxx(‘My file’,2,3)
可以像下面这样做:
Movetoxx(file=’My file’,times=2,id=3)
上面这样做虽然输入量多了一些,但是每个参数的作用清晰明了,而且参数的顺序错了也没有关系。
5、什么是收集参数?
有时候,允许用户提供任意数量的参数很有用。例如,每次只能存储一个姓名。如果能够像下面这样同时存储多个姓名就好了:
store(data, name1, name2,name3)
为此,应允许用户提供任意数量的姓名。可以这样的函数定义:
def print_params(*params):
print(params)
这里好像只指定了一个参数,但它前面有一个星号。这是什么意思呢?尝试使用一个参数来调用这个函数,看看结果如何。
print_params(1, 2, 3)
(1, 2, 3)
参数前面的星号将提供的所有值都放在一个元组中,也就是将这些值收集起来。
与赋值时一样,带星号的参数也可放在其他位置(而不是后),但不同的是,在这种情况 下你需要做些额外的工作:使用名称来指定后续参数。
def in_the_middle(x, *y, z):
print(x, y, z)
in_the_middle(1, 2, 3, 4, 5, z=7)
1 (2, 3, 4, 5) 7
>>> in_the_middle(1, 2, 3, 4, 5, 7)
Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: in_the_middle() missing 1 required keyword-only argument: 'z'
要收集关键字参数,可使用两个星号。
def print_params_3(**params):
print(params)
print_params_3(x=1, y=2, z=3)
{'z': 3, 'x': 1, 'y': 2}
如你所见,这样得到的是一个字典而不是元组。
6、什么是分配参数?
前面介绍了如何将参数收集到元组和字典中,但用同样的两个运算符(*和**)也可执行相 反的操作。与收集参数相反的操作是什么呢?假设有如下函数: def add(x, y):
return x + y
同时假设还有一个元组,其中包含两个你要相加的数。 params = (1, 2) 这与前面执行的操作差不多是相反的:不是收集参数,而是分配参数。这是通过在调用函数 (而不是定义函数)时使用运算符*实现的。
add(*params)
3
这种做法也可用于参数列表的一部分,条件是这部分位于参数列表末尾。通过使用运算符**, 可将字典中的值分配给关键字参数。如果你像前面那样定义了函数hello_3,就可像下面这样做:
params = {'name': 'Sir Robin', 'greeting': 'Well met'}
hello_3(**params)
Well met, Sir Robin!
三、函数作用域
python变量的作用域大概分为以下四类:
L(local) 局部作用域 E(Enclosing) 闭包函数外的函数中 G(Global) 全局作用域 B(Built-in) 内建作用域
遵循LEGB原则:以 L –> E –> G –>B 的规则查找,即:在局部找不到,便会去局部外的局部找(例如闭包),再找不到就会去全局找,再者去内建中找。
x = int(2.9) # 内建作用域
g_count = 0 # 全局作用域
def outer():
o_count = 1 # 闭包函数外的函数中
def inner():
i_count = 2 # 局部作用域
在python中,模块(module),类(class)、函数(def、lambda)会产生新的作用域,其他代码块是不会产生作用域的,也就是说,类似条件判断(if…..else)、循环语句(for x in data)、异常捕捉(try…catch)等的变量是可以全局使用的
dataList = [1, 2, 3, 4]
for data in dataList:
a = 1 #for循环中的变量a
b = data + a
print(a) #在函数外也可视为全局变量使用
全局变量是指在函数外的变量,可以在程序全局使用,局部变量是指定义在函数内的变量,只能在函数内被声明使用
若内部作用域的想要修改外部作用域的变量,就要使用global关键字:参考一下代码
1、未使用global关键字
a = 1
def demo(): a = 123 print(a) demo() print(a)
运行结果是1231
全局变量a的值还是1,没有被改变
2、使用global关键字
a = 1
def demo(): global a a = 123 print(a)
demo() print(a)运行结果是123123
全局变量a的值被修改
3、nonlocal 关键字的使用方法和global关键字类似,修改嵌套作用域(enclosing 作用域,外层非全局作用域)中的变量。
def outer(): num = 10 def inner(): nonlocal num # nonlocal关键字声明 num = 100 print(num) inner() print(num) outer()运行结果为
100
100
闭包函数外的变量num值被修改
参考文献:
[1]Beginning Python From Novice to Professional (Third Edition),
Magnus Lie Hetland.
希望上述内容能够帮助到正在学习的你~