我们经常需要在同一个程序里多次复用代码。函数可以很好的帮助我们完成这一点。我们在函数里写我们要重复做的事,然后我们在任何需要的时候调用它。我们已经看到一些内建的函数,比如 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简明简称(八)—— 函数的更多相关文章

  1. 从零开始学习PYTHON3讲义(八)列表类型跟冒泡排序

    <从零开始PYTHON3>第八讲 ​前面我们见过了不少的小程序,也见过了不少不同类型的变量使用的方法.但目前我们涉及到的,还都是单个的变量和单个的立即数.以变量来说,目前我们见到的,基本都 ...

  2. Python3中的字符串函数学习总结

    这篇文章主要介绍了Python3中的字符串函数学习总结,本文讲解了格式化类方法.查找 & 替换类方法.拆分 & 组合类方法等内容,需要的朋友可以参考下. Sequence Types ...

  3. python3中的 zip()函数 和python2中的 zip()函数 的区别

    python3中的 zip()函数 和python2中的 zip()函数 的区别: 描述: zip() 函数用于将可迭代对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的对象. ...

  4. python3中的range函数返回的是列表吗?

    注意,这里说的Python3里面的range函数,和Python2是不同的,返回的不是列表,是可迭代对象. 在python3中,如果执行下面的语句 print(range(10)) 得到结果是 ran ...

  5. Python3 matplotlib的绘图函数subplot()简介

    Python3 matplotlib的绘图函数subplot()简介 一.简介 matplotlib下, 一个 Figure 对象可以包含多个子图(Axes), 可以使用 subplot() 快速绘制 ...

  6. Python3.x:zip()函数

    Python3.x:zip()函数 1,概述: zip函数接受任意多个(包括0个和1个)序列作为参数,返回一个tuple列表: 2,示例: (1).示例1: x = [1, 2, 3] y = [4, ...

  7. Python3 urllib.parse 常用函数示例

    Python3 urllib.parse 常用函数示例 http://blog.51cto.com/walkerqt/1766670  1.获取url参数. >>> from url ...

  8. python3.7 内置函数整理

    #!/usr/bin/env python __author__ = "lrtao2010" #python3.7 内置函数整理 #abs(x) #返回数字的绝对值. 参数可以是整 ...

  9. (转)Python3的四舍五入round()函数坑爹?不,更科学!

    原文:https://blog.csdn.net/lly1122334/article/details/80596026 Python3的四舍五入round()函数坑爹?不,更科学!Python2中, ...

随机推荐

  1. class.forName()和.class有什么区别?

    class.forName()会初始化类的成员(静态的),最先加载的是类的静态成员变量,然后是静态代码块. 访问常量并不会导致类的初始化,但是访问静态成员会.

  2. k-means 算法介绍

    概述 聚类属于机器学习的无监督学习,在数据中发现数据对象之间的关系,将数据进行分组,组内的相似性越大,组间的差别越大,则聚类效果越好.它跟分类的最主要区别就在于有没有“标签”.比如说我们有一组数据,数 ...

  3. HDOJ2955 0/1背包的价值和重量

    [hdoj2955] 1.概率问题: 计算逃跑率,但是要变成相×的 2.背包处理问题 然后因为率不能作为那个重量,所以价值作为重量,求一个在每个价值下的最大的逃跑率,然后在给定的逃跑率下面,来一个su ...

  4. bzoj 4036: [HAOI2015]按位或【min-max容斥+FWT】

    其实也不是FWT--我也不知道刷FWT专题问什么会刷出来这个东西 这是min-max容斥讲解:https://www.zybuluo.com/ysner/note/1248287 总之就是设min(s ...

  5. bzoj 3811: 玛里苟斯【线性基+期望dp】

    这个输出可是有点恶心啊--WA*inf,最后抄了别人的输出方法orz 还有注意会爆long long,要开unsigned long long 对于k==1,单独考虑每一位i,如果这一位为1则有0.5 ...

  6. iOS 上传的图片在HTML上显示时,图片方向信息(EXIF Orientation)异常

    将iPhone 6s拍摄的照片上传到服务器之后, 在Web网页上看到图片被逆时针旋转了90度, 这让我很惆怅呐! 出现这个问题其实是因为上传的图片为.jpg格式,.jpg文件含有EXIF信息, 其中E ...

  7. c++ 头文件路径选择

    单文件引用头文件./ 当前目录 ../ 父级目录 / 根目录              多文件引用头文件多文件引用头文件 定义单独放在cpp文件里面 ,声明放在().h)里面

  8. nginx重写模块

    参考:http://nginx.org/en/docs/http/ngx_http_rewrite_module.html 1 语法 Syntax: if (condition) { ... } De ...

  9. Hdu 5439 Aggregated Counting (2015长春网络赛 ACM/ICPC Asia Regional Changchun Online 找规律)

    题目链接: Hdu 5439 Aggregated Counting 题目描述: 刚开始给一个1,序列a是由a[i]个i组成,最后1就变成了1,2,2,3,3,4,4,4,5,5,5.......,最 ...

  10. 牛客国庆集训派对Day_4~6

    Day_4 A.深度学习 题目描述 小 A 最近在研究深度学习,他自己搭建了一个很牛逼的神经网络,现在他手头一共有 n 组训练数据,一开始他会给自己的神经网络设置一个 batch size,假设为 B ...