Python函数的定义与实现


1. 函数的介绍

  • \color{green}{函数是什么:}

函数是 实现具有特定功能的代码块
Python中预制了许多内置函数,也可以根据自己的需求创建自定义的函数

  • \color{cyan}{函数的特点:}

隐藏实现功能的细节
代码的复用
提高可读性,便与调试

  • \color{gray}{函数的定义:}

def 函数名(形参1, 形参2...):
要运行的代码块(函数体)
return 返回的数据(返回值)

函数名要有描述性,建议使用下划线的格式: 动作_描述()
在函数体内定义的变量是局部变量,只能作用于该函数



2. 形参和实参


2.1 形参/实参介绍

  • \color{blue}{示例:}
# 定义一个简单的问候函数
def print_hello(username):
    print("hello,{}".format(username))

# 调用函数,传入参数
print_hello("world")

  -- run --
hello,world

以上示例中,变量 username是一个形参函数完成其工作所需的一项信息,在调用函数中,值 "world"是一个实参实参是调用函数时传递给函数的信息,将实参传递给函数 print_hello() ,这个值被存储在形参 username

  • \color{green}{传递实参:}

函数定义中可能包含多个形参,因此函数调用中也可能包含多个实参,接下来会介绍向函数传递实参的方式


2.2 位置实参

  • \color{green}{方法:}

位置实参:要求实参的顺序与形参的顺序对应
定义:def 函数名(形参1, 形参2, 形参3):
调用:函数名(实参1, 实参2, 实参3)

位置实参的顺序很重要,如果实参的顺序与形参不相同,最终的函数结果可能出乎意料

  • \color{blue}{示例:}
# 定义一个宠物信息函数
def pet_describe(pet_type, pet_name):
    "显示宠物类型和名字"
    print("我的宠物是一只{},它的名字是{}".format(pet_type, pet_name))

# 实参与形参顺序相同
pet_describe("猫", "大橘")
# 实参与形参的顺序不同
pet_describe("大橘", "猫")

  -- run --
我的宠物是一只猫,它的名字是大橘
我的宠物是一只大橘,它的名字是猫

2.3 关键字实参

  • \color{green}{方法:}

关键字实参:每个实参都由变量名和值组成
定义:def 函数名(形参1, 形参2, 形参3):
调用:函数名(形参2=实参2, 形参3=实参3, 形参1=实参1)

关键字实参是传递给函数的 名称-值 对,直接在实参中将名称和值关联起来,因此无需考虑函数调用中的实参顺序

  • \color{blue}{示例:}
# 接着用上面位置实参的示例
def pet_describe(pet_type, pet_name):
    "显示宠物类型和名字"
    print("我的宠物是一只{},它的名字是{}".format(pet_type, pet_name))

# 明确指出了各个实参对应的形参,无需关注参数顺序
pet_describe(pet_type="猫", pet_name="大橘")
pet_describe(pet_name="大橘", pet_type="猫")

  -- run --
我的宠物是一只猫,它的名字是大橘
我的宠物是一只猫,它的名字是大橘

使用关键字实参时,务必准确的指定函数定义中的形参名


2.4 混合传参

  • \color{green}{介绍:}

使用位置实参与关键字实参混合使用的方式

使用混合传参时,关键字参数必须在位置参数后面

  • \color{blue}{示例:}
# 位置参数要放在最前面
def pet_describe(pet_type, pet_name, age):
    "显示宠物类型和名字"
    print("我的宠物是一只{},它的名字是{},今年{}岁".format(pet_type, pet_name, age))

pet_describe("猫", age=1, pet_name="大橘")

  -- run --
我的宠物是一只猫,它的名字是大橘,今年1岁

2.5 限制位置实参

  • \color{green}{方法:}

定义:def 函数名(形参1, *, 形参2, 形参3):
调用:函数名(实参1, 形参2=实参2, 形参3=实参3)

星号 * 代表之后所有参数传参时 必须使用关键字传参

  • \color{blue}{示例:}
# *号之后的都必须使用关键字传参法,否则报错
def pet_describe(pet_type, *, pet_name, age):
    "显示宠物类型和名字"
    print("我的宠物是一只{},它的名字是{},今年{}岁".format(pet_type, pet_name, age))

pet_describe("猫", "大橘", 1)

  -- run --
Traceback (most recent call last):
  File "D:\Python\imooc\2.Python函数与模块\2.1.函数的定义与实现\2.1.1.function\test.py", line 5, in <module>
    pet_describe("猫", "大橘", 1)
TypeError: pet_describe() takes 1 positional argument but 3 were given
# 类型错误:pet_describe()接受1个位置参数,但给出了3个

2.6 设置参数的默认值

  • \color{green}{方法:}

定义:def 函数名(形参=默认值):

在定义函数时,可以根据需要给指定的形参设置默认值

  • \color{red}{注意:}
  • 在调用函数中如果给该形参提供了实参,则使用指定的实参值,否则使用形参的默认值
  • 设置默认值时,在形参列表中必须 先列出没有默认值的形参再列出有默认值的形参 ,这让Python依然能够正确的解读位置实参
  • \color{blue}{示例:}
# 给设置了默认值的形参指定实参时,也可以用位置实参
def pet_describe(pet_name, age, pet_type="猫"):
    "显示宠物类型和名字"
    print("我的宠物是一只{},它的名字是{},今年{}岁".format(pet_type, pet_name, age))

pet_describe("大橘", 1)
pet_describe("大白", 0.5, "狗")

  -- run --
我的宠物是一只猫,它的名字是大橘,今年1岁
我的宠物是一只狗,它的名字是大白,今年0.5岁
  • \color{green}{让实参变成可选的:}

定义:def 函数名(形参=''):

通过给形参设置空字符串的默认值后,实参就变成可选的了,这样使用函数就只需要在必要时才提供额外的信息

  • \color{blue}{示例:}
# 姓 + 名 + 中间名(可选)组成完整的名字
def get_formatted_name(first_name, last_name, middle_name=''):
    "返回完整的姓名"
    if middle_name:
        full_name = "{} {} {}".format(first_name, middle_name, last_name)
    else:
        full_name = "{} {}".format(first_name, last_name)
    return full_name.title()

print(get_formatted_name("jimi", "hendrix"))
print(get_formatted_name("john", "hooker", "lee"))

  -- run --
Jimi Hendrix
John Lee Hooker

2.7 使用序列传参

  • \color{green}{方法:}

调用:函数名(*序列名)

序列不是Python中的某一种数据类型,而是一种数据结构的统称,如: 列表、元组、数字序列、字符串等 都称为序列,具体请移步 Python序列

  • \color{blue}{整个传入示例:}
# 定义一个简单的数学计算函数
def calc(a, b, c):
    d = (a + b) * c
    return d

# 位置传参
print(calc(1, 5, 10))

# 使用列表序列传参
num_list1 = [2, 4, 6]
print(calc(*num_list1))

  -- run --
60
36
  • \color{blue}{依次传入示例:}
# 函数内定义了遍历语句,所以列表元素是依次传入,不需要加*
def greet_users(names):
    "问候列表中的每个用户"
    for name in names:
        print("Hello,{}".format(name))

username = ["张三", "李四", "王五"]
greet_users(username)

  -- run --
Hello,张三
Hello,李四
Hello,王五

2.8 使用字典传参

  • \color{green}{方法:}

调用:函数名(**字典名)

使用字典传参时,类似于关键字传参,字典key的排列顺序无需对应形参的顺序,但是两者的名称、数量必须一致

  • \color{blue}{示例:}
# 定义一个简单员工信息函数
def fun_dict(name, hiredate, tel, dept):
    print("{p1}隶属于{p4},电话:{p3},入职如期:{p2}".format(p1=name, p2=hiredate, p3=tel, p4=dept))

# 字典传参,key的名称要和形参对上,key的数量也要和形参数一致
dict1 = {'name':'张三','hiredate':'2020-06-27','dept':'技术部','tel':13012345678}
fun_dict(**dict1)

  -- run --
张三隶属于技术部,电话:13012345678,入职如期:2020-06-27


3. 函数的返回值


3.1 函数中的return

  • \color{green}{介绍:}

参数是函数的输入数据,而返回值则是函数的输出结果

return 不是必须的,return语句 执行后,函数将中断执行

  • \color{green}{关于return的解释:}
    return解释.png
无return的函数.png
return与print区别.png

上述回答来自知乎用户“sqybi”,个人觉得通俗易懂,就摘录下来了,感谢大佬的解惑!

  • \color{blue}{示例:}
# 示例1:print
def print_hello():
    print("hello")

print_hello()
str1 = print_hello()
print(str1)

  -- run --
hello
hello
None

# 示例2:return
def print_hello():
    return "hello"

print_hello()
print(print_hello())
str2 = print_hello()
print(str2)

  -- run --
hello
hello

上述示例中,print是将结果打印在标准输出(屏幕)上,所以直接调用函数名就能执行打印;return是将结果保存至内存,打印时需要借助print函数
使用print的函数赋值时,由于没有返回值,仅有打印屏幕的操作,所以赋值变量返回的是 None ;而使用return的函数赋值时,将保存在内存中的返回值赋值给变量,所以赋值变量有返回值


3.2 返回值包含多个数据

  • \color{green}{介绍:}

在函数内定义嵌套字典,调用函数时使用不同的索引就可以获取多个返回数据

  • \color{blue}{示例:}
# 定义一个包含公司内信息的嵌套字典函数(仅列举部分信息)
def get_detail_info():
    dict1 = {
        "employee": [
            {"name": "张三", "salary": 3000},
            {"name": "李四", "salary": 4000}
        ],
        "device": [
            {"id": "88888888", "title": "xx笔记本"},
            {"id": "66666666", "title": "xx台式机"}
        ],
        "...": [{}, {}],
        "......": [{}, {}]
    }
    return dict1

# 获取员工张三的薪资信息
d = get_detail_info()
sal = d.get("employee")[0].get("salary")
print(sal)

# 获取xx台式机设备的id号
dev = d.get("device")[1].get("id")
print(dev)

  -- run --
3000
66666666

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 230,431评论 6 544
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 99,637评论 3 429
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 178,555评论 0 383
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 63,900评论 1 318
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 72,629评论 6 412
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 55,976评论 1 328
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 43,976评论 3 448
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 43,139评论 0 290
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 49,686评论 1 336
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 41,411评论 3 358
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 43,641评论 1 374
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 39,129评论 5 364
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 44,820评论 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 35,233评论 0 28
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 36,567评论 1 295
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 52,362评论 3 400
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 48,604评论 2 380