函数

定义函数

语法

  1. # def + 函数的名字 + (参数)
  2. def functionname( parameters ):
  3. "函数_文档字符串"
  4. function_suite
  5. return [expression]

举个例子:

  1. def sum( a,b ):
  2. c = a + b
  3. return c

这个函数的意思就是,接受两个参数ab,在函数中定义一个变量c,令这个变量c等两个参数之和,最后把这个c返回。
所以这个函数本质上是用于返回一个,不知道什么是返回值看下面的调用。

调用函数

  1. def sum( a,b ):
  2. c = a + b
  3. return c
  4. number = sum(1,2)
  5. print(number)
  6. # 2

同样这里需要注意缩进

可以看到,这里直接让number=sum(1,2),把这两个参数代入一开始定义的函数当中去,会发现这个时候c=2,也就是说这一条赋值的语句的真正意思应该是number = c =2。但是这里直接把c省略,所以这里number直接就等于2.

定义空函数

如果想定义一个什么事也不做的空函数,可以用pass语句

  1. def nop():
  2. pass

返回多个值

  1. def move(x, y, step ):
  2. nx = x + step
  3. ny = y + step
  4. return nx, ny
  5. x,y =move(1,2,3)
  6. print(x,y)
  7. # 4 5

参数传递(重点)

可更改和不更改对象

在 python 中,**字符串, 元组, 和数字**不可更改的对象,而 **数组,字典** 等则是可以修改的对象

  • 不可变类型:变量赋值 a=5 后再赋值 a=10,这里实际是新生成一个 int 值对象 10,再让 a 指向它,而 5 被丢弃,不是改变a的值,相当于新生成了a。
  • 可变类型:变量赋值 la=[1,2,3,4] 后再赋值 la[2]=5 则是将 list la 的第三个元素值更改,本身la没有动,只是其内部的一部分值被修改了。

python 函数的参数传递:

  • 不可变类型:类似 c++ 的值传递,如 整数、字符串、元组。如fun(a),传递的只是a的值,没有影响a对象本身。比如在 fun(a)内部修改 a 的值,只是修改另一个复制的对象,不会影响 a 本身。
  • 可变类型:类似 c++ 的引用传递,如 列表,字典。如 fun(la),则是将 la 真正的传过去,修改后fun外部的la也会受影响。

简单来说,字符串, 元组, 和数字 作为参数传入的时候,不改变参数原本的值。 数组,字典 作为参数传入的时候,改变参数原本的值。

  1. 举个例子:

传入不可变类型
  1. def ChangeInt( a ):
  2. a = 10
  3. b = 2
  4. ChangeInt(b)
  5. print b # b的结果是 2

传入可变类型
  1. mylist = [10,20,30]
  2. # 可写函数说明
  3. def changeme( mylist ):
  4. #"修改传入的列表"
  5. mylist.append(40)
  6. print ("函数内取值: ", mylist)
  7. return
  8. # 调用changeme函数
  9. changeme( mylist )
  10. print ("函数外取值: ", mylist)
  11. # 输出结果如下
  12. # 函数内取值: [10, 20, 30, 40]
  13. # 函数外取值: [10, 20, 30, 40]

关键字参数

函数调用使用关键字参数来确定传入的参数值。

  1. def printinfo( name, age ):
  2. "打印任何传入的字符串"
  3. print ("Name: ", name)
  4. print ("Age ", age)
  5. return
  6. #调用printinfo函数
  7. printinfo( age=50, name="miki" )
  8. # 输出结果如下
  9. # Name: miki
  10. # Age 50

默认参数

  1. # 如果没有传入age的值,则默认age的值是35
  2. def printinfo( name, age = 35 ):
  3. "打印任何传入的字符串"
  4. print ("Name: ", name)
  5. print ("Age ", age)
  6. return
  7. #调用printinfo函数
  8. printinfo( age=50, name="miki" )
  9. printinfo( name="miki" )
  10. # 输出结果如下
  11. # Name: miki
  12. # Age 50
  13. # Name: miki
  14. # Age 35

不定长参数

星号(*)的变量名会存放所有未命名的变量参数。

  1. def printinfo( arg1, *vartuple ):
  2. "打印任何传入的参数"
  3. print "输出: "
  4. print arg1
  5. for var in vartuple:
  6. print var
  7. return
  8. # 调用printinfo 函数
  9. printinfo( 10 )
  10. printinfo( 70, 60, 50 )
  11. # 输出结果如下
  12. # 第一个printinfo
  13. # 10
  14. # 第二个printinfo
  15. # 70
  16. # 60
  17. # 50

这边的vartuple可以理解为一个数组。把arg1后面所有的参数都存入到这个数组当中。 所以一般这种都是放在定义函数的最后一个参数的位置。

匿名函数

  • lambda只是一个表达式,函数体比def简单很多。
  • lambda的主体是一个表达式,而不是一个代码块。仅仅能在lambda表达式中封装有限的逻辑进去。
  • lambda函数拥有自己的命名空间,且不能访问自有参数列表之外或全局命名空间里的参数。
  • 虽然lambda函数看起来只能写一行,却不等同于C或C++的内联函数,后者的目的是调用小函数时不占用栈内存从而增加运行效率。

上面的定义看不懂没关系,看例子知道形式即可。

  1. sum = lambda arg1, arg2: arg1 + arg2
  2. # 这个就等同于
  3. # def sum(a,b):
  4. # c = a + b
  5. # return c
  6. # 调用sum函数
  7. print ("相加后的值为 : ", sum( 10, 20 ))
  8. print ("相加后的值为 : ", sum( 20, 20 ))
  9. # 输出结果如下
  10. # 相加后的值为 : 30
  11. # 相加后的值为 : 40

稍微拆分一下就可以得出,lambda表达式的结构就是 lambda + 参数 + : + 函数体


变量的作用域

一般情况下,函数内部是不能改变函数外变量的值的,比如:

  1. sum = 0
  2. def function():
  3. sum = 1
  4. function()
  5. print(sum)
  6. # 0

可以发现,这里虽然调用了函数,函数内部令sum=0了,但是并没有真正改变函数外sum的值。
这是因为函数内部的变量只作用在函数内部。
那么如果想要在函数内部修改函数外部的值,就需要使用global关键词。

  1. sum = 0
  2. def function():
  3. global sum
  4. sum = 1
  5. function()
  6. print(sum)
  7. # 1

函数的递归

所谓递归,就是在函数里面调用函数自己。
举个例子:
我们来计算阶乘n! = 1 x 2 x 3 x … x n,用函数fact(n)表示

  1. def fact(n):
  2. if n==1:
  3. return 1
  4. return n * fact(n - 1)
  5. fact(5)
  6. # 120
  1. 递归的过程如下:
  1. ===> fact(5)
  2. ===> 5 * fact(4)
  3. ===> 5 * (4 * fact(3))
  4. ===> 5 * (4 * (3 * fact(2)))
  5. ===> 5 * (4 * (3 * (2 * fact(1))))
  6. ===> 5 * (4 * (3 * (2 * 1)))
  7. ===> 5 * (4 * (3 * 2))
  8. ===> 5 * (4 * 6)
  9. ===> 5 * 24
  10. ===> 120
  1. 递归了解即可,后面会详细讲解

附赠:经典汉诺塔问题

  1. def move(n, a, b, c):
  2. if n == 1:
  3. print(a, '-->', c)
  4. else:
  5. move(n-1,a,c,b)
  6. move(1,a,b,c)
  7. move(n-1,b,c,a)
  8. move(3, 'A', 'B', 'C')

局部变量和全局变量

简单粗暴的来归纳一下就是:

  • 函数内定义的变量基本都是局部变量
  • 函数外定义的变量基本都是全局变量

    下面是关于局部变量和全局变量的详细解析:

python的 局部变量和全局变量_Vincent_ceso的博客-CSDN博客_python 局部变量

一般来讲,函数不能调用全局变量的,也就是不能改变函数外变量的值
如果想要调用,就要使用global关键词
举个例子:

  1. Money = 2000
  2. def AddMoney():
  3. # 表明Money是全局变量
  4. global Money
  5. Money = Money + 1
  6. print Money
  7. AddMoney()
  8. print Money

模块

模块的定义

  1. Python的模块就类似于Java当中的类,非常好理解。<br />举个例子:<br />这里创建两个python文件,`support.py`以及`test.py`<br />**supprot.py**
  1. # support.py 模块:
  2. def print_func( par ):
  3. print ("Hello : ", par)
  4. return
  1. **test.py**
  1. # 导入模块
  2. import support
  3. # 现在可以调用模块里包含的函数了
  4. support.print_func("Runoob")
  5. # Hello : Runoob

总结一下就是:

  • 首先在另外一个python文件中定义相关的函数变量等
  • 在其他的python文件中使用import进行导入文件
  • 导入完成之后就可以通过导入的文件名称调用文件的函数等

    模块语法

    import

    这个没什么好说的,就是单纯的导入模块 ```python

    导入模块

    import support

现在可以调用模块里包含的函数了

support.print_func(“Runoob”)

Hello : Runoob

  1. <a name="TqPjO"></a>
  2. #### from import
  3. Python 的 from 语句让你从模块中**导入一个指定的部分**到当前命名空间中。语法如下:
  4. ```python
  5. # 导入support模块中的 print_func方法
  6. from support import print_func
  7. # 现在可以调用模块里包含的函数了
  8. print_func("Runoob")
  9. # Hello : Runoob
  1. 如果需要导入所有的部分,就只需要是 `import *`即可
  1. # 导入support模块中的 print_func方法
  2. from support import *
  3. # 现在可以调用模块里包含的函数了
  4. print_func("Runoob")
  5. # Hello : Runoob

as

as的作用就是给导入的模块取别名,以此简化书写,或者避免函数同名冲突:

  1. # 导入support模块中的 print_func方法 并且取别名为pf
  2. from support import print_func as pf
  3. # 现在可以调用模块里包含的函数了
  4. pf("Runoob")
  5. # Hello : Runoob

模块相关函数(了解即可)

dir()函数

dir() 函数一个排好序的字符串列表,内容是一个模块里定义过的名字。
返回的列表容纳了在一个模块里定义的所有模块,变量和函数。如下一个简单的实例:

  1. # 导入内置math模块
  2. import math
  3. content = dir(math)
  4. print content;

以上实例输出结果:

  1. ['__doc__', '__file__', '__name__', 'acos', 'asin', 'atan', 'atan2', 'ceil', 'cos', 'cosh', 'degrees', 'e', 'exp', 'fabs', 'floor', 'fmod', 'frexp', 'hypot', 'ldexp', 'log', 'log10', 'modf', 'pi', 'pow', 'radians', 'sin', 'sinh', 'sqrt', 'tan', 'tanh']

在这里,特殊字符串变量name指向模块的名字,file指向该模块的导入文件名。

globals() 和 locals() 函数

根据调用地方的不同,globals() 和 locals() 函数可被用来返回全局和局部命名空间里的名字
如果在函数内部调用 locals(),返回的是所有能在该函数里访问的命名
如果在函数内部调用 globals(),返回的是所有在该函数里能访问的全局名字。
两个函数的返回类型都是字典。所以名字们能用 keys() 函数摘取。

reload() 函数

当一个模块被导入到一个脚本,模块顶层部分的代码只会被执行一次。
因此,如果你想重新执行模块里顶层部分的代码,可以用 reload() 函数。该函数会重新导入之前导入过的模块。语法如下:

  1. reload(module_name)

在这里,module_name要直接放模块的名字,而不是一个字符串形式。比如想重载 hello 模块,如下:

  1. reload(hello)

原文链接:

Python 函数 | 菜鸟教程
Python 模块 | 菜鸟教程