一、函数是什么

​ 计算机语言中的函数是类比于数学中的函数演变来的,但是又有所不同。前面的知识中我们学会了运用基础语法(列表、字典)和流程控制语句貌似也能处理一些复杂的问题,但是相对于相似的大量重复性的操作我们就没办法用之前的逻辑方法来解决了,这时候就需要一个可以概括这些重复性操作的统一代码来描述其特征来实现,所以函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。

定义:函数是值将一组语句集合通过一个名字(函数名)封装起来,要想执行这个函数,只需调用其函数名即可。

优点:在解决问题时,使用函数有诸多好处,最主要的好处就是:增强代码的重用性和可读性,后期扩展方便

二、函数的定义

2.1、格式

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

举个栗子,简单认识一下函数:

def greet_user():
"""显示最简单的问候语"""
print("Hello," greet_user()

上面这三行代码就是一个简单的函数实例,def是必不可少的,用于定义函数,greet_user是定义的函数名,() - 括号内指出函数为完成其任务需要什么样的信息,也就是参数,但是这里它不需要任何信息就能完成其工作,因此括号是空的(即便如此,括号也必不可少)。最后,定义以冒号结尾。

中间的缩进行构成了函数体。这里是函数的重点,所有的操作都是定义在这里的。上面的注释处的文本是被称为文档字符串 ( docstring )的注释,描述了函数是做什么的。文档字符串用三引号括起, Python 使用它们来生成有关程序中函数的文档。

greet_user() 这是对上面定义好的函数的调用。Python中要调用函数,可依次指定函数名以及用括号括起的必要信息-参数,上面的函数因为没有定义参数所以就不需要进行参数的传递,直接加括号调用。

2.2、函数的命名规则

函数名必须以下划线或字母开头,可以包含任意字母、数字或下划线的组合。不能使用任何的标点符号;

函数名是区分大小写的。

函数名不能是保留字。

三、参数的传递

3.1、形参和实参

举个栗子:

def greet_user(username):
print("Hello,"+username.title()) greet_user('jack')

上面的代码片段,定义函数greet_user,需要向函数中传递参数,在上面的函数中名后的括号中的username就是形参(形式参数),调用函数时给函数传入的值'jack'就是实参(实际参数)。实参将用户传递的值传递给形参,形参在传递进函数体中进行相关运算执行。

形参:形式参数,不是实际存在,是虚拟变量。在定义函数和函数体的时候使用形参,目的是在函数调用时接收实参(实参个数,类型应与实参一一对应)

实参:实际参数,调用函数时传给函数的参数,可以是常量,变量,表达式,函数,传给形参 。

区别:形参是虚拟的,不占用内存空间,形参变量只有在被调用时才分配内存单元,实参是一个变量,占用内存空间,数据传送单向,实参传给形参,不能形参传给实参。

3.2、位置实参

鉴于函数定义中可能包含多个形参,因此函数调用中也可能包含多个实参。向函数传递实参的方式很多,可使用位置实参 ,这要求实参的顺序与形参的顺序相同;也可使用关键字实参 ,其中每个实参都由变量名和值组成;还可使用列表和字典。

调用函数时, Python 必须将函数调用中的每个实参都关联到函数定义中的一个形参。为此,最简单的关联方式是基于实参的顺序。这种关联方式被称为位置实参。

文字描述太多不如举个栗子:看一个显示宠物信息的函数。这个函数指出一个宠物属于哪种动物以及它叫什么名字

def describe_pet(pet_name,animal_type):
print("\nI have a " + animal_type)
print("My " + animal_type + "'s name is " + pet_name.title()) describe_pet('Hellen','dog')
describe_pet('dog','Hellen') # 错误的位置参数传递

上述代码的运行结果为:

C:\Python37\python3.exe D:/pythoncode/Exercise/Exer8/Exer8-2.py

I have a dog
My dog's name is Hellen # 参数位置传递错误 结果也不一样
I have a Hellen
My Hellen's name is Dog Process finished with exit code 0

分析:上述代码上两次实参的传递因为位置不同而得到不同的结果,第二个显然不是我们想要的结果,所以在进行实参传递时确认函数调用中实参的顺序与函数定义中形参的顺序一致。

3.3、关键字实参

关键字参数是向形参传递--值对,关键字实参传递让我们无需考虑函数调用中的实参顺序,还清楚地指出了函数调用中各个值的用途。

举个栗子:

def describe_pet(pet_name,animal_type):
print("\nI have a " + animal_type)
print("My " + animal_type + "'s name is " + pet_name.title()) # 关键字传参不必考虑位置
describe_pet(pet_name='Hellen',animal_type="dog")
describe_pet(animal_type="dog",pet_name='Hellen')

上述代码的运行结果为:

C:\Python37\python3.exe D:/pythoncode/Exercise/Exer8/Exer8-2.py

I have a dog
My dog's name is Hellen I have a dog
My dog's name is Hellen Process finished with exit code 0

分析:上面的这个例子是关键字实参传递,使用关键字参数允许函数调用时参数的顺序与声明时不一致,因为 Python 解释器能够用参数名匹配参数值。

注意:如果关键字参数和位置参数一起出现时,关键字参数是不能写在位置参数前面的

3.3、默认参数

编写函数时,可给每个形参指定 默认值 。在调用函数中给形参提供了实参时, Python 将使用指定的实参值;否则,将使用形参的默认值。因此,给形参指定默认值后,可在函数调用中省略相应的实参。使用默认值可简化函数调用,还可清楚地指出函数的典型用法。

举个栗子:

def describe_pet(pet_name,animal_type='dog'):
print("\nI have a " + animal_type)
print("My " + animal_type + "'s name is " + pet_name.title()) describe_pet('jack') # 默认animal_type='dog'
describe_pet('pick','cat') # 使用位置实参,赋值animal_type='cat'
describe_pet(animal_type="cat",pet_name='Hellen') # 关键字传参

上述代码的执行结果为:

C:\Python37\python3.exe D:/pythoncode/Exercise/Exer8/Exer8-2.py

I have a dog
My dog's name is Jack I have a cat
My cat's name is Pick I have a cat
My cat's name is Hellen Process finished with exit code 0

分析:这里修改了函数 describe_pet() 的定义,在其中给形参 animal_type 指定了默认值 'dog' 。这样,调用这个函数时,如果没有给 animal_type 指定值, Python 将把这个形参设置为 'dog' ,如果指定 animal_type的值则就使用指定的值。

3.4、不定长参数

有时候可能我们预先不知道函数需要接受多少个实参,好在 Python 允许函数从调用语句中收集任意数量的实参。

举个栗子:

def make_pizza(*topings):
print(topings) make_pizza('pepperoni')
make_pizza('mushrooms','green peppers','extra cheese')

上述代码的执行结果为:

C:\Python37\python3.exe D:/pythoncode/Exercise/Exer8/Exer8-5.py
('pepperoni',)
('mushrooms', 'green peppers', 'extra cheese') Process finished with exit code 0

分析:上面的make_pizza函数只有一个形参 *toppings ,但不管调用语句提供了多少实参,这个形参都将它们统统收入囊中。形参名 *toppings 中的星号让 Python 创建一个名为 toppings 的空元组,并将收到的所有值都封装到这个元组中,即使是一个值也会生成一个元组。

注意:上面make_pizza函数还有另一种传值方式,test(*[1,2,3,4,5]),这样还是会以元组的方式返回数据

其中 **toping = [1,2,3,4,5]

举个栗子:

def make_pizza(*topings):
print(topings) make_pizza(*'list') ====> ('l', 'i', 's', 't') /传入字符串时返回元组
make_pizza(*(1,2,3)) ====> (1, 2, 3) /传入元组时返回元组
make_pizza(*[1,2,3]) ====> (1, 2, 3) /传入列表时返回元组
make_pizza(*{'first':'name','last':'name2'}) ====> ('first', 'last') /传入字典时,只返回key值元组

3.4.1、结合使用位置实参和任意数量实参

如果要让函数接受不同类型的实参,必须在函数定义中将接纳任意数量实参的形参放在最后。 Python 先匹配位置实参和关键字实参,再将余下的实参都收集到最后一个形参中。

def make_pizza(size,*topings):
print(size,topings) make_pizza(2,'pepperoni')
make_pizza(16,23,45,'mushrooms','green peppers','extra cheese')

上述代码的执行结果为:

C:\Python37\python3.exe D:/pythoncode/Exercise/Exer8/Exer8-5.py
2 ('pepperoni',)
16 (23,45,'mushrooms', 'green peppers', 'extra cheese') Process finished with exit code 0

分析:基于上述函数定义, Python 将收到的第一个值存储在形参 size 中,并将其他的所有值都存储在元组 toppings 中。

注意:*topings只接收位置参数,不能接收关键字参数

当位置参数遇到topings时:就是有位置参数同时也有N个实参传入,首先将值赋给位置参数,然后剩下的多余的值赋给args以元组的形式输出

3.4.2、使用任意数量的关键字实参

有时候,需要接受任意数量的实参,但预先不知道传递给函数的会是什么样的信息。在这种情况下,可将函数编写成能够接受任意数量的 键—值 对 —— 调用语句提供了多少就接受多少。

举个栗子:

def build_profile(first, last, **user_info):
profile = {}
profile['first_name'] = first
profile['last_name'] = last
for key, value in user_info.items():
profile[key] = value
return profile user_profile = build_profile('albert','eniston',
location = 'China',
field = 'physics',
age = 18) print(user_profile)

上述代码的执行结果为:

C:\Python37\python3.exe D:/pythoncode/Exercise/Exer8/Exer8-5.py
{'first_name': 'albert', 'last_name': 'eniston', 'location': 'China', 'field': 'physics', 'age': 18} Process finished with exit code 0

分析:形参 * *user_info 中的两个星号让 Python 创建一个名为 user_info 的空字典,并将收到的所有名称 — 值对都封装到这个字典中。上面的build_profile函数不知道用户会输入多少信息,指明姓名后,再提供住址、年龄等信息,函数都会将这些信息都存储在空字典中。

注意:上述任意数量关键字实参传值时也有两种方法:一是使用键值传值,二是直接调用**{字典}的方式

print(build_profile(**{'first':123,'last':'name'}))  # 也接受**{字典} 的传值方式

# 运行结果
{'first_name': 123, 'last_name': 'name'}
3.4.2.1、当位置参数遇上**kwargs时:
def build_profile(name, **user_info): #name 是一个位置形参  **user_info是用来生成一个空字典接受其他变量
print(name)
print(user_info) # 首先是赋值一个位置实参,然后将后面键值对指定的实参存储到字典里
build_profile('keitter',age=12,location = 'China') # 使用特殊传值方式 **{} 传入的是字典 最后传出的也是字典
build_profile('\njson',**{'first':'jack','location':'China'}) # 当只传入一个位置实参时 则后面的**user_info 还是会生成一个空字典
build_profile('\nkitter') # 当传入的位置参数个数和形参中定义好的位置参数数量不符时就直接报错
build_profile('\nkitter','name',age=12,location = 'China') ===》直接报错
C:\Python37\python3.exe D:/pythoncode/Exercise/Exer8/Exer8-5.py
keitter
{'age': 12, 'location': 'China'} json
{'first': 'jack', 'location': 'China'} kitter
{} Process finished with exit code 0
3.4.2.2、当位置参数、默认参数遇到 **kwargs 时:

注意:默认参数一定不能放到 **kwargs 后面,否则程序会直接报错。

举个栗子:

def build_profile(name, age=18,**user_info):  #name 是一个位置形参  age是默认形参  **user_info是用来生成一个空字典接受其他变量
print(name)
print(age)
print(user_info) # 这很好理解,就是位置实参传值,将默认参数age赋值为12,然后剩下的参数生成字典
build_profile('keitter',12,location = 'China') # 这和上面那个差不多,只不过是使用了关键字实参给默认参数赋值
build_profile('\nHellon',location = 'China',age=23) # 使用特殊传值方式 **{} age值和上面两个一样,可以是位置实参,也可以关键字指定
build_profile('\njson',**{'first':'jack','location':'China'}) # 当只传入一个位置实参时 则会生成默认参数值和后面的**user_info 生成的一个空字典
build_profile('\nkitter')
C:\Python37\python3.exe D:/pythoncode/Exercise/Exer8/Exer8-5.py
keitter
12
{'location': 'China'} Hellon
23
{'location': 'China'} json
18
{'first': 'jack', 'location': 'China'} kitter
18
{} Process finished with exit code 0
3.4.2.3、当位置参数、默认参数遇上 *args 和 **kwargs 时

注意: *args 只接收位置参数,转换成元组的形式,不接收关键字参数

​ * *kwargs 只接收关键字参数,转换成字典的形式

​ **位置顺序不能变, args必须放在 * kwargs 前面 ,位置参数一定是放在默认参数前面,不定长参数肯定是放在最后面。

举个栗子:

def build_profile(name, age=18, *user, **user_info): # 位置参数 默认参数 两种不定长参数
print(name)
print(age)
print(user)
print(user_info) # 位置参数肯定是要匹配的 默认参数可给可不给 *args 只接收位置参数 **kwargs 只接收关键字参数
build_profile('keitter',12,'people',location = 'China') # 多种形参混合时,不能将默认实参放到最后 会直接报错
build_profile('\nHellon','people',location = 'China',age=23) ====》 直接报错 # 特殊参数传递方法 注意在传递*[]时,没有指定默认实参时,会将第一个值赋给默认参数
build_profile('\njson',*[{'name':'jack'},1,2,3],**{'first':'jack','location':'China'},) # 默认没有给 *args 和 * *kwargs 传值时,还是会生成一个空列表和空字典
build_profile('\nkitter','people')
C:\Python37\python3.exe D:/pythoncode/Exercise/Exer8/Exer8-5.py
keitter
12
('people',)
{'location': 'China'} json
{'name': 'jack'} # 注意在传递*[]时,没有指定默认实参时,会将第一个值赋给默认参数
(1, 2, 3) # 注意在传递*[]时,除了传给默认参数的,后面的剩的值还是会生成一个元组
{'first': 'jack', 'location': 'China'} kitter
people
() # 还是会生成一个空列表和空字典
{} Process finished with exit code 0

四、返回值

函数并非总是直接显示输出,相反,它可以处理一些数据,并返回一个或一组值。函数返回的值被称为 返回值 。在函数中,可使用 return 语句将值返回到调用函数的代码行。返回值让你能够将程序的大部分繁重工作移到函数中去完成,从而简化主程序。

返回值的分类:

当返回值数 = 0         ==》返回none

当返回值数 = 1         ==》返回object,是什么就返回什么

当返回值数 > 1         ==》 返回元组(tuple)元组中包含所有的返回值

举个栗子:

def get_formatted(first_name,last_name):
full_name = first_name + ' ' + last_name
return full_name.title() musician = get_formatted('qi','siwill')
print(musician)

上述代码的执行结果为:

C:\Python37\python3.exe D:/pythoncode/Exercise/Exer8/Exer8-3.py
Qi Siwill Process finished with exit code 0

分析:调用返回值的函数时,需要提供一个变量,用于存储返回的值。在这里,将返回值存储在了变量 musician 中

函数可返回任何类型的值,包括列表和字典等较复杂的数据结构

举个返回字典的例子:

def build_people(first_name,last_name):
person = {'first':first_name,'last':last_name}
return person musician = build_people('jack','rose')
print(musician)

上述代码的执行结果为:

C:\Python37\python3.exe D:/pythoncode/Exercise/Exer8/Exer8-3.py
{'first': 'jack', 'last': 'rose'} Process finished with exit code 0

分析:上述代码就是指返回值个数为1 ,那么是什么就返回什么,person是一个字典所以就返回一个字典,如果是其他对象也都返回对应的。

再举个栗子:

def build_people(first_name,last_name):
# person = {'first':first_name,'last':last_name}
return first_name,last_name musician = build_people('jack','rose')
musician2 = build_people('jack','["Rose","jack"]') print(musician)
print(musician2)
C:\Python37\python3.exe D:/pythoncode/Exercise/Exer8/Exer8-3.py
('jack', 'rose')
('jack', '["Rose","jack"]') Process finished with exit code 0

分析:上述代码就是指返回值个数大于1 ,那么则返回一个元组,包含所有值的元组。

Python函数初识的更多相关文章

  1. 从入门到自闭之Python函数初识

    函数初识 定义:def--关键字 ​ 将某个功能封装到一个空间中就是一个函数 功能: ​ 减少重复代码 函数的调用 ​ 函数名+():调用函数和接收返回值 函数的返回值 return 值 == 返回值 ...

  2. python 函数初识和文件操作

    文件操作  打开文件:文件句柄 = open('文件路径', '模式')  打开文件的模式 w #以写的方式打开 (不可读,不存在则创建,存在则删除内容) a #以追加的模式打开(可读, 不存在则创建 ...

  3. Python 函数初识 (1)

    一.今日主要内容 认识函数 函数:对功能或者动作的封装(定义) 语法: def 函数名字(形参) 函数体 函数的调用格式:函数名(实参) 函数的返回值 关键字:return 终止函数的运行 1.函数内 ...

  4. Python函数初识二

    一.变量的作用域LEGB 1.1.变量的作用域 在Python中,程序的变量并不是在哪个位置都可以访问的,访问权限决定于这个变量是在哪里赋值的.变量的作用域决定了在哪一部分程序可以访问哪个特定的变量名 ...

  5. 9.Python初窥门径(函数初识)

    Python(函数初识) 一.初识函数 面向过程缺点 : 代码重复,代码描述性不高 函数 : 函数是以功能为导向,一个函数封装一个功能. 函数的优点 : 减少代码重复性,增强了代码的可读性 二.函数的 ...

  6. 从入门到自闭之Python基础——函数初识

    1. 文件操作: 读操作: 格式:f = open("文件路径",mode = "r",encoding = "utf-8") f : 代表 ...

  7. python函数-函数初识

    python函数-函数初识 1.函数的定义 语法 def 函数名(参数1,参数2,参数3,...): '''注释''' 函数体 return 返回的值 2.函数的使用原则---先定义后调用 #定义阶段 ...

  8. Python函数01/函数的初识/函数的定义/函数调用/函数的返回值/函数的参数

    Python函数01/函数的初识/函数的定义/函数调用/函数的返回值/函数的参数 内容大纲 1.函数的初识 2.函数的定义 3.函数的调用 4.函数的返回值 5.函数的参数 1.函数初识 # def ...

  9. 【python 3】 函数 初识

    函数初识 1.函数的定义.调用.返回值 函数的定义.调用.返回值 def demo(): ## 定义函数 (def + 空格 + 函数名 + () + 冒号) ## 如下为函数体 return a # ...

随机推荐

  1. 打包dll发布到nuget服务器

    几个月前上传过一次nuget包,结果好久不用,今天想更新下,完全忘记了怎么用了,又是一顿查,所以决定记录下来,当然这可能不是一个傻瓜式的教程,但聪明的你们应该能够看明白的,因为整体操作还是很简单的 好 ...

  2. jmeter验证WEB页面的href链接请求

    1. 第一步: 创建Samper_HTTP请求,打开测试页面 2. 第二步: 创建后置处理器_正则表达式(也有其他方式,这里仅介绍正则) 如图 3. 第三步 创建逻辑控制器_ForEach控制器,配置 ...

  3. 集合之Iterator

    迭代对于我们搞Java的来说绝对不陌生.我们常常使用JDK提供的迭代接口进行Java集合的迭代. Iterator iterator = list.iterator(); while(iterator ...

  4. 重载全局new/delete实现内存检测

    下面介绍用重载new/delete运算符的方式来实现一个简单的内存泄露检测工具,基本思想是重载全局new/delete运算符,被检测代码调用new和delete运算符时就会调用重载过的operator ...

  5. p​o​s​t​m​a​r​k​使​用

    一.Postmark原理 Postmark是由着名的NAS提供商NetApp开发,用来测试其产品的后端存储性能. Postmark主要用于测试文件系统在邮件系统或电子商务系统中性能,这类应用的特点是: ...

  6. 用HTML编写阿里云

    <!DOCTYPE html><html><head lang="en"> <meta charset="UTF-8" ...

  7. 2015539平措卓玛课堂测试(ch06)

    课堂测试(ch06) 1.下面代码中,对数组x填充后,采用直接映射高速缓存,所有对x和y引用的命中率为(D) A .1 B .1/4 C .1/2 D .3/4 解析:缓存命中:当程序需要第(k+1) ...

  8. v$pwfile_user表

    SQL> select * from v$pwfile_users;select * from v$pwfile_users; USERNAME SYSDB SYSOP SYSAS------- ...

  9. 安装OpenLDAP步骤

    磨砺技术珠矶,践行数据之道,追求卓越价值 回到上一级页面: PostgreSQL杂记页     回到顶级页面:PostgreSQL索引页 [作者 高健@博客园  luckyjackgao@gmail. ...

  10. 北京Uber优步司机奖励政策(4月19日)

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...