Python3简明简称(八)—— 函数
我们经常需要在同一个程序里多次复用代码。函数可以很好的帮助我们完成这一点。我们在函数里写我们要重复做的事,然后我们在任何需要的时候调用它。我们已经看到一些内建的函数,比如 len(),divmod()。
定义一个函数
我们使用关键字 def 来定义一个函数,语法描述如下所示:
def 函数名(参数):
语句1
语句2
让我们编写一个函数,它将接受两个整数作为输入,然后返回总和。
>>> def sum(a, b):
... return a + b
第二行有个 return 关键字,我们把 a + b 的值返回给调用者。
你必须像下面这样调用这个函数。
>>> res = sum(234234, 34453546464)
>>> res
34453780698L
还记得我们上一个实验讲过的回文检查程序么,让我们编写一个函数来检查给出的字符串是否为回文,然后返回 True 或者 False。
#!/usr/bin/env python3
def palindrome(s):
return s == s[::-1]
if __name__ == '__main__':
s = input("Enter a string: ")
if palindrome(s):
print("Yay a palindrome")
else:
print("Oh no, not a palindrome")
关于if __name__ == '__main__'详情请见:
局部变量和全局变量
我们通过几个例子来弄明白局域或全局变量,首先我们在函数内部和函数调用的代码中都使用同一个变量 a,例如:
#!/usr/bin/env python3
def change():
a = 90
print(a)
a = 9
print("Before the function call ", a)
print("inside change function", end=' ')
change()
print("After the function call ", a)
运行结果:
rogn@ubuntu:~$ ./local.py
Before the function call 9
inside change function 90
After the function call 9
可见,当我们在函数里写 a = 90 时,它实际上创建了一个新的名为 a 的局部变量,这个变量只在函数里可用,并且会在函数完成时销毁。所以即使这两个变量的名字都相同,但事实上他们并不是同一个变量。
那么如果我们先定义 a,在函数中是否可以直接使用呢?例如下面这段代码:
#!/usr/bin/env python3
a = 9
def change():
print(a)
change()
这段代码是没有问题的,可以直接打印输出 9。但是稍微改动一下:
#!/usr/bin/env python3
a = 9
def change():
print(a)
a = 100
change()
现在就会报错了:“UnboundLocalError: local variable 'a' referenced before assignment”,原因是当函数中只要用到了变量 a,并且 a 出现在表达式等于号的前面,就会被当作局部变量。当执行到 print(a) 的时候会报错,因为 a 作为函数局部变量是在 print(a) 之后才定义的。
现在我们使用 global 关键字,对函数中的 a 标志为全局变量,让函数内部使用全局变量的 a,那么整个程序中出现的 a 都将是这个:
#!/usr/bin/env python3
a = 9
def change():
global a
print(a)
a = 100
print("Before the function call ", a)
print("inside change function", end=' ')
change()
print("After the function call ", a)
程序中的 end=' ' 参数表示,print 打印后的结尾不用换行,而用空格。默认情况下 print 打印后会在结尾换行。
程序执行的结果,不会报错了,因为函数体内可以访问全局的变量 a:
Before the function call 9
inside change function 9
After the function call 100
在函数内使用 global 会有什么作用呢?尝试下面的代码:
#!/usr/bin/env python3
def change():
global a
a = 90
print(a)
a = 9
print("Before the function call ", a)
print("inside change function", end=' ')
change()
print("After the function call ", a)
程序执行的结果:
Before the function call 9
inside change function 90
After the function call 90
这里通过关键字 global 来告诉 a 的定义是全局的,因此在函数内部更改了 a 的值,函数外 a 的值也实际上更改了。
默认参数值
函数的参数变量可以有默认值,也就是说如果我们对指定的参数变量没有给出任何值则会赋其默认值。
>>> def test(a , b=-99):
... if a > b:
... return True
... else:
... return False
在上面的例子里,我们在函数的参数列表写出 b = -99。这表示如果调用者未给出 b 的值,那么 b 的值默认为 -99。这是一个关于默认参数的非常简单的例子。
你可以通过调用函数测试代码:
>>> test(12, 23)
False
>>> test(12)
True
有两个非常重要的地方,第一个是具有默认值的参数后面不能再有普通参数,比如 f(a,b=90,c) 就是错误的。
第二个是默认值只被赋值一次,因此如果默认值是任何可变对象时会有所不同,比如列表、字典或大多数类的实例。例如,下面的函数在后续调用过程中会累积(前面)传给它的参数:
>>> def f(a, data=[]):
... data.append(a)
... return data
...
>>> print(f(1))
[1]
>>> print(f(2))
[1, 2]
>>> print(f(3))
[1, 2, 3]
要避免这个问题,你可以像下面这样:
>>> def f(a, data=None):
... if data is None:
... data = []
... data.append(a)
... return data
...
>>> print(f(1))
[1]
>>> print(f(2))
[2]
关键字参数
函数可以通过关键字参数的形式来调用,形如 keyword = value。如下:
>>> def func(a, b=5, c=10):
... print('a is', a, 'and b is', b, 'and c is', c)
...
>>> func(12, 24)
a is 12 and b is 24 and c is 10
>>> func(12, c = 24)
a is 12 and b is 5 and c is 24
>>> func(b=12, c = 24, a = -1)
a is -1 and b is 12 and c is 24
在上面的例子中你能看见调用函数时使用了变量名,这样能够对指定的参数赋值。
强制关键字参数
我们也能将函数的参数标记为只允许使用关键字参数。用户调用函数时将只能对每一个参数使用相应的关键字参数。
>>> def hello(*, name='User'):
... print("Hello", name)
...
>>> hello('shiyanlou')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: hello() takes 0 positional arguments but 1 was given
>>> hello(name='shiyanlou')
Hello shiyanlou
了解更多,请阅读PEP-3102。
文档字符串
在 Python 里我们使用文档字符串(docstrings)来说明如何使用代码,即写一些与代码上下文无关的、起解释说明作用的字符串。这在交互模式非常有用,也能用于自动创建文档。下面我们来看看使用文档字符串的例子。
#!/usr/bin/env python3
import math def longest_side(a, b):
"""
Function to find the length of the longest side of a right triangle. :arg a: Side a of the triangle
:arg b: Side b of the triangle :return: Length of the longest side c as float
"""
return math.sqrt(a*a + b*b) if __name__ == '__main__':
print(longest_side.__doc__)
print(longest_side(4,5))
高阶函数
高阶函数(Higher-order function)或仿函数(functor)是可以接受函数作为参数的函数:
- 使用一个或多个函数作为参数
- 返回另一个函数作为输出
Python 里的任何函数都可以作为高阶函数,下面举一个简单的例子:
# 创建一个函数,将参数列表中每个元素都变成全大写
>>> def high(l):
... return [i.upper() for i in l]
...
# 创建高阶函数,接受一个函数和一个列表作为参数
>>> def test(h, l):
... return h(l)
...
>>> l = ['python', 'Linux', 'Git']
# 运行高阶函数,返回预期的结果
>>> test(high, l)
['PYTHON', 'LINUX', 'GIT']
阅读官方文档了解更多。
map函数
map 是一个在 Python 里非常有用的高阶函数。它接受一个函数和一个序列(迭代器)作为输入,然后对序列(迭代器)的每一个值应用这个函数,返回一个序列(迭代器),其包含应用函数后的结果。
>>> lst = [1, 2, 3, 4, 5]
>>> def square(num):
... return num * num
...
>>> map(square, lst)
<map object at 0x7fd8043302b0>
>>> list(map(square, lst))
[1, 4, 9, 16, 25]
>>> tuple(map(square, lst))
(1, 4, 9, 16, 25)
总结
经过本实验应当知道如何定义函数,局域变量和全局变量一定要弄清楚,参数默认值、关键字参数也需要掌握。
另外,其它高级语言常见的函数重载,Python 是没有的,这是因为 Python 有默认参数这个功能,函数重载 的功能大都可以使用默认参数达到。
在后面我们还介绍了高阶函数的概念并使用了 map() 函数。在 Python 中还有其它的高阶函数,如 sorted()、filter() 以及 functools 模块中的函数,大家可以了解一下。
参考链接:https://www.shiyanlou.com/courses/596
Python3简明简称(八)—— 函数的更多相关文章
- 从零开始学习PYTHON3讲义(八)列表类型跟冒泡排序
<从零开始PYTHON3>第八讲 前面我们见过了不少的小程序,也见过了不少不同类型的变量使用的方法.但目前我们涉及到的,还都是单个的变量和单个的立即数.以变量来说,目前我们见到的,基本都 ...
- Python3中的字符串函数学习总结
这篇文章主要介绍了Python3中的字符串函数学习总结,本文讲解了格式化类方法.查找 & 替换类方法.拆分 & 组合类方法等内容,需要的朋友可以参考下. Sequence Types ...
- python3中的 zip()函数 和python2中的 zip()函数 的区别
python3中的 zip()函数 和python2中的 zip()函数 的区别: 描述: zip() 函数用于将可迭代对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的对象. ...
- python3中的range函数返回的是列表吗?
注意,这里说的Python3里面的range函数,和Python2是不同的,返回的不是列表,是可迭代对象. 在python3中,如果执行下面的语句 print(range(10)) 得到结果是 ran ...
- Python3 matplotlib的绘图函数subplot()简介
Python3 matplotlib的绘图函数subplot()简介 一.简介 matplotlib下, 一个 Figure 对象可以包含多个子图(Axes), 可以使用 subplot() 快速绘制 ...
- Python3.x:zip()函数
Python3.x:zip()函数 1,概述: zip函数接受任意多个(包括0个和1个)序列作为参数,返回一个tuple列表: 2,示例: (1).示例1: x = [1, 2, 3] y = [4, ...
- Python3 urllib.parse 常用函数示例
Python3 urllib.parse 常用函数示例 http://blog.51cto.com/walkerqt/1766670 1.获取url参数. >>> from url ...
- python3.7 内置函数整理
#!/usr/bin/env python __author__ = "lrtao2010" #python3.7 内置函数整理 #abs(x) #返回数字的绝对值. 参数可以是整 ...
- (转)Python3的四舍五入round()函数坑爹?不,更科学!
原文:https://blog.csdn.net/lly1122334/article/details/80596026 Python3的四舍五入round()函数坑爹?不,更科学!Python2中, ...
随机推荐
- NOIP2007普及 守望者的逃离
传送门 普及组的题目……很水. 原来写了一个模拟不过好像状态考虑的不全得了80,这次我们考虑一下dp做法. 守卫者有两种移动的方法,一种是闪现,一种是跑,我们可以把闪现和跑分开处理. 首先只处理闪现的 ...
- bzoj 4756 Promotion Counting —— 线段树合并
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4756 合并子树的权值线段树: merge 返回 int 或者是 void 都可以. 代码如下 ...
- bzoj 1098 办公楼biu —— 链表+栈
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1098 首先,没有连边的人一定得在一个连通块里: 先把所有人连成一个链表,然后从第一个人开始, ...
- 012--python字符编码和list列表和循环语句
一.字符编码: ASCII码最多只能表示 256个符号,每一个字符占8位 为什么一个字节占8位?因为计算机在读一串二进制数111011001111101110的时候, 要按照规定的长度截取,才能分清一 ...
- sql常识性误解
今天在公司一个项目,遇到一个问题,最后解决下来竟然发现自己对sql竟然存在一个常识性的误解 表数据 需求如下 查找 name中的数据被参数 'adsb' 包含的的列 个人原先的误区一直在于一个认识, ...
- Codeforces686C【dfs】
题意: n,m<=1e9 设定一天n小时,一小时m分钟, 显示时间的是一个7进制的表, 问你在一天里出现多少个时刻,表中的数字要都不相同. 思路: 因为7进制,显示的数字肯定是0-7之间的. 然 ...
- <TLE>奇偶剪枝hdoj1010
(奇偶剪枝)转自百度百科,讲的非常棒: http://baike.baidu.com/link?url=3g5bW7LszRVOVvFDFp6cL0ZZnAaOLUdpaNjc2leHoxkKU9Eh ...
- bzoj 4871: [Shoi2017]摧毁“树状图”【树形dp】
做不来--参考https://www.cnblogs.com/ezyzy/p/6784872.html #include<iostream> #include<cstdio> ...
- bzoj 4240: 有趣的家庭菜园【树状数组+贪心】
以为是逆序对数-- 实际上,原数组移动若干次后我们会得到一个新的下标序列,需要的移动次数是这个新下标序列的逆序对数 然后我们要让这个最小,考虑贪心先按h把下标排一遍序,然后每次询问到一种值的时候,对每 ...
- spark 机器学习 朴素贝叶斯 原理(一)
朴素贝叶斯算法仍然是流行的挖掘算法之一,该算法是有监督的学习算法,解决的是分类问题,如客户是否流失.是否值得投资.信用等级评定等多分类问题.该算法的优点在于简单易懂.学习效率高.在某些领域的分类问题中 ...