Python学习--05函数
Python函数
函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。
函数能提高应用的模块性,和代码的重复利用率。我们已经知道Python提供了许多内建函数,比如print()
。但我们也可以自己创建函数,这被叫做用户自定义函数。
定义一个函数
我们可以定义一个由自己想要功能的函数,以下是简单的规则:
- 函数代码块以
def
关键词开头,后接函数标识符名称
和圆括号()
。 - 任何传入参数和自变量必须放在圆括号中间。圆括号之间可以用于
定义参数
。 - 函数的
第一行语句
可以选择性地使用文档字符串—用于存放函数说明
。 - 函数内容以
冒号
起始,并且缩进。 Return[expression]
结束函数,选择性地返回一个值给调用方。不带表达式的return相当于返回None
。
语法
def functionname( parameters ):
"函数_文档字符串"
function_suite
return [expression]
默认情况下,参数值和参数名称是按函数声明中定义的的顺序匹配起来的。
实例
以下为一个简单的Python函数,它将一个字符串作为传入参数,再打印到标准显示设备上。
def printme( str ):
"打印传入的字符串到标准显示设备上"
print str
return
函数调用
定义一个函数只给了函数一个名称,指定了函数里包含的参数,和代码块结构。
这个函数的基本结构完成以后,你可以通过另一个函数调用执行,也可以直接从Python提示符执行。
Python里不用像C语言里需要先申明函数再使用。
如下实例调用了printme()
函数:
#!/usr/bin/python
# -*- coding: UTF-8 -*-
# 定义函数
def printme( str ):
"打印任何传入的字符串"
print(str);
return;
# 调用函数
printme("我要调用用户自定义函数!");
printme("再次调用同一函数");
以上实例输出结果:
我要调用用户自定义函数!
再次调用同一函数
参数
以下是调用函数时可使用的正式参数类型:
- 必选参数:
fun(name, age)
- 默认参数:
fun(name='yjc', age=18)
- 可变参数:
fun(*args)
- 关键字参数:
fun(name, age, **kw)
- 命名关键字参数:
fun(name, age, *, city)
必选参数
必选参数也称位置参数。必选参数须以正确的顺序传入函数。调用时的数量必须和声明时的一样。
调用printme()
函数,你必须传入一个参数,不然会出现语法错误:
#!/usr/bin/python
# -*- coding: UTF-8 -*-
#可写函数说明
def printme( str ):
"打印任何传入的字符串"
print(str);
return;
#调用printme函数
printme();
以上实例输出结果:
Traceback (most recent call last):
File "test.py", line 11, in <module>
printme();
TypeError: printme() takes exactly 1 argument (0 given)
默认参数
调用函数时,默认参数的值如果没有传入,则被认为是默认值。下例会打印默认的age,如果age没有被传入:
#!/usr/bin/python
# -*- coding: UTF-8 -*-
def printinfo( name, age = 35 ):
"打印任何传入的字符串"
print ("Name: ", name);
print ("Age ", age);
return;
# 调用printinfo函数
printinfo( "miki" )
printinfo( "miki", 50)
# 当不按顺序提供部分默认参数时,需要把参数名写上:
printinfo( name="miki", age=50 )
以上实例输出结果:
Name: miki
Age 35
Name: miki
Age 50
Name: miki
Age 50
可变参数
在Python函数中,还可以定义可变参数。顾名思义,可变参数就是传入的参数个数是可变的,可以是1个、2个到任意个,还可以是0个。基本语法如下:
def functionname(*var_args_tuple ):
"函数_文档字符串"
function_suite
return [expression]
加了星号(*)的变量名会存放所有未命名的变量参数。如下实例:
#!/usr/bin/python
# -*- coding: UTF-8 -*-
def calc(*numbers):
sum = 0
for n in numbers:
sum = sum + n * n
return sum
在函数内部,参数numbers接收到的是一个tuple。调用该函数时,可以传入任意个参数,包括0个参数:
>>> calc(1, 2)
5
>>> calc()
0
如果已经有一个list或者tuple,要调用一个可变参数怎么办?Python允许你在list或tuple前面加一个*
号,把list或tuple的元素变成可变参数传进去:
>>> nums = [1, 2, 3]
>>> calc(*nums)
14
*nums
表示把nums
这个list的所有元素作为可变参数传进去。
关键字参数
关键字参数允许我们在传入必选参数外,还可以接受关键字参数kw:
def person(name, age, **kw):
print('name:', name, 'age:', age, 'other:', kw)
这里name, age
是必须的,kw
可选,意味着第三个参数开始我们可以传入任意个数的关键字参数:
>>> person('Bob', 35, city='Beijing')
name: Bob age: 35 other: {'city': 'Beijing'}
>>> person('Adam', 45, gender='M', job='Engineer')
name: Adam age: 45 other: {'gender': 'M', 'job': 'Engineer'}
这个例子里,关键字参数让我们保证能接收到name
和age
这两个参数,但是,如果提供更多的参数,我们也能收到。
实际上,关键字参数kw
是个dict,如果我们已经准备好了dict,只需要在前面加**
就可以转换为参数传入:
param = {'gender': 'M', 'job': 'Engineer'}
>>> person('Adam', 45, **param)
name: Adam age: 45 other: {'gender': 'M', 'job': 'Engineer'}
注关键字参数kw
获得的dict是param的一份拷贝,对kw的改动不会影响到函数外的param。
命名关键字参数
如果要限制关键字参数的名字,就可以用命名关键字参数,例如,只接收city和job作为关键字参数。这种方式定义的函数如下:
def person(name, age, *, city, job):
print(name, age, city, job)
# 调用:
person('yjc', 22, city='Beijing', job='IT')
输出:
yjc 22 Beijing IT
和关键字参数**kw
不同,命名关键字参数需要一个特殊分隔符*
,*
后面的参数被视为命名关键字参数
。
命名关键字参数必须传入参数名,这和位置参数不同。如果没有传入参数名,调用将报错。如果调用时缺少参数名city和job,Python解释器把这4个参数均视为位置参数,但person()
函数仅接受2个位置参数。
如果函数定义中已经有了一个可变参数,后面跟着的命名关键字参数就不再需要一个特殊分隔符*
了:
def person(name, age, *args, city, job):
print(name, age, args, city, job)
命名关键字参数可以有缺省值,从而简化调用:
def person(name, age, *, city='Beijing', job):
print(name, age, city, job)
由于命名关键字参数city具有默认值,调用时,可不传入city参数。
返回多个值
Python里函数可以返回多个值:
def updPoint(x, y):
x+=5
y+=10
return x,y
x,y = updPoint(1,2)
print(x,y)
输出:
6 12
但其实这只是一种假象,Python函数返回的仍然是单一值:
r = updPoint(1,2)
print(r)
输出:
(6, 12)
返回值是一个tuple!但是,在语法上,返回一个tuple可以省略括号,而多个变量可以同时接收一个tuple,按位置赋给对应的值,所以,Python的函数返回多值其实就是返回一个tuple,但写起来更方便。
匿名函数
python 使用 lambda
来创建匿名函数。
lambda
只是一个表达式,函数体比def
简单很多。
lambda的主体是一个表达式,而不是一个代码块。仅仅能在lambda表达式中封装有限的逻辑进去。
lambda函数拥有自己的名字空间,且不能访问自有参数列表之外或全局名字空间里的参数。
虽然lambda函数看起来只能写一行,却不等同于C或C++的内联函数,后者的目的是调用小函数时不占用栈内存从而增加运行效率。
语法
lambda函数的语法只包含一个语句,如下:
lambda [arg1 [,arg2,.....argn]]:expression
如下实例:
#!/usr/bin/python
# -*- coding: UTF-8 -*-
# 可写函数说明
sum = lambda arg1, arg2: arg1 + arg2;
# 调用sum函数
print "相加后的值为 : ", sum( 10, 20 )
print "相加后的值为 : ", sum( 20, 20 )
以上实例输出结果:
相加后的值为 : 30
相加后的值为 : 40
return语句
return语句用于退出函数,选择性地向调用方
返回一个表达式。不带参数值的return语句返回None。之前的例子都没有示范如何返回数值,下例便告诉你怎么做:
#!/usr/bin/python
# -*- coding: UTF-8 -*-
# 可写函数说明
def sum( arg1, arg2 ):
# 返回2个参数的和."
total = arg1 + arg2
print("函数内 : ", total)
return total;
# 调用sum函数
total = sum( 10, 20 );
print("函数外 : ", total )
以上实例输出结果:
函数内 : 30
函数外 : 30
变量作用域
一个程序的所有的变量并不是在哪个位置都可以访问的。访问权限决定于这个变量是在哪里赋值的。
变量的作用域决定了在哪一部分程序你可以访问哪个特定的变量名称。两种最基本的变量作用域如下:
- 全局变量
- 局部变量
变量和局部变量
定义在函数内部的变量拥有一个局部作用域,定义在函数外的拥有全局作用域。
局部变量只能在其被声明的函数内部访问,而全局变量可以在整个程序范围内(包括函数里面)访问。如下实例:
#!/usr/bin/python
# -*- coding: UTF-8 -*-
total = 0; # 这是一个全局变量
# 可写函数说明
def sum( arg1, arg2 ):
#返回2个参数的和."
total = arg1 + arg2; # total在这里是局部变量.
print "函数内是局部变量 : ", total
return total;
#调用sum函数
sum( 10, 20 );
print "函数外是全局变量 : ", total
以上实例输出结果:
函数内是局部变量 : 30
函数外是全局变量 : 0
但是如果在函数中定义的局部变量如果和全局变量同名,则它会隐藏该全局变量。例如:
#!/usr/bin/python
a = 10;
def test():
print(a);
#a = 11;
test();
输出:10
如果把上面代码的注释去掉,运行会报错:UnboundLocalError: local variable 'a' referenced before assignment。这点非常值得注意。
如果要给全局变量在一个函数里赋值,必须使用global语句。
global VarName
表达式会告诉Python, VarName是一个全局变量,这样Python就不会在局部命名空间里寻找这个变量了。
例如,我们在全局命名空间里定义一个变量money。我们再在函数内给变量money赋值,然后Python会假定money是一个局部变量。然而,我们并没有在访问前声明一个局部变量money,结果就是会出现一个UnboundLocalError
的错误。取消global语句的注释就能解决这个问题。
#!/usr/bin/python
# -*- coding: UTF-8 -*-
Money = 2000
def AddMoney():
# 想改正代码就取消以下注释:
# global Money
Money = Money + 1
print Money
AddMoney()
print Money
在这里我对比c、php、js进行说明:
- php里函数外定义的变量在函数内部是不可见的。如果想使用或者修改函数外的变量,需要函数内使用global语句。
- pyhon里函数外定义的变量在函数内部是可见的,但是不能修改。且函数里存在和函数外变量同名,函数外变量不可用。如果想修改函数外的变量,需要函数内使用global语句。
- c语言里函数外定义的变量在函数内部是可见可修改的。但函数内部定义的变量(含同名)作用域是局部的。
- js语言里函数外定义的变量在函数内部是可见可修改的。但函数内部定义的变量(含同名)作用域是局部的。另外js变量在函数内部还有变量提升的特性。
按值传递参数和按引用传递参数
和其他语言不一样,传递参数的时候,python不允许程序员选择采用传值还是传引用。
Python参数传递采用的肯定是“传对象引用”的方式。实际上,这种方式相当于传值和传引用的一种综合。
如果函数收到的是一个可变对象(比如字典或者列表)的引用,就能修改对象的原始值——相当于通过“传引用”来传递对象。如果函数收到的是一个不可变对象(比如数字、字符或者元组)的引用,就不能直接修改原始对象——相当于通过“传值'来传递对象。
例如:
#!/usr/bin/python
# -*- coding: UTF-8 -*-
# 可写函数说明
def changeme( mylist ):
"修改传入的列表"
mylist.append([1,2,3,4]);
print("函数内取值: ", mylist)
return
# 调用changeme函数
mylist = [10,20,30];
changeme( mylist );
print("函数外取值: ", mylist)
# 不可变对象
def changeFixed(age):
age += 5
print(age)
age = 10;
changeFixed(age);
print(age)
输出结果如下:
函数内取值: [10, 20, 30, [1, 2, 3, 4]]
函数外取值: [10, 20, 30, [1, 2, 3, 4]]
15
10
有时候,我们并不想函数修改了原列表,有没有办法呢?有的。既然列表互相赋值是地址引用,引入新的变量名也是不行的,那么,可以复制一个列表出来,这样内存里用的就不是同一个地址,也就不会改变原数组了:
def changeme( mylist ):
"修改传入的列表"
mylist.append([1,2,3,4]);
print("函数内取值: ", mylist)
return
# 调用changeme函数
mylist = [10,20,30];
# tmp = mylist; # 这样还是引用同一地址,达不到不修改原列表目的
tmp = mylist[:] # 将原列表复制一份,地址将不再是相同的
changeme( tmp );
print("函数外取值: ", mylist)
输出:
函数内取值: [10, 20, 30, [1, 2, 3, 4]]
函数外取值: [10, 20, 30]
这里使用了切片相关知识,后续会详细讲解。
空函数
如果想定义一个什么事也不做的空函数,可以用pass语句:
def nop():
pass
常用系统函数
参考:
1、Python 函数
http://www.runoob.com/python/python-functions.html
2、函数的参数
http://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/001431752945034eb82ac80a3e64b9bb4929b16eeed1eb9000
Python学习--05函数的更多相关文章
- python学习 05 函数switch功能
1.python没有switch功能,利用字典实现 如果用if else,可行但是效率不高
- python学习8—函数之高阶函数与内置函数
python学习8—函数之高阶函数与内置函数 1. 高阶函数 a. map()函数 对第二个输入的参数进行第一个输入的参数指定的操作.map()函数的返回值是一个迭代器,只可以迭代一次,迭代过后会被释 ...
- python学习7—函数定义、参数、递归、作用域、匿名函数以及函数式编程
python学习7—函数定义.参数.递归.作用域.匿名函数以及函数式编程 1. 函数定义 def test(x) # discription y = 2 * x return y 返回一个值,则返回原 ...
- 从0开始的Python学习007函数&函数柯里化
简介 函数是可以重用的程序段.首先这段代码有一个名字,然后你可以在你的程序的任何地方使用这个名称来调用这个程序段.这个就是函数调用,在之前的学习中我们已经使用了很多的内置函数像type().range ...
- python学习Day10 函数的介绍(定义、组成、使用)
今日学习内容: 1.什么是函数 :函数就是一个含有特定功能的变量,一个解决某问题的工具 函数的定义:通过关键字def + 功能名字():代码体(根据需求撰写代码逻辑) 2.为什么要用函数:可以复用:函 ...
- Python学习之函数参数
上一节,我们学习了Python中是如何定义和调用函数且如何得到返回值的.在调用函数时,有的函数需要参数来启动函数,有的则无需参数.这一节我们来介绍Python中有哪些参数类型. 位置参数 在调用函数时 ...
- Python学习笔记 - 函数参数
>>> def power(x): ... return x * x ... >>> power(5) 25 >>> def power(x, n ...
- Python学习笔记—函数
函数 我们知道圆的面积计算公式为: S = πr2 当我们知道半径r的值时,就可以根据公式计算出面积.假设我们需要计算3个不同大小的圆的面积: r1 = 12.34 r2 = 9.08 r3 = 73 ...
- Python学习之函数篇
python查看对象,函数帮助文档:.__doc__,例:str.split.__doc__ 查看详细对象,函数文档:help(),例:help(str.split) 函数参数可设置默认值 如果不能提 ...
随机推荐
- ABP入门系列(2)——通过模板创建MAP版本项目
一.从官网创建模板项目 进入官网下载模板项目 依次按下图选择: 输入验证码开始下载 下载提示: 二.启动项目 使用VS2015打开项目,还原Nuget包: 设置以Web结尾的项目,设置为启动项目: 打 ...
- ASP.NET MVC5+EF6+EasyUI 后台管理系统(71)-微信公众平台开发-公众号管理
系列目录 思维导图 下面我们来看一个思维导图,这样就可以更快了解所需要的功能: 上一节我们利用了一个简单的代码例子,完成了与微信公众号的对话(给公众号发一条信息,并得到回复) 这一节将讲解公众号如何设 ...
- Lambda
Lambda Lambda 表达式是一种可用于创建委托或表达式目录树类型的匿名函数. 通过使用 lambda 表达式,可作为参数传递或作为函数调用值返回的本地函数. Lambda 表达式对于编写 LI ...
- PHP的学习--RSA加密解密
PHP服务端与客户端交互或者提供开放API时,通常需要对敏感的数据进行加密,这时候rsa非对称加密就能派上用处了. 举个通俗易懂的例子,假设我们再登录一个网站,发送账号和密码,请求被拦截了. 密码没加 ...
- JQuery中的siblings()是什么意思
jQuery siblings() 方法返回被选元素的所有同胞元素,并且可以使用可选参数来过滤对同胞元素的搜索. 实例演示:点击某个li标签后将其设置为红色,而其所有同胞元素去除红色样式. 1.创建H ...
- TCP/IP之Nagle算法与40ms延迟
Nagle算法是针对网络上存在的微小分组可能会在广域网上造成拥塞而设计的.该算法要求一个TCP连接上最多只能有一个未被确认的未完成的小分组,在该分组确认到达之前不能发送其他的小分组.同时,TCP收集这 ...
- Openstack Periodic Task
Openstack Periodic Task 周期性任务在各个模块的manager.py(computer,scheduler,cell,network)中添加. 添加方法:在模块manager类实 ...
- [Top-Down Approach]Take Notes
Computer Networking - A Top-Down Approach Six Edition Learn HTTP Using Browser and Proxy 2016-03-20 ...
- 关于Java中进程和线程的详解
一.进程:是程序的一次动态执行,它对应着从代码加载,执行至执行完毕的一个完整的过程,是一个动态的实体,它有自己的生命 周期.它因创建而产生,因调度而运行,因等待资源或事件而被处于等待状态,因完成任务而 ...
- [PHP源码阅读]count函数
在PHP编程中,在遍历数组的时候经常需要先计算数组的长度作为循环结束的判断条件,而在PHP里面对数组的操作是很频繁的,因此count也算是一个常用函数,下面研究一下count函数的具体实现. 我在gi ...