python之函数

简介:

  本篇文章我们来说说Python中的函数,那么什么是函数呢?

  函数是Python为了代码最大程度地重用和最小化代码冗余而提供的基本程序结构。

  函数是一种设计工具,能让程序员将复杂的系统分解为可管理的部件,在需要时能够按需去调用这些部件。

  函数用于将相关功能打包并参数化

  在Python中可以创建4种函数:

    全局函数:定义在模块中

    局部函数:嵌套于其它函数中

    lambda(匿名)函数:仅是一个表达式,可以出现在任何位置,使用的灵活度比函数强得多。它生成一个函数对象,若想多次调用,则应将其赋予某变量名进行调用

    方法:与特定数据类型关联的函数,并且只能与数据类型关联一起使用。说白了就是定义在类(class)中的函数


创建函数,语法如下:

1
2
def  functionName(parameters):
     suite

  def是一个可执行语句,因此可以出现在任何能够使用语句的地方,甚至可以嵌套于其它语句,例如if或while中。

  def创建了一个对象并将其赋值给一个变量名(即函数名)。

  return用于返回结果对象,其为可选;无return语句的函数自动返回None对象。返回多个值时,彼此间使用逗号分隔,且组合为元组形式返回一个对象。

  def语句运行之后,可以在程序中通过函数后附加括号进行调用。如:

1
2
3
4
5
6
In [ 1 ]:  def  printName():     #定义一个函数printName
    ...:      print  "hello"
    ...: 
 
In [ 2 ]: printName()          #调用函数printName
hello

  Python创建、改变或查找变量名,都是在名称空间中进行的。名称空间(作用域)说白了就是一个变量所能够生效的范围。

  在Python中,变量名在程序代码中被赋值的位置,决定了其能够被访问到的范围。

  函数定义了本地作用域,而模块定义了全局作用域

    每个模块都是一个全局作用域,因此,全局作用域的范围仅限于单个文件;

    每次对函数的调用都会创建一个新的本地作用域,赋值的变量除非声明为全局变量,否则均为本地变量;

    所有的变量名都可以归纳为本地、全局或内置的(由__builtin__模块提供)


  变量名引用分三个作用域进行:首先是本地、之后是函数内、接着是全局,最后是内置。

wKiom1hY6lCzfHQtAAC9gYEXo40352.jpg

  变量名解析遵循由内而外的法则,也即LEGB原则(如上图)。变量解析时有几点需要注意:

    先从Local(function)中查找,找到则返回解析结果,若找不到则到Enclosing function locals中查找;

    若在Enclosing function locals中找到了则返回解析结果,若找不到则到Global(module)中查找;

    若在Global(module)中找到了则返回解析结果,若找不到则到Built-in中查找;

    若在Built-in中找到了则返回解析结果,若找不到则返回“名称引用错误”异常

  变量名解析时,作用域越小,其优先级越高。也就是说,若在Local(function)中找到了,则直接返回其解析结果,而不会再到Enclosing function locals上去查找了。


  全局变量:

    全局变量是模块文件内部的顶层变量名;

    如果要在函数内部对全局变量进行赋值的话,必须事先使用global进行声明,global关键字后跟一个或多个由逗号隔开的变量名;

    全局变量名在函数内部不经声明也可以被引用;

    本地变量在函数返回时会消失,而全局变量不会,因此,使用全局变量是保存函数状态信息的最直接办法;

    尽量避免在函数中使用global声明全局变量。


  内嵌函数:

    Python中函数可以嵌套,也即可以在一个函数内部定义一个函数;

    在函数内部定义的函数仅能由外层函数进行调用;

    而如果外层函数直接把内层函数使用return返回,则调用外层函数时赋值的变量名引用的是一个内层函数对象,且此内层函数能够记忆其内部引用的外层函数的变量,这种行为叫做工厂函数,也叫闭合函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
In [ 11 ]:  def  maker(N):
     ...:      def  action(X):
     ...:          return  * *  N
     ...:      return  action
     ...:
 
In [ 12 ]: f  =  maker( 2 )
 
In [ 13 ]: f( 3 )
Out[ 13 ]:  9
 
In [ 14 ]: f( 4 )
Out[ 14 ]:  16
 
In [ 15 ]:  type (f)
Out[ 15 ]: function

  参数传递:

    参数的传递是通过自动将对象赋值给本地变量实现的

wKioL1hY9h-wG3iAAAAxe5nkG6Y156.jpg

  不可变参数通过“值”进行传递,在函数内部改变形参的值,只是让其引用了另一个对象(如数字)

  可变参数通过“指针”进行传递,在函数内部改变形参的值,将直接修改引用的对象(如列表)


有两种方式可避免可变参数被函数修改:

  1、直接传递可变对象的副本:

1
2
3
4
5
6
7
8
9
10
11
12
In [ 16 ]: L  =  [ 1 , 2 , 3 , 4 ]
 
In [ 17 ]:  def  changer(X):
     ...:     X[ 2 ] + = 10
     ...:      return  X
     ...:
 
In [ 18 ]: changer(L[:])
Out[ 18 ]: [ 1 2 13 4 ]
 
In [ 19 ]:  print  L
[ 1 2 3 4 ]

  2、在函数内部创建可变参数的副本

1
2
3
4
5
6
7
8
9
10
11
12
13
In [ 27 ]: L  =  [ 1 , 2 , 3 , 4 ]
 
In [ 28 ]:  def  changer(X):
     ...:     aa  =  X[:]
     ...:     aa[ 2 ] + = 10
     ...:      return  aa
     ...:
 
In [ 29 ]: changer(L)
Out[ 29 ]: [ 1 2 13 4 ]
 
In [ 30 ]:  print  L
[ 1 2 3 4 ]


参数匹配模型:

  默认情况下,参数通过其位置进行传递,从左至右,这意味着,必须精确地传递和函数头部参数一样多的参数

  但也可以通过关键字参数、默认参数或参数容器等改变这种机制

    位置:从左至右

    关键字参数:使用“name=value”的语法通过参数名进行匹配

    默认参数:定义函数时使用“name=value”的语法直接给变量一个值,从而传入的值可以少于参数个数

    可变参数:定义是为了整合,调用是为了分解

      定义函数时使用*开头的参数,可用于收集任意多基于位置的参数:

1
2
3
4
5
6
7
8
9
In [ 31 ]:  def  test( * x):
     ...:      print  x
     ...: 
 
In [ 32 ]: test( 1 )
( 1 ,)
 
In [ 33 ]: test( 1 , 2 , 3 )
( 1 2 3 )

      定义函数时使用**开头的参数,可用于收集任意多基于关键字参数,并将其转换成字典:

1
2
3
4
5
6
In [ 34 ]:  def  dict ( * * x):
     ...:      print  x
     ...: 
 
In [ 35 ]:  dict (x = 1 ,y = 2 ,z = 6 )
{ 'y' 2 'x' 1 'z' 6 }

     混用位置参数与可变参数:

1
2
3
4
5
6
In [ 36 ]:  def  a(x, * y):
     ...:      print  x,y
     ...: 
 
In [ 37 ]: a( 1 , 2 , 3 , 4 )
1  ( 2 3 4 )
1
2
3
4
5
6
7
8
In [ 38 ]:  def  b( * x, * * y):
     ...:      print  x
     ...:      print  y
     ...: 
 
In [ 39 ]: b( 1 , 2 , 3 , 4 , 5 ,i = 3 ,j = 9 ,c = 5 )
( 1 2 3 4 5 )
{ 'i' 3 'c' 5 'j' 9 }

    可变参数解包:调用函数时,使用*开头的参数,可用于将参数集合打散,从而传递任意多基于位置或关键字的参数。可以理解为分解参数。

      变量分解赋值:

1
2
3
4
5
6
7
8
9
10
11
12
In [ 1 ]: l1  =  [ 'Sun' , 'Mon' , 'Tue' ]
 
In [ 2 ]: x,y,z  =  l1
 
In [ 3 ]:  print  x
Sun
 
In [ 4 ]:  print  y
Mon
 
In [ 5 ]:  print  z
Tue
1
2
3
4
5
6
7
8
In [ 6 ]: l2  =  [ 'Sun' , 'Mon' , 'Tue' ]
 
In [ 7 ]:  def  a(x,y,z):
    ...:      print  x,y,z
    ...: 
 
In [ 8 ]: a( * l2)
Sun Mon Tue

  可变参数与位置参数混合使用时,不论是定义还是调用,均使用以下顺序:

    位置参数-->任意位置参数(*)-->关键字参数(**)


匿名函数lambda:

语法如下:

1
lambda  args: expression

    args:以逗号分隔的参数列表

    expression:用到args中各参数的表达式

  lambda语句定义的代码必须是合法的表达式,不能出现多条件语句(可使用if的三元表达式)和其它非表达式语句,如for和while等。

  lambda的首要用途是指定短小的回调函数。lambda将返回一个函数而不是将函数赋值给某变量名。

注意:

  lambda是一个表达式而非语句;

  lambda是一个单个表达式,而不是一个代码块

1
2
3
4
5
6
7
8
9
In [ 9 ]:  lambda  x,y:  print  x,y     #不能是语句,只能是表达式
   File  "<ipython-input-9-323c5186b793>" , line  1
     lambda  x,y:  print  x,y
                     ^
SyntaxError: invalid syntax
 
 
In [ 10 ]:  lambda  x,y: x  +  y         #返回的是一个函数
Out[ 10 ]: <function __main__.< lambda >>

  因为lambda返回的是一个函数,所以如果要调用它的话,则要将lambda表达式赋予一个变量名,通过变量名来调用:

1
2
3
4
In [ 11 ]: a  =  lambda  x,y: x  +  y
 
In [ 12 ]: a( 5 , 6 )
Out[ 12 ]:  11

  正因为lambda函数调用时必须赋予给某个变量名,通过变量名来调用,而这个变量名又不固定,故此称之为匿名函数。

  def语句创建的函数将赋值给某变量名,而lambda表达式则直接返回函数。lambda也支持使用默认参数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
In [ 13 ]:  def  testFunc(x,y,z):
     ...:      return  +  +  z
     ...:
 
In [ 14 ]: testFunc( 4 , 5 , 6 )
Out[ 14 ]:  15
 
In [ 15 ]: f  =  lambda  x,y,z: x + y + z
 
In [ 16 ]: f( 4 , 5 , 6 )
Out[ 16 ]:  15
 
In [ 17 ]: f2  =  ( lambda  x,y,z = 10 : x + y + z)
 
In [ 18 ]: f2( 4 , 5 )
Out[ 18 ]:  19

  在对某个数据对象作出多种不同处理时,可以把每一种处理机制定义成一个lambda,而后对这个数据对象调用这多个lambda表达式。

1
2
3
4
5
6
7
In [ 1 ]: l3  =  [ ( lambda  x: x * 2 ),( lambda  y: y * 3 ) ]
 
In [ 2 ]:  for  in  l3:         #i取到的是lambda表达式,而不是x和y的值
    ...:      print  i( 4 )
    ...: 
8
12


Python中的函数递归:

  说到递归,什么是递归呢?

  递归其实就是在运行中一层一层调用自己,直到不符合条件时退出。

  递归对自身的调用有以下几点需要注意:

    需要有一个退出条件(或者说边界条件)能够使自己退出递归状态,否则将会陷入无限式递归;

    需要有一个递归前进段来定义递归怎么一层层往前走;

    需要有一个递归返回段来定义必要时怎么一层层返回回来

  递归的次数不能过多,在python中函数的递归最深层次不能超过1000层,否则将抛出异常


通过递归的方式实现阶乘:

10 * 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2 * 1

==> 10 * (10-1) * ((10-1)-1)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
In [ 4 ]:  def  factorial(x):
    ...:      if  x < =  1 :
    ...:          return  1
    ...:      else :
    ...:          return  *  factorial(x - 1 )
    ...: 
    ...: 
 
In [ 5 ]: factorial( 3 #factorial(3) = 3 * factorial(2) = 3 * 2 * factorial(1) = 3 * 2 * 1
Out[ 5 ]:  6
 
In [ 6 ]: factorial( 10 )
Out[ 6 ]:  3628800
 
In [ 7 ]:  10  *  9  *  8  *  7  *  6  *  5  *  4  *  3  *  2  *  1
Out[ 7 ]:  3628800

通过递归的方式实现斐波那契数列:

wKioL1hct7ryUm5MAAA44L4WF78049.jpg

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
In [ 11 ]:  def  fab(x):
     ...:      if  = =  1 :
     ...:          return  1
     ...:      elif  = =  0 :
     ...:          return  0
     ...:      else :
     ...:         result  =  int (fab(x - 1 +  fab(x - 2 ))
     ...:          return  result
     ...: 
 
In [ 12 ]:  for  in  range ( 10 ):
     ...:      print  fab(i)
     ...: 
0
1
1
2
3
5
8
13
21
34


Python中的函数设计规范:

  耦合性:

    通过参数接受输入,通过return产生输出以保证函数的独立性,除非必要,不要用print输出太多东西;

    尽量减少使用全局变量进行函数间通信;

    不要在函数中直接修改可变类型的参数;

    避免直接改变定义在另一个模块中的变量

  聚合性:

    每个函数都应该有一个单一的、统一的目标;

    每个函数的功能都应该相对简单,不要让一个函数的功能过多


Python中的函数执行环境:

  函数可以通过多种方法获得输入及产生输出

wKiom1hct_aj95QmAAA81z76Ows294.jpg










本文转自 忘情OK  51CTO博客,原文链接:http://blog.51cto.com/itchentao/1884653,如需转载请自行联系原作者
目录
相关文章
|
8天前
|
Python
python函数的参数学习
学习Python函数参数涉及五个方面:1) 位置参数按顺序传递,如`func(1, 2, 3)`;2) 关键字参数通过名称传值,如`func(a=1, b=2, c=3)`;3) 默认参数设定默认值,如`func(a, b, c=0)`;4) 可变参数用*和**接收任意数量的位置和关键字参数,如`func(1, 2, 3, a=4, b=5, c=6)`;5) 参数组合结合不同类型的参数,如`func(1, 2, 3, a=4, b=5, c=6)`。
13 1
|
23天前
|
Python
Python函数使用(四)
Python函数使用(四)
59 0
|
1天前
|
Serverless 开发者 Python
《Python 简易速速上手小册》第3章:Python 的函数和模块(2024 最新版)
《Python 简易速速上手小册》第3章:Python 的函数和模块(2024 最新版)
25 1
|
1天前
|
索引 Python
Python高维变量选择:SCAD平滑剪切绝对偏差惩罚、Lasso惩罚函数比较
Python高维变量选择:SCAD平滑剪切绝对偏差惩罚、Lasso惩罚函数比较
|
3天前
|
Python
python学习-函数模块,数据结构,字符串和列表(下)
python学习-函数模块,数据结构,字符串和列表
25 0
|
3天前
05-python之函数-函数的定义/函数的参数/函数返回值/函数说明文档/函数的嵌套使用/函数变量的作用域
05-python之函数-函数的定义/函数的参数/函数返回值/函数说明文档/函数的嵌套使用/函数变量的作用域
|
4天前
|
Python
python学习10-函数
python学习10-函数
|
4天前
|
Python
python学习4-内置函数range()、循环结构、循环控制语句、else语句、嵌套循环
python学习4-内置函数range()、循环结构、循环控制语句、else语句、嵌套循环
|
7天前
|
测试技术 开发者 Python
Python中的装饰器:优雅而强大的函数修饰工具
在Python编程中,装饰器是一种强大的工具,用于修改函数或方法的行为。本文将深入探讨Python中装饰器的概念、用法和实际应用,以及如何利用装饰器实现代码的优雅和高效。
|
12天前
|
Python
Python函数学习应用案例详解
【4月更文挑战第7天】学习Python函数的应用,包括计算两数之和、判断偶数、计算阶乘、生成斐波那契数列及反转字符串。示例代码展示了函数接收参数和返回结果的功能,如`add(a, b)`求和,`is_even(num)`判断偶数,`factorial(n)`计算阶乘,`fibonacci(n)`生成斐波那契数,以及`reverse_string(s)`反转字符串。
13 1