
python 学习笔记(3)——函数和模块
Contents [hide]
函数和模块
函数
函数定义
在 Python 中可以使用 def
关键字来定义函数,同样是用 return
关键字返回一个值(这里真的不要再有 return(a)
这种写法了!)。
一个简单的应用如下:(来自原文)
这里的函数就是求取阶乘的函数,这个程序也就是在计算 (mn)。
当然实际上很多简单的函数 Python 的各种模块中已经有了,所以实际应用中往往不会选择自己写。
函数参数
Python 对于函数参数的处理比较特别。
Python 中,函数参数可以有默认值,也支持使用可变参数。
比如:
其中第二次调用就是表示 n 取默认值 10 的调用。
再比如:(来自原文)
这种写法是 C/C++ 等其他一些语言不那么容易实现的。
模块
用模块管理函数
对于一种编程语言(其实不止编程)来说,起名字很让人头疼。
最简单的就是同一个 .py
文件中定义了多个同名函数,这会导致后面的定义覆盖前面的。
这导致同名函数只能存在一个。
所以这个时候我们就可以通过模块的管理来解决这个问题。
我们有两个模块:
module1.py
module2.py
然后在 test.py
中可以这样使用:
也可以这样:
特别说明一点,如果导入的模块中除了定义函数之外,还有可执行代码,那么解释器导入模块时,就会执行这些代码,但是这往往是与我们希望相悖的。所以如果有这种可执行代码,最好加入如下判断:(来自原文)
说明:这里的
pass
语句只是一个占位语句,不做任何事情,一般用于填充尚未想好怎么实现的程序部分。(比如空函数中写pass
保证不报错)
变量作用域(原文重点)
首先注意函数内部定义函数的特殊用法。
上面代码可以顺利输出 100
、hello
、True
的结果,然而,在函数 bar()
,我们实际上并没有定义过 a
和 b
。
上面代码中 if
语句下定义了一个变量 a
,这是一个全局变量(global variable),属于全局作用域,因为其没有定义在任何的函数中。在上面的 foo()
函数中定义了变量 b
,这是一个定义在函数中的局部变量(local variable),属于局部作用域,在本函数外部无法访问。而对于 foo()
函数内部的 bar()
函数来说,变量 b
属于嵌套作用域,在 bar()
函数中依然可以访问。而 bar()
函数中的变量 c
属于局部作用域,外部都无法访问。
事实上,Python 查找一个变量会按照局部作用域、嵌套作用域、全局作用域和内置作用域的顺序进行搜索,所谓内置作用域就是 Python 内置的标识符,之前用过的 input
、print
、int
都属于内置作用域。
但注意,下面程序中,函数是新定义了一个局部变量而不是修改了全局变量:
如果想要在函数中改变全局变量而不是新建,需要使用 global
关键字。
函数需要修改为:
这代表使用 global
关键字来指示 foo()
函数中的变量 a
来自于全局作用域,如果全局作用域中没有定义 a
,后面就会新定义一个变量 a
并设置其作用域为全局作用域。同样还可以使用 nonlocal
关键字来指示变量来自于嵌套作用域。
一般实际开发中,应该尽量减少全局变量使用,其诸多好处就不说了。
想要延长函数中局部变量的生命周期需要使用闭包,当然这个这里不会讲。
最后作者给了一个良好的写法习惯:
可以学习一下。
原文“精选”习题
- 使用辗转相除法和递归求取两数的最大公约数:此处不提供参考程序。
- 写一个程序判断输入的正整数是不是回文素数:请用两个函数分别判断是否是素数和是否是回文数。
No Comments