今天来学习python函数,对于有java基础的我来说那岂不是手到擒来
既然已经有java基础了,那么首先我想到的就是两个问题
- python如何定义函数
- python如何调用函数
python中如何定义函数,于是我打开了GitHub上骆昊大神的教程
定义如下:
在Python中可以使用def
关键字来定义函数,和变量一样每个函数也有一个响亮的名字,而且命名规则跟变量的命名规则是一致的。在函数名后面的圆括号中可以放置传递给函数的参数,这一点和数学上的函数非常相似,程序中函数的参数就相当于是数学上说的函数的自变量,而函数执行完成后我们可以通过return
关键字来返回一个值,这相当于数学上说的函数的因变量。
我们来回忆一下Java方法的定义
修饰符 返回值类型 方法名(参数类型 参数名){
...
方法体
...
return 返回值;
}
而Python函数的定义
def 方法名(参数名):
...
方法体
...
return 返回值
我们可以看到Python中函数的定义比Java中精简了很多
学着这个样子,我们来定义一个函数
def sum(a, b):
return a + b
嗯....,函数定义确实很简单
接下来我们来调用上面定义的函数:
def sum(a, b):
return a + b
if __name__ == '__main__':
print(sum(2, 3))
控制台输出:
既然我们函数的定义和调用都学会了,那到这我们难道就学会Python的函数了吗?
我们再将上面的代码修改一下
def sum(a = 3, b = 4):
return a + b
if __name__ == '__main__':
print(sum(2, 3))
什么,函数的形参竟然设置了默认值?
那我们跑一下代码,看一下结果是多少
结果还是5,那我们换一种调用方式
def sum(a = 3, b = 4):
return a + b
if __name__ == '__main__':
print(sum())
控制台输出一下:
吆西,竟然换成了7,也就是说如果我们调用函数的时候没有给参数传值,那么这种情况函数就会使用在函数定义中设置的默认值,那么我们如果调用的时候既没有给参数传值,定义函数的时候也没有设置默认值呢?
def sum(a, b):
return a + b
if __name__ == '__main__':
print(sum())
没错!报错了
我们发现原来python是可以给函数设置默认值的,重点!!!!
而回到java,java是不能给方法的参数设置默认值的,至于原因,是因为“默认参数”和“方法重载”同时支持的话有二义性的问题,Java可能为了简单就不要“默认参数”了。当然使用“方法重载”可以间接实现”默认参数“的效果。
我们把所有情况都实现一遍
def add(a=0, b=0, c=0):
"""三个数相加"""
return a + b + c
if __name__ == '__main__':
print(add())
print(add(1))
print(add(1, 2))
print(add(1, 2, 3))
# 传递参数时可以不按照设定的顺序进行传递
print(add(c=50, a=100, b=200))
控制台输出:
好,我们现在已经学会了函数的定义和调用, 下面来练习几个题目
1.实现计算求最大公约数和最小公倍数的函数
答案:
def gcd(a, b):
if(a > b):
a, b = b, a
for factor in range(a, 0, -1):
if(a % factor == 0 and b % factor == 0):
return factor
def lcm(a, b):
return a * b // gcd(a, b)
if __name__ == '__main__':
a = int(input('请输入正整数a:'))
b = int(input('请输入正整数b:'))
print('%d和%d的最大公约数为%d' % (a, b, gcd(a, b)))
print('%d和%d的最小公倍数为%d' % (a, b, lcm(a, b)))
控制台输出:
2.实现判断一个数是不是回文数的函数
答案:
def is_palindrome(n):
temp = num
total = 0;
while(temp != 0):
total = total * 10 + temp % 10
temp //= 10
return num == total
if __name__ == '__main__':
num = int(input('请输入一个整数:'))
print(is_palindrome(num))
控制台输出:
通过这两个题我们似乎已经学会了函数的定义和调用,那么我们接下来要学习什么呢?
我们先来写一段代码:
def Print(n):
print(a)
print(n)
if __name__ == '__main__':
a = 10
Print(20)
控制台输出一下:
什么,这竟然没有报错,这要是在java妥妥的报错啊!
究竟是什么情况?
没错,我们接下来要讲的就是python函数变量的作用域
我们再写一段代码:
def foo():
b = 'hello'
# Python中可以在函数内部再定义函数
def bar():
c = True
print(a)
print(b)
print(c)
bar()
# print(c) # NameError: name 'c' is not defined
if __name__ == '__main__':
a = 100
# print(b) # NameError: name 'b' is not defined
foo()
控制台输出一下:
上面的代码能够顺利的执行并且打印出100、hello和True,但我们注意到了,在bar
函数的内部并没有定义a
和b
两个变量,那么a
和b
是从哪里来的。
我们在上面代码的if
分支中定义了一个变量a
,这是一个全局变量(global variable),属于全局作用域,因为它没有定义在任何一个函数中。
在上面的foo
函数中我们定义了变量b
,这是一个定义在函数中的局部变量(local variable),属于局部作用域,在foo
函数的外部并不能访问到它;但对于foo
函数内部的bar
函数来说,变量b
属于嵌套作用域,在bar
函数中我们是可以访问到它的。
bar
函数中的变量c
属于局部作用域,在bar
函数之外是无法访问的。
事实上,Python查找一个变量时会按照“局部作用域”、“嵌套作用域”、“全局作用域”和“内置作用域”的顺序进行搜索,前三者我们在上面的代码中已经看到了,所谓的“内置作用域”就是Python内置的那些标识符,我们之前用过的input
、print
、int
等都属于内置作用域。
那么到这里我们会思考一个问题,既然我们在函数中可以访问到全局变量,那么我们是否可以在函数中修改全局变量呢,这在java中是不能实现的!
我们来设计代码:
def foo():
a = 20
print(a)
if __name__ == '__main__':
a = 10
foo()
print(a)
控制台输出一下:
嗯?好像不行
难道在python中只能在函数中访问到全局变量,但是却不能改变全局变量吗?
答案是否定的!
在调用foo
函数后,我们发现a
的值仍然是10,这是因为当我们在函数foo
中写a = 20
的时候,是重新定义了一个名字为a
的局部变量,它跟全局作用域的a
并不是同一个变量,因为局部作用域中有了自己的变量a
,因此foo
函数不再搜索全局作用域中的a
。如果我们希望在foo
函数中修改全局作用域中的a
,那么代码可以这么写:
def foo():
global a
a = 20
print(a)
if __name__ == '__main__':
a = 10
foo()
print(a)
控制台输出一下:
成功!
我们可以使用global
关键字来指示foo
函数中的变量a
来自于全局作用域,如果全局作用域中没有a
,那么下面一行的代码就会定义变量a
并将其置于全局作用域。
同理,如果我们希望函数内部的函数能够修改嵌套作用域中的变量,可以使用nonlocal
关键字来指示变量来自于嵌套作用域
我们来设计代码:
def foo():
a = 10
def bar():
nonlocal a
a = 20
print(a)
bar()
print(a)
if __name__ == '__main__':
foo()
控制台输出:
好的,现在我们已经了解了函数参数的作用域的知识,下面这段话送给大家:
在实际开发中,我们应该尽量减少对全局变量的使用,因为全局变量的作用域和影响过于广泛,可能会发生意料之外的修改和使用,除此之外全局变量比局部变量拥有更长的生命周期,可能导致对象占用的内存长时间无法被垃圾回收。
通过今天的学习,已经对python中函数的定义和调用,以及函数参数的作用域已经大致了了解,学会了这些东西,在日常使用中,我们就基本可以应付了,这篇文章参考了GitHub上驼昊的python教程,最近我也正通过他的教程来学习python,如果对python感兴趣的同学,可以去GitHub上自行学习,散会!