之前的文章我们简单介绍了一下 Python 的几种变量类型,本篇文章我们来看一下 Python 中的函数。

函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。

函数能提高应用的模块性,和代码的重复利用率。你已经知道Python提供了许多内建函数,比如print()。但你也可以自己创建函数,这被叫做用户自定义函数。

你可以定义一个由自己想要功能的函数,以下是简单的规则:

  • 函数代码块以 def 关键词开头,后接函数标识符名称和圆括号 ()
  • 任何传入参数和自变量必须放在圆括号中间,圆括号之间可以用于定义参数。
  • 函数的第一行语句可以选择性地使用文档字符串—用于存放函数说明。
  • 函数内容以冒号起始,并且缩进。
  • return [表达式] 结束函数,选择性地返回一个值给调用方。不带表达式的return相当于返回 None。

Python 定义函数使用 def 关键字,一般格式如下:

 def 函数名(参数列表):
函数体
 def getNum():
pass

如果我们定义了一个函数,里面什么也没有写,为了不让代码崩溃,我们可以写一个 pass。

现在我们来定义一个可执行的函数:

 def getNum():
print(123)
getNum() #

如上我们定义了一个 getNum 的函数,函数内部 print 输出 123,当我们调用 getNum() 时,就会输出 123。

如果我们不想输出固定的 123,输出结果有我们自己定义,我们可以通过传参的形式解决:

def getNum(num):
print(num)
print(num * 2)
getNum(123) # 123 246

可以通过 return 的方式把想要的结果 return 出来:

 def getNum(num):
return num
print(getNum(123)) #

函数中也可以使用嵌套函数的方式:

 def getNum(num):
getName(num) def getName(name):
print(name) getNum("zhangsan") # zhangsan

我们通过向函数传值来获取我们的结果,也可以通过设置变量的形式来解决:

num = 1
def getNum():
print(num) getNum() #

上面的代码我们设置了一个全局变量,当然我们也可以在函数内部设置变量,叫做局部变量,这样更有利于我们对自己函数内的变量操作而不去改变全局的变量,如下:

 def getNum():
name = "zhangsan"
print(name) getNum() # zhangsan

在有的时候,我们可以直接将函数内的参数设置默认值,这就就可以避免在没有传入该参数时函数报错:

 def getNum(a, b, c=11, d=22):
print(a)
print(b)
print(c)
print(d) getNum(1, 2, 3) # 1 2 3 22

在上面的代码中,我们对函数 getNum 的第三个和第四个参数设置了默认值,在调用该函数时,我们传入了三个值,然后输出结果发现,第三个参数的默认值被调用 getNum 时传入的参数值覆盖掉了,而第四个参数值由于没有传入,所以使用了默认值 d=22。由此我们可以得出,当我们不传入对应参数值时如果设置默认值则使用默认值,如果传入了参数值则优先使用传入的参数值。

在上面的代码中,我们定义的参数都是单一的字符串或者数字,我们也可以定义列表,元组,字典这样的参数,如下:

 list = [11, 22, 33]
tuple = (44, 55, 66)
dict = {"a": "", "b": 88, "c": 99} def getTest(list, tuple, dict):
print(list)
print(tuple)
print(dict) getTest(list, tuple, dict)
'''
[11, 22, 33]
(44, 55, 66)
{'a': '77', 'b': 88, 'c': 99}
'''

在上面的代码中我们可以看出,Python 中的不同变量类型都可以作为参数传入函数中。

接下来我们再来看一下函数中缺省参数的 *args 和 **kwargs

 def getTest(a, b, c=123, *args):
print(a) #
print(b) #
print(c) #
print(args) # (44, 55, 66) getTest(11, 22, 33, 44, 55, 66)

在上面的代码中,print(c) 结果为 33,这个我们再上面已经解释过了,但是我们在参数 c 后面又加入了一个 *args 的形参,然后我们在调用 getTest() 时向函数内部传入参数的个数为 6 个,而函数体 getTest() 接收的参数为 4 个,按我们上面叫的函数方法,理论上程序应该报错,然而程序却能运行,运行结果打印的第 4 个参数结果为一个元组,将形参按顺序对应的参数对应完毕之后剩余的内容组成一个元组输出。其中 *args 可以写成 *xxx,我们习惯上命名为 *args。

在函数传参时,除了 *args 外还有一个 **kwargs,如下:

 def getTest(a, b, c=123, *args, **kwargs):
print(a) #
print(b) #
print(c) #
print(args) # (44, 55, 66)
print(kwargs) # {'name': 'zhangsan', 'age': 30} getTest(11, 22, 33, 44, 55, 66, name="zhangsan", age=30)

上面的代码中,我们在函数 getTest() 后面又多家了一个形参 **kwargs,当我们在调用 getTest() 函数并传入参数时,我们传入了 name="zhangsan" 这样的键值对,这样在打印输出 **kwargs 时会转为一个字典类型的数据。其中 **kwargs 可以写成 **xxx,我们习惯上命名为 **kwargs。

注意:在print() 输出时,*args 和 **kwargs 的 * 不需要写。

根据上面的 *args 和 **kwargs,我们现在来向这样一个问题,加入我先在外面分别定义了一个元组类型变量 tuple 和字典类型数据 dict,然后调用 getTest() 函数时将变量传入,输出结果还是跟上面的结果一样,即下面的代码:

 def getTest(a, b, c=123, *args, **kwargs):
print(a) #
print(b) #
print(c) #
print(args) # ((44, 55, 66), {'name': 'zhangsan', 'age': 30})
print(kwargs) # {} tuple=(44,55,66)
dict={'name': 'zhangsan', 'age': 30}
getTest(11, 22, 33, tuple, dict)

当我们还是按照上面的 *args 和 **kwargs 写法写时,发现参数 tuple 和 dict 被当做一个数据输出到了 *args 里,这是由于当我们传入 tuple 和 dict 时被当做了一个整体,我们可以在传入前先将其解构一下就可以了,如下:

 def getTest(a, b, c=123, *args, **kwargs):
print(a) #
print(b) #
print(c) #
print(args) # (44, 55, 66)
print(kwargs) # {'name': 'zhangsan', 'age': 30} tuple=(44,55,66)
dict={'name': 'zhangsan', 'age': 30}
getTest(11, 22, 33, *tuple, **dict)

如上,我们在传入参数的时候传入 *tuple 和 **dict 就可以解决了,但是如果我们在传入参数时和调用时都不加 * 不就相当于把整个变量作为参数了吗?如下:

 def getTest(a, b, c=123, tuple, dict):
print(a)
print(b)
print(c)
print(tuple)
print(dict) tuple=(44,55,66)
dict={'name': 'zhangsan', 'age': 30}
getTest(11, 22, 33, tuple, dict) # SyntaxError: non-default argument follows default argument

我们会发现不写 * 的话会报错,原因是当我们在函数中定义默认参数时,默认参数必须写在最后面,即 c=123 需写在最后面,如下:

 def getTest(a, b, tuple, dict, c=123):
print(a) #
print(b) #
print(c) #
print(tuple) # (44, 55, 66)
print(dict) # {'name': 'zhangsan', 'age': 30} tuple=(44,55,66)
dict={'name': 'zhangsan', 'age': 30}
getTest(11, 22, tuple, dict, 33)

但是如果参数中存在 * 的话默认参数不能写在最后面,如下:

 def getTest(a, b, *tuple, **dict, c=123):
print(a)
print(b)
print(c)
print(tuple)
print(dict) tuple=(44,55,66)
dict={'name': 'zhangsan', 'age': 30}
getTest(11, 22, *tuple, **dict, 33) # SyntaxError: invalid syntax

由此我们得出函数的传参顺序为:参数,默认参数,*args,**kwargs。

我们接下来看一下匿名函数。

python 使用 lambda 来创建匿名函数。

所谓匿名,意即不再使用 def 语句这样标准的形式定义一个函数。

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

lambda 函数的语法只包含一个语句,如下:

lambda [arg1 [,arg2,.....argn]]:expression
 # 实现一个两数相加的匿名函数
sum = lambda num1, num2: num1 + num2
print(sum(10, 20)) #

Python 从入门到进阶之路(四)的更多相关文章

  1. Python 从入门到进阶之路(一)

    人生苦短,我用 Python. Python 无疑是目前最火的语言之一,在这里就不再夸他的 NB 之处了,本着对计算机编程的浓厚兴趣,便开始了对 Python 的自学之路,并记录下此学习记录的心酸历程 ...

  2. Python 从入门到进阶之路(七)

    之前的文章我们简单介绍了一下 Python 中异常处理,本篇文章我们来看一下 Python 中 is 和 == 的区别及深拷贝和浅拷贝. 我们先来看一下在 Python 中的双等号 == . == 是 ...

  3. Python 从入门到进阶之路(六)

    之前的文章我们简单介绍了一下 Python 的面向对象,本篇文章我们来看一下 Python 中异常处理. 我们在写程序时,有可能会出现程序报错,但是我们想绕过这个错误执行操作.即使我们的程序写的没问题 ...

  4. Python 从入门到进阶之路(五)

    之前的文章我们简单介绍了一下 Python 的函数,本篇文章我们来看一下 Python 中的面向对象. Python从设计之初就已经是一门面向对象的语言,正因为如此,在Python中创建一个类和对象是 ...

  5. Python 从入门到进阶之路(三)

    在之前的文章我们介绍了一下 Python 中 if while for 的使用,本章我们来看一下 Python 中的变量类型. 在 Python 定义变量时的规则是 变量名 = 变量 ,Python ...

  6. Python 从入门到进阶之路(二)

    之前的文章我们对 Python 语法有了一个简单的认识,接下来我们对 Python 中的 if while for 做一下介绍. 上图为 if 判断语句的流程,无论任何语言,都会涉及到判断问题,if ...

  7. python快速入门及进阶

    python快速入门及进阶 by 小强

  8. Python 爬虫从入门到进阶之路(十四)

    之前的文章我们已经可以根据 re 模块,Xpath 模块和 BeautifulSoup4 模块来爬取网站上我们想要的数据并且存储在本地,但是我们并没有对存储数据的格式有要求,本章我们就来看数据的存储格 ...

  9. Python 爬虫从入门到进阶之路(四)

    之前的文章我们做了一个简单的例子爬取了百度首页的 html,我们用到的是 urlopen 来打开请求,它是一个特殊的opener(也就是模块帮我们构建好的).但是基本的 urlopen() 方法不支持 ...

随机推荐

  1. Unity中文API参考手册

    转载请标明原文地址:http://www.cnblogs.com/zhangyukof/p/6835582.html  Unity5中文脚本手册 网页版 Unity API 执行顺序: Unity5中 ...

  2. ETL子系统

    最近在看<Pentaho Kettle 解决方案>,看到 ETL子系统,发现信息量比较大,用简短的语句做一下笔记. ETL子系统有34种子系统,被分成4个部分:抽取.清洗和更正.发布.管理 ...

  3. Android 基于ksoap2的webservice请求的学习

    [学习阶段] WebService网络请求? 其实我也是第一次遇到,之所以有这个需要是因为一些与 ERP 相关的业务,需要用到这样的一个请求方式. 开始学习WebService ①当然是百度搜索,这里 ...

  4. Java面试题_第四阶段

    1.1 电商行业特点 1.分布式 垂直拆分:根据功能模块进行拆分 水平拆分:根据业务层级进行拆分 2.高并发 用户单位时间内访问服务器数量,是电商行业中面临的主要问题 3.集群 抗击高兵发的有效手段, ...

  5. python基础之字符串讲解(下)

    7.swapspace 这个命令是让大小写翻转 s = 'qwerQ' s3 = s.swapcase() print(s3) 8.title 每个隔开(特殊字符或者数字)的单词首字母大写 s = ' ...

  6. 活久见: maven pom 竟然都会崩溃!

    问题是: 我的应用的pom 并没有任何报错,但是代码报错,而且编译不通过. 如下,我本地项目,从 spring-cloud-alibaba-dependencies 0.2.1.RELEASE 升级到 ...

  7. Java 添加超链接到Word文档

    对特定元素添加超链接后,用户可以通过点击被链接的元素来激活这些链接,通常在被链接的元素下带有下划线或者以不同的颜色显示来进行区分.按照使用对象的不同,链接可以分为文本超链接,图像超链接,E-mail链 ...

  8. linux查看磁盘及文件夹大小命令

    https://www.runoob.com/w3cnote/linux-view-disk-space.html 1.使用lsof查看已删除但未释放的文件 lsof -n | grep delete ...

  9. C#线程学习笔记一:线程基础

    本笔记摘抄自:https://www.cnblogs.com/zhili/archive/2012/07/18/Thread.html,记录一下学习过程以备后续查用. 一.线程的介绍 进程(Proce ...

  10. angular cli + primeNG

    目录: 1.安装  angular cli 2.创建项目 3.构建路由 4.新建组件 5.组件之间的通信 6.引入primeNG 7.修改primeNG组件样式 8.问题 -------------- ...