python学习-函数基础1

出自:https://blog.csdn.net/gavin_john/article/details/50018297

函数相关的语句和表达式

语句 例子
Calls myfunc("spam","eggs",meat=ham)
def def adder(a,b=1,*C):
return return a+b+c[0]
global def changer():
global x;x = 'new'
nonlocal def changer():
   nonlocal x;x = 'new'
yield def squares(x):
for i in range(x):yield i**2
lambda Funcs=[lambda x:x**2,lambda x:x*3]

======================================================================

为何使用函数

函数是一个通用的程序结构的部件,它的作用为:
(1)最大化的代码重用和最小化的代码冗余
(2)流程的分解

======================================================================

编写函数

(1)def是可执行的代码。
函数并不存在,直到运行了def后才存在。事实上,在if语句、while循环甚至是其他的def中嵌套式合法的。
在典型的操作中,def语句在模块文件中编写,并自然而然地在模块文件第一次被导入的时候生成定义的函数。
(2)def创建了一个对象并将其赋值给某一变量名。
当Python运行到def语句时,它将会生成一个新的函数对象并将其赋值给这个函数名。就像所有的赋值一样,函数名变成了某一个函数的引用
函数也可以通过lambda表达式来创建
(3)lambda创建一个对象但将其作为结果返回
也可以用lambda表达式创建函数,这一功能允许我们把函数定义内联到语法上一条def语句不能工作的地方。
(4)return将一个结果对象发送给调用者。
(5)yield向调用者发回一个结果对象,但是记住它离开的地方。
像生成器这样的函数也可以通过yield语句来返回值,并挂起它们的状态以便稍后能过恢复状态
(6)global声明了一个模块级的变量并被赋值。
在默认情况下,所有在一个函数中被赋值的对象,是这个函数的本地变量,并且仅在这个函数运行的过程中存在。
为了分配一个可以在整个模块中都可以使用的变量名,函数需要在global语句中将它列举出来。
通常情况下,变量名往往需要关注它的作用域(也就是说变量存储的地方)
(7)nonlocal声明了将要赋值的一个封闭的函数变量。
(8)函数是通过赋值(对象引用)传递的。
在Python中,参数通过赋值传递给了函数(也就是说,就像我们所学过的,使用对象引用)
(9)参数、返回值以及变量并不是声明

---------------------------------------------------------------------------------------------------------------------------------

def语句

def语句将创建一个函数对象并将其赋值给一个变量名。一般格式如下:

[python]  view plain  copy
  1. def <name>(arg1,arg2,...,argN):  
  2.     <statements>  
就像所有的多行Python语句一样,def包含了首行并有一个代码块跟随在后边,这个代码块都长都会缩进(或者就是在冒号后边简单的一句)。而这个代码块就成为了函数的主体——也就是每当调用函数时Python所执行的语句。

def首行定义了函数名,赋值给了函数对象,并在括号中包含了0个或以上的参数。在函数调用的时候,在首行的参数名赋值给了括号中的传递来的对象。

函数的主体往往都包含了一条return语句。

[python]  view plain  copy
  1. def<name> (arg1,arg2,...,argN):  
  2.     ...  
  3.     return <value>  
return 语句是可选的,如果没有return语句,函数将会在控制流执行完函数主体时结束
从技术角度来讲,一个没有返回值的函数自动返回了none对象,但是这个值是往往被忽略掉的

函数也许会有yield语句,这在每次都会产生一系列值时被用到。

---------------------------------------------------------------------------------------------------------------------------------

def 语句是实时执行的

Python的def语句实际上是一个可执行语句:当它运行的时候,它创建一个新的函数对象并将其赋值给一个变量名。(请记住,Python中所有的语句都是实时运行的,没有像独立的编译时间这样的流程)因为它是一个语句,一个def往往是包含在模块文件中,并在模块导入时运行,函数还是可以通过嵌套在if语句中去实现不同的函数定义,这样也是完全合法的。

[python]  view plain  copy
  1. if test:  
  2.     def func():  
  3.         ...  
  4. else:  
  5.     def func():  
  6.         ...  
  7. ...  
  8. func()  
它在运行时简单地给一个变量名进行赋值。

因为函数定义是实时发生的,所以对于函数名来说并没有什么特别之处。关键之处在于函数名所引用的那个对象。
[python]  view plain  copy
  1. otername = func  
  2. otername()  
这里,将函数赋值给一个不同的变量名,并通过新的变量名进行了调用。就像Python中其他语句一样,函数仅仅是对象,在程序执行时它清楚地记录在了内存之中。
实际上,除了调用之外,函数允许任意的属性附加到记录信息以供随后使用:

[python]  view plain  copy
  1. def func():...  
  2. func()  
  3. func.attr = value  
======================================================================
第一个例子:定义和调用

【定义】
这是一个在交互模式下输入的定义语句,它定义了一个名为times的函数,这个函数将返回两个参数的结果.

[python]  view plain  copy
  1. >>> def times(x,y):  
  2.     return x*y  
当Python运行到这里并执行了def语句后,它将会创建一个新的函数对象,封装这个函数的代码并将这个对象赋值给变量名times。典型的情况是,这样一个语句编写在一个模块文件中,当这个文件导入的时候运行。在这里,对于这个小的一个程序,用交互提示模式就已经足够了。
---------------------------------------------------------------------------------------------------------------------------------

【调用】

在def运行之后,可以在程序中通过函数名后增加括号调用(运行)这个函数。括号中可以包含一个或多个对象参数,这些参数将会传递给函数头部的参数名。

[python]  view plain  copy
  1. >>> times(2,6)  
  2. 12  
这个表达式传递了两个参数给times函数。参数是通过赋值传递的。
如果稍后我们需要使用这个值,可以将其赋值给另一个变量。例如:
[python]  view plain  copy
  1. >>> x = times(3,6)  
  2. >>> x  
  3. 18  
我们也可以传递两个完全不同种类的对象:
[python]  view plain  copy
  1. >>> times('Hello',3)  
  2. 'HelloHelloHello'  
这次,函数的作用完全不同。‘*’对数字和序列都有效。我们可以把times用作数字的乘法或是序列的重复。
---------------------------------------------------------------------------------------------------------------------------------

Python中的多态

就像上边那样,times函数的表达式x*y的意义完全取决于x和y的对象类型。Python将一对象在某种语法的合理性交由对象自身来判断。

这种依赖类型的行为成为多态,其含义就是一个操作的意义取决于被操作对象的类型。

======================================================================

第二个例子:寻找序列的交集

【定义】
把代码封装在函数中,使他成为一个通用搜索交集的工具

[python]  view plain  copy
  1. >>> def intersect(seq1,seq2):  
  2.     res = []  
  3.     for x in seq1:  
  4.         if x in seq2:  
  5.             res.append(x)  
  6.     return res  
---------------------------------------------------------------------------------------------------------------------------------
【调用】

在你能够使用函数之前,必须先创建它。你可以先运行def语句,要么就是通过在交互模式下输入,要么就是在一个模块文件中编写好它,然后导入这个文件。一旦运行了def,就可以通过在括号中传递两个序列对象从而调用这个函数:

[python]  view plain  copy
  1. >>> s1 = 'gavin'  
  2. >>> s2 = 'canv'  
  3. >>> intersect(s1,s2)  
  4. ['a''v''n']  
这个函数运行相当慢,因为它执行嵌套循环,并不是真正的数学交集(结果中可能有重复的元素),并且也根本不必要(Python的集合数据类型提供了一个内置的交集操作)。
实际上,这个函数可以用一个单独的列表解析表达式来替代
[python]  view plain  copy
  1. >>> [x for x in s1 if x in s2]  
  2. ['a''v''n']  
---------------------------------------------------------------------------------------------------------------------------------
重访多态

和所有的Python中的函数一样,intersect是多态的,也就是说,它可以支持多种类型,只要其支持扩展对象接口:

[python]  view plain  copy
  1. >>> x = intersect([1,2,3],(1,4))  
  2. >>> x  
  3. [1]  
这次,给函数传递了不同类型的对象(一个列表和一个元祖),并且仍然是选择出共有的元素。
对于intersect函数,这意味着第一个参数必须支持for循环,并且第二个参数支持成员测试。所有满足这两点的对象都能够正常工作,与它们的类型无关。
---------------------------------------------------------------------------------------------------------------------------------

本地变量

可能上面的intersect函数最有趣的部分是其名称。它证明了,intersect函数中的res变量在Python中叫做本地变量——这个变量只是在def内部的函数中是可见的,并且仅在函数运行时是存在的。实际上,intersect函数内的所有的变量均为本地变量。


猜你喜欢

转载自blog.csdn.net/kangkang_hacker/article/details/80532332