Python 从入门到进阶之路(四)
之前的文章我们简单介绍了一下 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 从入门到进阶之路(四)的更多相关文章
- Python 从入门到进阶之路(一)
人生苦短,我用 Python. Python 无疑是目前最火的语言之一,在这里就不再夸他的 NB 之处了,本着对计算机编程的浓厚兴趣,便开始了对 Python 的自学之路,并记录下此学习记录的心酸历程 ...
- Python 从入门到进阶之路(七)
之前的文章我们简单介绍了一下 Python 中异常处理,本篇文章我们来看一下 Python 中 is 和 == 的区别及深拷贝和浅拷贝. 我们先来看一下在 Python 中的双等号 == . == 是 ...
- Python 从入门到进阶之路(六)
之前的文章我们简单介绍了一下 Python 的面向对象,本篇文章我们来看一下 Python 中异常处理. 我们在写程序时,有可能会出现程序报错,但是我们想绕过这个错误执行操作.即使我们的程序写的没问题 ...
- Python 从入门到进阶之路(五)
之前的文章我们简单介绍了一下 Python 的函数,本篇文章我们来看一下 Python 中的面向对象. Python从设计之初就已经是一门面向对象的语言,正因为如此,在Python中创建一个类和对象是 ...
- Python 从入门到进阶之路(三)
在之前的文章我们介绍了一下 Python 中 if while for 的使用,本章我们来看一下 Python 中的变量类型. 在 Python 定义变量时的规则是 变量名 = 变量 ,Python ...
- Python 从入门到进阶之路(二)
之前的文章我们对 Python 语法有了一个简单的认识,接下来我们对 Python 中的 if while for 做一下介绍. 上图为 if 判断语句的流程,无论任何语言,都会涉及到判断问题,if ...
- python快速入门及进阶
python快速入门及进阶 by 小强
- Python 爬虫从入门到进阶之路(十四)
之前的文章我们已经可以根据 re 模块,Xpath 模块和 BeautifulSoup4 模块来爬取网站上我们想要的数据并且存储在本地,但是我们并没有对存储数据的格式有要求,本章我们就来看数据的存储格 ...
- Python 爬虫从入门到进阶之路(四)
之前的文章我们做了一个简单的例子爬取了百度首页的 html,我们用到的是 urlopen 来打开请求,它是一个特殊的opener(也就是模块帮我们构建好的).但是基本的 urlopen() 方法不支持 ...
随机推荐
- C语言每日一练——第4题
一.题目要求 已知数据文件in.dat中有300个四位数,并调用readDat()函数把这些数存储数组a中,编写函数jsValue(),其功能是:求出所有这些四位数是素数的个数cnt,再把所有满足此条 ...
- 我的 FPGA 学习历程(15)—— Verilog 的 always 语句综合
在本篇里,我们讨论 Verilog 语言的综合问题,Verilog HDL (Hardware Description Language) 中文名为硬件描述语言,而不是硬件设计语言.这个名称提醒我们是 ...
- 你不知道的JavaScript(中)读书笔记(一)
第一章 1.内置类型 JavaScript有七种内置类型[除了对象以外,其他统称为“基本类型”]: 空值(null) 未定义(undefined) 布尔值(boolean) 数字(number) 字符 ...
- pycharm连接mysql
pycharm 换成2019之后连接数据库用户名密码数据库名字都没错,就是连接不上去,网上百度一下,试试将URL后面拼接 ?useSSL=false&serverTimezone=UTC 发现 ...
- python并发之多进程
#mutiprocessing模块 python中的多线程无法利用多核优势,如果想要充分地使用多核CPU的资源(os.cpu_count()查看),在python中大部分情况需要使用多进程.Pytho ...
- 解决logstash.outputs.elasticsearch[main] Could not index event to Elasticsearch status 404
现象:lostack启动正常,logstack收集输入redis数据,输出到elasticsearch写入失败 提示:去建索引 的时候elasticsearch返回404 [2019-11-12T11 ...
- python连接sqlserver和MySQL实现增删改查
参考python核心编程 编写一个用户洗牌的脚本,根据用户输入,选择连接sqlserver或者MySQL,创建数据库.表,随机生成数据,并实现增删改查. 其中,为了兼容python2和python3, ...
- 解决mysql导入数据量很大导致失败及查找my.ini 位置(my.ini)在哪
数据库数据量很大的数据库导入到本地时,会等很久,然而等很久之后还是显示失败: 这是就要看看自己本地的没mysql是否设置了超时等待,如果报相关time_out这些,可以把mysql.ini尾部添加ma ...
- WebAPI接口测试数据库操作
通常我们是不建议直接查看数据库内容来检查功能的,但是在没有外部接口或者图形界面验证的情况下,只能通过查询数据库来验证. 比如我们手工需要从界面上添加一万条数据,估计要花好几天时间,显然不能手工去操作. ...
- python程序员面试高概率会遇到的技术问题
本篇只列举会问到的技术问题.其他的问题会在另一篇文章多年职场老狗的面试经验提到. 1. TCP三次握手和四次挥手的过程 2.HTTP协议的状态码 3.讲一下自己用过的设计模式 4.python的多线程 ...