python之函数,,防伪码:忘情公子著函


防伪码:忘情公子著


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

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

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

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

全局函数:定义在模块中

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

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

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


创建函数,语法如下:

deffunctionName(parameters):suite

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

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

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

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

In[1]:defprintName():#定义一个函数printName...:print"hello"...:In[2]:printName()#调用函数printNamehello


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

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

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

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

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

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


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

技术分享

变量名解析遵循由内而外的法则,也即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返回,则调用外层函数时赋值的变量名引用的是一个内层函数对象,且此内层函数能够记忆其内部引用的外层函数的变量,这种行为叫做工厂函数,也叫闭合函数

In[11]:defmaker(N):...:defaction(X):...:returnX**N...:returnaction...:In[12]:f=maker(2)In[13]:f(3)Out[13]:9In[14]:f(4)Out[14]:16In[15]:type(f)Out[15]:function


参数传递:

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

技术分享

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

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


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

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

In[16]:L=[1,2,3,4]In[17]:defchanger(X):...:X[2]+=10...:returnX...:In[18]:changer(L[:])Out[18]:[1,2,13,4]In[19]:printL[1,2,3,4]

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

In[27]:L=[1,2,3,4]In[28]:defchanger(X):...:aa=X[:]...:aa[2]+=10...:returnaa...:In[29]:changer(L)Out[29]:[1,2,13,4]In[30]:printL[1,2,3,4]


参数匹配模型:

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

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

位置:从左至右

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

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

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

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

In[31]:deftest(*x):...:printx...:In[32]:test(1)(1,)In[33]:test(1,2,3)(1,2,3)

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

In[34]:defdict(**x):...:printx...:In[35]:dict(x=1,y=2,z=6){‘y‘:2,‘x‘:1,‘z‘:6}

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

In[36]:defa(x,*y):...:printx,y...:In[37]:a(1,2,3,4)1(2,3,4)
In[38]:defb(*x,**y):...:printx...:printy...: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}

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

变量分解赋值:

In[1]:l1=[‘Sun‘,‘Mon‘,‘Tue‘]In[2]:x,y,z=l1In[3]:printxSunIn[4]:printyMonIn[5]:printzTue
In[6]:l2=[‘Sun‘,‘Mon‘,‘Tue‘]In[7]:defa(x,y,z):...:printx,y,z...:In[8]:a(*l2)SunMonTue

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

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


匿名函数lambda:

语法如下:

lambdaargs:expression

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

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

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

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

注意:

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

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

In[9]:lambdax,y:printx,y#不能是语句,只能是表达式File"<ipython-input-9-323c5186b793>",line1lambdax,y:printx,y^SyntaxError:invalidsyntaxIn[10]:lambdax,y:x+y#返回的是一个函数Out[10]:<function__main__.<lambda>>

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

In[11]:a=lambdax,y:x+yIn[12]:a(5,6)Out[12]:11

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

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

In[13]:deftestFunc(x,y,z):...:returnx+y+z...:In[14]:testFunc(4,5,6)Out[14]:15In[15]:f=lambdax,y,z:x+y+zIn[16]:f(4,5,6)Out[16]:15In[17]:f2=(lambdax,y,z=10:x+y+z)In[18]:f2(4,5)Out[18]:19

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

In[1]:l3=[(lambdax:x*2),(lambday:y*3)]In[2]:foriinl3:#i取到的是lambda表达式,而不是x和y的值...:printi(4)...:812


本文出自 “忘情博” 博客,请务必保留此出处http://itchentao.blog.51cto.com/5168625/1884653

python之函数

评论关闭