Python函数的定义使用、return返回值、参数传递方式、结合字典列表循环的使用以及将函数存储在模块中

本文详细介绍了Python函数的各个方面,包括如何定义函数、使用return返回值、参数传递方式(位置参数、关键字参数、默认值参数、可变参数)以及如何将函数存储在模块中。通过示例展示了函数的使用,强调了函数的组织和可维护性,以及在函数中如何处理字典和列表。此外,还讨论了导入模块的多种方式,如导入整个模块、导入特定函数、使用别名等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

函数编写指南

  1. 应给函数指定描述性名称,且只在其中使用小写字母和下划线。
  2. 在编写代码完成某任务时,可以编写一系列的函数来完成任务,每个函数都完成其中某一项具体的工作,这样测试和维护起来更容易。
  3. 每个函数都应包含简要地阐述其功能的注释。该注释应紧跟在函数定义后面,并采用文档字符串格式(“”“…”“”)。
  4. 给形参指定默认值和调用函数中的关键字参数时,等号两边不要有空格。PEP 8 建议代码行的长度不超过79字符,若函数定义时形参很多,长度超过79字符,可在函数定义中输入左括号后按回车键,并在下一行按两次 tab 键。如下所示:
def function_name(
		parameter_0,parameter_1,parameter_2,
		parameter_3,parameter_4,parameter_5):
	function body...

函数的定义

定义函数的语法格式如下:

def <函数名>(<形参1,形参2, …>):
<函数体>
return <返回值列表>

函数定义以 def 关键字开头,后接函数名和圆括号;圆括号可以用于定义参数,函数可以有0个、1个或多个参数,有多个参数时各参数由逗号分隔。

<函数体>是函数每次被调用时执行的代码,由一行或多行语句组成。

return <返回值列表>结束函数,选择性地返回一个值给调用方;函数可以没有return语句,<函数体>执行结束后将控制权交给调用方。

def favorite_book(title):
    print(f"One of my favorite books is {title.title()}")
    
favorite_book('alice in wonderland')

输出结果:

One of my favorite books is Alice In Wonderland

函数的返回值return

(一)返回值的个数(0个,1个,多个)

所有函数都有返回值,如果没有 return 语句,会隐式地调用 return None 作为返回值。如果函数执行了 return 语句,函数会立刻返回,结束调用,return 语句之后的其他语句都不会被执行。

return 语句可以出现在函数的任何部分,同时可以将0个、1个或多个函数运算的结果返回给函数被调用处的变量。

一个函数可以存在多条 return 语句,但只有一条 return 语句可以被执行。

当有多个返回值时,可以使用一个变量(元组数据类型)或多个变量保存结果。例如:

  1. 函数没有返回值
def multiply(a,b):
    a * b   #函数没有返回值
s = multiply(2,5)
print(s)

输出结果:

None

  1. 函数有一个返回值
def multiply(a,b):
    return a * b   #函数有一个返回值
s = multiply(2,5)
print(s)

输出结果:

10

  1. 函数有多个返回值
def multiply(a,b):
    return a * b, a + b, a - b   #函数有多个返回值
s = multiply(2,5)   #使用一个变量保存结果
print(s)
m,n,k = multiply(2,5)   #使用多个变量保存结果
print(m)
print(n)
print(k)

输出结果:

(10, 7, -3)
10
7
-3

函数并非总是直接显示输出,它还可以处理一些数据,并返回一个或一组值。例如:

def get_formatted_name(first_name,last_name):
    """返回整洁的姓名。"""
    full_name = f"{first_name} {last_name}"
    return full_name.title()

musician = get_formatted_name('jimi','hendrix')
print(musician)

输出结果:

Jimi Hendrix

(二)return终止函数程序运行的功能(提前退出)

例1:

def check(flag):
    if flag:
        return 'a'
    return 'b'

print(check(1))
print(check(0))

输出结果:

a
b

当执行了第一个return,返回第一个return的值,第二个return不再执行。

例2:
默认情况下,遇见 return 函数就会返回给调用者,但是 try,finally情况除外:

def fun(): 
    try: 
        print(100)
        return 'abc'
        print(199)
        
    finally:   # finally语句块不管在什么情况下都会执行
        print(1000)

fun()

输出结果:

100
1000
‘abc’(交互式的输出结果,单独运行脚本中要写 print(fun() 才能显示return的结果)

注:
在交互模式下,return的结果会自动打印出来,而作为脚本单独运行时则需要print函数才能显示!!

参数的传递方式

实参和形参

  1. 形参:在函数定义时传入的参数被称为形参,形参不是实际存在的变量。
  2. 实参:函数调用时实际传入的参数被称为实参。

位置参数

要求"实参的数量与顺序"必须和函数声明时"形参的数量与顺序"相同。

def test(a,b):
    print(a,b)
test(3,4)
test(1,2)

输出结果:

3 4
1 2

关键字参数

关键字实参是传递给函数的名称值对,直接在实参中将名称和值关联起来。此时实参的顺序和形参的顺序可以不一致。

def test(a,b,c):
    print(a,b,c)
test(b=4,a=21,c=5)

输出结果:

21 4 5

默认值参数

使用默认值时,必须先在形参列表中列出没有默认值的形参,再列出有默认值的实参。否则会报错。

def make_shirt(size,pattern='I love Python'):
    print(f'''该T恤的尺码为{size},字样为"{pattern}"''')
    
make_shirt(size='M')
make_shirt('s','中国')

输出结果:

该T恤的尺码为M,字样为"I love Python"
该T恤的尺码为s,字样为"中国"

有时候,需要让参数变成可选的,这时可以将形参指定一个空的默认值。例如:

# 使用默认值让实参变成可选的

def get_formatted_name(first_name, last_name, middle_name=''):
	 """返回整洁的姓名。"""
    if middle_name:
        full_name = f"{first_name} {middle_name} {last_name}"
    else:
        full_name = f"{first_name} {last_name}"
    return full_name.title()

misician = get_formatted_name('jimi','hendrix')
print(misician)

misician = get_formatted_name('jimi','hooker','lee')
print(misician)

输出结果:

Jimi Hendrix
Jimi Lee Hooker

当有多个默认值参数时,传入参数时需要区分位置参数和默认值参数,例如:

def people(name,age=23,addr='杭州'):
    print("\n我的名字是",name)
    print("今年",age)
    print("现在居住在",addr)

people('Jack',addr='西安',age=44)
people('Jack',21,addr='北京')
people('Jack',22,'成都')

输出结果:


我的名字是 Jack
今年 44
现在居住在 西安

我的名字是 Jack
今年 21
现在居住在 北京

我的名字是 Jack
今年 22
现在居住在 成都

但如果按照以下方式传入参数,则会报错positional argument follows keyword argument(位置参数跟随关键字参数):

people('Jack',age=21,'北京')

输出结果:

  File "<ipython-input-36-163ee5b58933>", line 1
    people('Jack',age=21,'北京')
                        ^
SyntaxError: positional argument follows keyword argument

注:如果第一个默认值参数想要通过指定参数名(如age=21)来更改参数值,则其他需要更改的默认值参数都需要指定参数名来更改参数,否则报错。

可变参数(任意数量实参)

python允许函数从调用语句中收集任意数量的实参。
可变参数主要有两种表现形式:*param 和 **param

*param:表示可以接收多个位置参数收集的实参组成一个元组
**param:表示可以接收多个关键字参数收集的实参名和值组成的一个字典

例1:

def make_pizza(*toppings):
    """概述要制作的披萨。"""
    print("\nMaking a pizza with the following toppings:")
    for topping in toppings:
        print(f"- {topping}")
        
make_pizza('pepperoni')
make_pizza('mushrooms','green peppers','extra cheese')

输出结果:

Making a pizza with the following toppings:
- pepperoni

Making a pizza with the following toppings:
- mushrooms
- green peppers
- extra cheese

其中形参名*toppings中的星号让python创建一个名为toppings的空元组,
并将收到的所有值都封装到这个元组中。

例2:(结合使用位置参数和任意数量实参)

def make_pizza(size,*toppings):
    """概述要制作的披萨。"""
    print(f"\nMaking a {size}-inch pizza with the following toppings:")
    for topping in toppings:
        print(f"- {topping}")
        
make_pizza(16,'pepperoni')
make_pizza(12,'mushrooms','green peppers','extra cheese')

输出结果:

Making a 16-inch pizza with the following toppings:
- pepperoni

Making a 12-inch pizza with the following toppings:
- mushrooms
- green peppers
- extra cheese

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

如果要让函数接受不同类型的实参,必须在函数定义中将接纳任意数量实参的形参放在最后。

例3:

def build_profile(first,last,**user_info):
	"""创建一个字典,其中包含我们知道的有关用户的一切。"""
    user_info['first_name'] = first
    user_info['last_name'] = last
    return user_info

user_profile = build_profile('albert','einstein',
                             location='princeton',
                             field='physics')
print(user_profile)

输出结果:

{‘location’: ‘princeton’, ‘field’: ‘physics’, ‘first_name’: ‘albert’, ‘last_name’: ‘einstein’}

形参**user_info中的两个星号让python创建一个名为user_info的空字典,并将收到的所有名称值对都放到这个字典中。由于名和姓没有放到字典中,所以在函数体内把这两项信息也加入字典中。

例4:

def make_car(manufacturer, model, **options):
    """创建一个表示汽车的字典。"""
    car_dict = {
        'manufacturer': manufacturer.title(),
        'model': model.title(),
        }
    for option, value in options.items():
        car_dict[option] = value
    
    return car_dict

my_outback = make_car('subaru', 'outback', color='blue', tow_package=True)
print(my_outback)

my_old_accord = make_car('honda', 'accord', year=1991, color='white',headlights='popup')
print(my_old_accord)

输出结果:

{‘manufacturer’: ‘Subaru’, ‘model’: ‘Outback’, ‘color’: ‘blue’, ‘tow_package’: True}
{‘manufacturer’: ‘Honda’, ‘model’: ‘Accord’, ‘year’: 1991, ‘color’: ‘white’, ‘headlights’: ‘popup’}

组合使用多种参数

编写函数时,能以各种方式混合使用位置参数、关键字参数、默认值和可变参数(任意数量实参)。但需要注意使用顺序必须是:位置参数、默认值参数、可变参数及关键字参数。

def test(a,b,c=1,*p,**k):
    print('a=',a,'b=',b,'c=',c,'p=',p,'k=',k)
    
test(3,4)
test(3,4,5)
test(3,4,5,'A','B')
test(5,'A','B',x=7,y=8)
test(3,4,5,'AB',x=7,y=8)

输出结果:

a= 3 b= 4 c= 1 p= () k= {}
a= 3 b= 4 c= 5 p= () k= {}
a= 3 b= 4 c= 5 p= (‘A’, ‘B’) k= {}
a= 5 b= A c= B p= () k= {‘x’: 7, ‘y’: 8}
a= 3 b= 4 c= 5 p= (‘AB’,) k= {‘x’: 7, ‘y’: 8}

利用函数返回字典

def build_person(first_name, last_name, age = None):  
	"""返回一个字典,其中包含有关一个人的信息。"""
    person = {'first': first_name, 'last':last_name}
    if age:
        person['age'] = age
    return person

musician = build_person('jimi','hendrix')
print(musician)

musician = build_person('jimi','hendrix',age=27)
print(musician)

输出结果:

{‘first’: ‘jimi’, ‘last’: ‘hendrix’}
{‘first’: ‘jimi’, ‘last’: ‘hendrix’, ‘age’: 27}

在函数定义中,新增一个可选形参age,将默认值设置为特殊值None(表示变量没有值),可将None视为占位值。在条件测试(if age:)中,None相当于False。

结合使用函数和while循环

例1:
编写一个函数使用名和姓跟用户打招呼。

def get_formatted_name(first_name,last_name):
    """返回整洁的姓名。"""
    full_name = f"{first_name} {last_name}"
    return full_name.title()

while True:
    print("\nPlease tell me your name:")
    print("(enter 'q' at any any time to quit.)")
    
    f_name = input("First_name:")
    if f_name == 'q':
        break
    
    l_name = input("Last_name:")
    if l_name == 'q':
        break
        
    formatted_name = get_formatted_name(f_name, l_name)
    print(f"\nHello, {formatted_name.title()}!")

用户输入及输出结果:(粗体部分是用户输入!)

Please tell me your name:
(enter ‘q’ at any any time to quit.)
First_name:eric
Last_name:matthes

Hello, Eric Matthes!

Please tell me your name:
(enter ‘q’ at any any time to quit.)
First_name:q

例2:
编写一个while循环,让用户输入专辑的歌手和名称。

def make_album(artist, title, tracks = 0):
    """创建一个包含专辑信息的字典。"""
    album_dict = {
        'artist': artist.title(),
        'title': title.title(),
        }
    if tracks:
        album_dict['tracks'] = tracks
    return album_dict

# 生成提示语:
title_prompt = "\nWhat album are you thinking of? "
artist_prompt = "Who's the artist? "

# 让用户知道如何退出:
print("Enter 'quit' at any time to stop.")

while True:
    title = input(title_prompt)
    if title == 'quit':
        break
    
    artist = input(artist_prompt)
    if artist == 'quit':
        break
        
    album = make_album(artist, title)
    print(album)

print("\nThanks for responding!")

用户输入及输出结果:(粗体部分是用户输入!)

Enter ‘quit’ at any time to stop.

What album are you thinking of? number of the beast
Who’s the artist? iron maiden
{‘artist’: ‘Iron Maiden’, ‘title’: ‘Number Of The Beast’}

What album are you thinking of? rust in peace
Who’s the artist? megadeth
{‘artist’: ‘Megadeth’, ‘title’: ’ Rust In Peace’}

What album are you thinking of? quit

Thanks for responding!

向函数传递列表

def greet_users(names):
    """向列表中的每位用户发出简单的问候。"""
    for name in names:
        msg = f"Hello,{name.title()}!"
        print(msg)

names = ['hannah','ty','margot']
greet_users(names)

输出结果:

Hello,Hannah!
Hello,Ty!
Hello,Margot!

在函数中修改列表

案例:这是一家为用户提交的设计制作3D打印模型的公司。需要打印的设计存储在一个列表中,设计完成打印后将移到另一个列表中。

首先,在不使用函数的情况下模拟这个过程:

# 首先创建一个列表,其中包含一些要打印的设计
unprinted_designs = ['phone case','robot pendant','dodecahedron']
completed_models = []

# 模拟打印每个设计,直到没有未打印的设计为止。
# 打印每个设计后,都将其移到列表completed_models中。
while unprinted_designs:
    current_design = unprinted_designs.pop()
    print(f"Printing model: {current_design}")
    completed_models.append(current_design)

#显示打印好的所有模型
print("\nThe following models have been printed:")
for completed_model in completed_models:
    print('\t',completed_model)

输出结果:

Printing model: dodecahedron
Printing model: robot pendant
Printing model: phone case

The following models have been printed:
	 dodecahedron
	 robot pendant
	 phone case

然后,编写两个函数重新组织这些代码:

def print_models(unprinted_designs, completed_models):
    """
    模拟打印每个设计,直到没有未打印的设计为止。
    打印每个设计后,都将其移到列表completed_models中。
    """
    while unprinted_designs:
        current_design = unprinted_designs.pop()
        print(f"Printing model: {current_design}")
        completed_models.append(current_design)
        
def show_completed_models(completed_models):
    """显示打印好的所有模型"""
    print("\nThe following models have been printed:")
    for completed_model in completed_models:
        print('\t',completed_model)
        
unprinted_designs = ['phone case','robot pendant','dodecahedron']
completed_models = []

print_models(unprinted_designs, completed_models)
show_completed_models(completed_models)

输出结果:

Printing model: dodecahedron
Printing model: robot pendant
Printing model: phone case

The following models have been printed:
	 dodecahedron
	 robot pendant
	 phone case

这时,每个函数都应只负责一项具体的工作。相比没有使用函数的版本,这个程序更容易扩展和维护。

注:
如果需要禁止函数修改列表,例如像案例中不想清空未打印的设计列表 unprinted_designs,可以这样调用函数:

print_models(unprinted_designs[:], completed_models)

其中unprinted_designs[:]表示创建了副本,函数中所做的修改不会影响到原始列表。

虽然向函数传递列表的副本可保留原始列表的内容,但是除非有充分的理由,否则还是应该将原始列表传递给函数。这是因为让函数使用现成的列表可避免花时间和内存创建副本,从而提高效率,在处理大型列表时尤其如此。

将函数存储在模块中

关于导入模块和函数的通用语法公式:

说明通用语法公式
导入模块中的特定函数from module_name import function_name
导入模块中任意数量的函数from module_name import function_0,function_1,function_2
给函数指定别名from module_name import function as fn
给模块指定别名import module_name as mn
导入模块中所有的函数import module_name as *

将函数存储在称为模块的独立文件中,再利用import语句将模块导入到主程序中。通过将函数存储在独立的文件中,可隐藏程序代码的细节,将重点放在程序的高层逻辑上,还能在众多不同的程序中重用函数。

接下来,通过一个制作披萨的函数来解释各种导入的方法:

导入整个模块

模块是扩展名为 .py 的文件,包含要导入到程序中的函数代码。

首先,将函数 make_pizza() 存储在一个名为 pizza.py 文件中,相当于创建了一个包含函数 make_pizza() 的模块。

将函数make_pizza()存储在一个.py文件中

然后,在同一个路径再创建另一个文件通过 import 语句调用这个模块来打开使用这个函数。代码如下:

import pizza

pizza.make_pizza(16,'pepperoni')
pizza.make_pizza(12,'mushrooms','green peppers','extra cheese')

输出结果:

Making a 16-inch pizza with the following toppings:
- pepperoni

Making a 12-inch pizza with the following toppings:
- mushrooms
- green peppers
- extra cheese

这就是一种导入方法,只需要编写一条 import 语句并在其中指定模块名,就可在程序中使用该模块中的所有函数。

如果使用这种 import 语句导入了名为 module_name.py 的整个模块,就可以使用 module_name.function_name() 来使用其中的任何一个函数。

导入特定的函数

from pizza import make_pizza

make_pizza(16,'pepperoni')
make_pizza(12,'mushrooms','green peppers','extra cheese')

使用这种语法时,调用函数时无须使用句点,直接指定函数名称即可。输出结果同上(后面的也一样)。

使用 as 给函数指定别名

如果要导入函数的名称可能与程序中现有名称冲突,或者函数的名称太长,可指定简短而独一无二的别名。

from pizza import make_pizza as mp

mp(16,'pepperoni')
mp(12,'mushrooms','green peppers','extra cheese')

使用 as 给模块指定别名

import pizza as p

p.make_pizza(16,'pepperoni')
p.make_pizza(12,'mushrooms','green peppers','extra cheese')

导入模块中的所有函数

使用星号 * 运算符可以让 Python 导入模块中所有的函数。由于导入了每个函数,通过名称来调用每个函数,无须使用句点表示法。

from pizza import *

make_pizza(16,'pepperoni')
make_pizza(12,'mushrooms','green peppers','extra cheese')

注:
使用并非自己编写的大型模块时,最好不要采用这种导入方法。Python 可能遇到多个名称相同的函数或变量,进而覆盖函数,而不是分别导入所有的函数。

ps:大多数内容来源于埃里克马瑟斯的蟒蛇书《Python编程从入门到实践》第八章!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值