我们经常需要在同一个程序里多次复用代码。函数可以很好的帮助我们完成这一点。我们在函数里写我们要重复做的事,然后我们在任何需要的时候调用它。我们已经看到一些内建的函数,比如 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. 【POJ 1061】 青蛙的约会

    [题目链接] 点击打开链接 [算法] 列出同余方程,然后用exgcd求解 [代码] #include <algorithm> #include <bitset> #includ ...

  2. bzoj2973石头游戏——矩阵乘法

    题目:权限题! 写了一下,但提交不了,先放着吧. 代码如下: #include<iostream> #include<cstdio> #include<cstring&g ...

  3. cocos2dx常见32种场景切换动画

    bool HelloWorld::init() { ////////////////////////////// // 1. super init first if ( !CCLayer::init( ...

  4. bootstrap-Glyphicons 字体图标

    使用的方法: 1 引入 font-awesome.css文件 2 fonts文件夹  Bootstrap 假定所有的图标字体文件全部位于 ../fonts/ 目录内(可以在font-awesome.c ...

  5. py-day15_css+js_初

    css+js_初 一.鼠标移动变色 <!DOCTYPE html> <html lang="en"> <head> <meta chars ...

  6. 字符指针unsigned char *ch_p

    指向类型为unsigned char的指针变量叫字符指针. 例如: unsigned char ch = 'a'; unsigned char *ch_p = &ch;那么指针变量ch_p就是 ...

  7. C++ 多项目dll调用-隐式

    将DAA人脸检测做成动态库以便其他程序调用,采用隐式调用完成. 给出部分关于dll制作的关键代码: 1.DLL 多项目DLL编写注意将其他相关项目设置成静态库,以及各库涉及的版本一致性. DLL.h ...

  8. OpenCV视频的读写

    实验室的项目是处理视频,所以就从视频的读取和写入开始吧! 常用的接口有C++和Python,Python肯定要简洁许多,不过因为项目需要,还是用C++了(PS:其实是我被Python的速度惊到了... ...

  9. Node学习图文教程之express重写留言本案例

    写在前面 小伙伴们大家好,我是你们的pubdreamcc,接着前面的学习,这篇博文出至于我的GitHub仓库:Node学习教程资料,如果你觉得对你有帮助,欢迎star,你们的点赞是我持续更新的动力,谢 ...

  10. 51nod 1247 可能的路径(gcd)

    传送门 题意 略 分析 有以下结论 \(1.(x,y)->(y,x)\) \(2.(x,y)->(a,b)==>(a,b)->(x,y)\) 证明 做如下变换 \((a,b)- ...