Python 基础 -- 函数

本文详细介绍了Python中的函数定义,包括如何定义、传递信息、形参与实参的区别,以及练习案例。此外,还讨论了不同类型的参数传递方式,如位置实参、关键字实参和默认值。同时,介绍了如何使用函数返回值,包括返回简单值、可选参数和返回字典。最后,讲解了如何将函数存储在模块中以及如何导入和使用模块中的函数。这些内容涵盖了函数的基础知识和高级用法,有助于提升代码的复用性和组织性。
摘要由CSDN通过智能技术生成

  • 函数是带名字的代码块;
  • 函数是组织好的,可以重复使用的,用来实现单一或相关功能的代码段;
  • Python 提供了许多内建函数,比如 print()
  • 自己编写的函数称为自定义函数;

1. 定义函数

  • 首先以一个简单的函数为例,来讲解函数:

    def greet_user():
    	"""显示简单的问候语"""
    	print("Hello!")
    
    greet_user()
    
    • 第一行中:
      • def 是定义函数的关键字,此关键字将会告诉 Python 这段程序是函数;
      • greet_user() 是函数名称,括号中,可以传递参数给函数,通过函数处理在输出,也可以不传递,就像这个函数,只是简单的打印一句话;
      • : 是必循存在的,就跟之前的 if 语句以及 for 循环一样,用来表示下面紧跟着的缩进内容都是这个函数的一部分;
    • 第二行:
      • 六个双引号之间的文本被称为文档字符串,算是一种注释,对函数的描述;
    • 第三行:
      • 是函数 greet_user() 唯一的一行代码,只做打印输出;
  • 输出结果:
    在这里插入图片描述

1.1 函数定义规则及语法

  • 定义函数规则:由上述例子,我们可以简单归纳以下定义函数的规则;

    • 函数代码块以 def 关键字开头,后接函数标识符名称和圆括号,最后以冒号结尾;
    • 函数代码块中的内容缩进;
    • 函数第一行语句可以选择性的使用文档字符串进行注释说明;
  • 定义函数语法

    def function_name():
        """文档字符串"""
        function_suite
    

1.2 向函数传递信息

  • 对函数进行修改,可以使得函数 greet_user()不仅可以向用户显示 Hello,还可以将用户的名字添加进入;

  • 为此,只需要在括号中添加适当的参数即可;

  • 这里通过 username,就可以让函数接受你给 username 的任何值;

  • 当添加了参数 username 后,在调用函数时,就必须要给 username 指定一个值;

    def greet_user(username):
    	"""显示简单的问候语"""
    	msg = "Hello, " + username + "!" 
    	print(msg)
    
    greet_user('Eric')
    
  • 当调用代码时,传递进入 Eric 之后,函数会接受传递的名字,并向这个用户发出问候:
    在这里插入图片描述

1.3 形参和实参

  • 形参:就是函数完成工作时,所需要的信息,例如 1.2 节中的 username ,当函数在没有被调用时,需要逻辑上的完整,就需要用这种形式上的参数,来完成工作;
  • 实参:调用函数时传递给函数的信息,例如 1.2 节中调用函数时,传递的 Eric
  • 在 1.2 节中,我们使用函数 greet_user() 时,将实参 Eric 传递给了函数 greet_user(),然后将实参的值,存储在了形参 username 中;

1.4 练习

  • 编写一个名为 display_messge() 的函数,它打印一个句子,指出本章学的内容,并调用这个函数,确认显示消息正确无误:
    在这里插入图片描述

  • 编写一个名为 favorite_book() 的函数,其中包含一个名为 title 的形参。这个函数打印一条消息,如 One of my favorite books is Alice in Woderland。调用这个函数,并将一本图书的名称作为实参传递给它。
    在这里插入图片描述

2. 传递实参

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

2.1 位置实参

  • 调用函数时, Python 必须将函数调用中的每个实参都关联到函数定义中的一个形参。

  • 所以,最简单的关联方式就是基于实参的顺序,这种关联方式称为位置实参

  • 以一个简单的显示从无信息的函数为例:

    def describe_pet(animal_type, pet_name):
    	"""显示宠物信息"""
    	msg = "\nI have a " + animal_type + "."
    	print(msg)
    	msg = "My " + animal_type + "'s name is " + pet_name.title() + "."
    	print(msg)
    
    describe_pet('hamster', 'harry')
    
    • 第一行中:有两个形参 animal_typepet_name,当调用函数时,会将传入的实参值进行存储,并等待函数工作时的调用;
  • 结果:
    在这里插入图片描述

  • 函数可以根据需求调用多次

  • 如果再要描述一个宠物,只需再次调用 describe_pet() 即可:
    在这里插入图片描述

  • 调用函数多次是一种效率极高的工作方式;

  • 只需要在函数中编写描述宠物的代码一次,然后每当需要描述新宠物时,都可以调用这个函数,并向他提供新宠物的信息;

  • 位置实参的顺序很重要,如果传入的实参顺序不对,将会出乎意料的结果:
    在这里插入图片描述

2.2 关键字实参

  • 关键字实参是传递给函数的名称-值对;

  • 直接在实参中将名称和值关联起来,因此向函数传递实参时不会混淆;

  • 关键字实参无需考虑函数调用中的实参顺序;

  • 关键字实参清楚的指出了函数调用中的各个值的用途;

  • 使用关键字实参,必须准确的指定函数定义中的形参名;
    在这里插入图片描述

2.3 默认值

  • 有时候,编写一类动物程序时,只是名字不同,种类都相同的情况下,可以个动物类型设定默认值,可以减少参数的传递;

  • 一般在提供了实参的情况下,函数会使用指定的实参;

  • 如果没有指定,将使用形参的默认值;

  • 在有指定默认值的情况下,需要将没有默认值的形参放在形参列表中的前边,将有默认值的放在最后;

  • 上述暂时理解为规定,目前没接触到为什么;
    在这里插入图片描述

2.4 练习

  • 编写一个名为 make_shirt() 的函数,它接受一个尺码以及要印到 T 恤上的字样,这个函数打印一个句子,概要说明 T 恤的尺码和字样;
    在这里插入图片描述

  • 编写一个名为 describe_city() 的函数,它接受一座城市的名字以及该城市所属的国家。这个函数将打印一个简单的句子,如 Reykjavik is in Iceland。
    在这里插入图片描述

3. 返回值

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

3.1 返回简单值

  • 编写一个简单的含有返回值的函数示例,下列函数接收名和姓,返回整洁的名字;

    def get_formatted_name(first_name, last_name):
    	"""返回整洁的姓名"""
    	full_name = first_name + " " + last_name
    	return full_name.title()
    	
    musician = get_formatted_name('jimi', 'hendrix')
    print(musician)
    
  • 结果:
    在这里插入图片描述

3.2 将实参变成可选项

  • 有的人会有中间名,但是有的人没有,但为了简便起见,不可能写上两个程序,这样做会使得调用函数容易出错;

  • 我们先将中间名默认设置为空字符,然后在函数体中根据判断是否需要使用中间名;

    def get_formatted_name(first_name, last_name, middle_name=''):
    	"""返回整洁的姓名"""
    	if middle_name:
    		full_name = first_name + " " + middle_name + " " + last_name
    	else:
    		full_name = first_name + " " + last_name	
    	return full_name.title()
    	
    musician = get_formatted_name('jimi', 'hendrix')
    print(musician)
    
    musician = get_formatted_name('jimi', 'hendrix', 'lee')
    print(musician)
    
    • 在函数体中,使用 if 进行判断时,只要字符串非空,则 Python 将会解读为 True,因此,如果提供中间名,将会执行 if 语句;
  • 结果显示:
    在这里插入图片描述

3.3 返回字典

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

  • 下面的函数接受姓和名返回一个表示人的字典:

    def build_person(first_name, last_name):
    	"""返回一个字典,包含有关一个人的信息"""
    	person = {'first': first_name, 'last': last_name}
    	return person
    	
    musician = build_person('jimi', 'hendrix')
    print(musician)
    
  • 结果:
    在这里插入图片描述

3.4 结合使用函数和 while 循环

  • 将之前的 get_formatted_name() 函数和 while 循环结合使用,以更正规的方式问候用户;

    def get_formatted_name(first_name, last_name):
    	"""返回整洁的姓名"""
    	full_name = first_name + ' ' + last_name
    	return full_name.title()
    
    while True:
    	msg = "\nPlease tell me your name: "
    	print(msg)
    	msg = "(enter 'q' at any time to quit)"
    	print(msg)	
    	
    	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)
    	msg = "\nHello, " + formatted_name + "!"
    	print(msg)	
    
    • 此程序使用提示语句,当用户不需要输入时,将使用 break 退出循环语句;
  • 结果演示:
    在这里插入图片描述

3.5 练习

  • 编写一个名为 city_country() 的函数,它接受城市的名称及其所属的国家;
    在这里插入图片描述

  • 编写一个名为 make_album() 的函数,它创建一个描述音乐专辑的字典;

    # 定义函数
    def make_album(singer, album, number = ''):
    	if number:
    		int_number = int(number)
    		message_1 = {'singer' : singer.title(), 'Ablum' : album.title(), 'Number' : int_number}
    	else:
    		message_1 = {'singer' : singer.title(), 'Ablum' : album.title()}
    	return message_1
    
    # 位置实参
    singer_album = make_album('singer_A', 'Album_A')
    print(singer_album)
    singer_album = make_album('singer_B', 'Album_B', '9')
    print(singer_album)
    
    # 关键词实参
    singer_album = make_album(singer = 'singer_C', album = 'Album_C')
    print(singer_album)
    singer_album = make_album(singer = 'singer_D', album = 'Album_D', number = '4')
    print(singer_album)
    
    # 混合实参
    singer_album = make_album('singer_E', album = 'Album_E')
    print(singer_album)
    singer_album = make_album('singer_F', album = 'Album_F', number = '15')
    print(singer_album)
    
    • 结果:

      {'singer': 'Singer_A', 'Ablum': 'Album_A'}
      {'singer': 'Singer_B', 'Ablum': 'Album_B', 'Number': 9}
      {'singer': 'Singer_C', 'Ablum': 'Album_C'}
      {'singer': 'Singer_D', 'Ablum': 'Album_D', 'Number': 4}
      {'singer': 'Singer_E', 'Ablum': 'Album_E'}
      {'singer': 'Singer_F', 'Ablum': 'Album_F', 'Number': 15}
      
  • 结合上述的 make_album() 函数和 while 循环,打印字典;

    # 定义函数。输入 歌手名字 歌手专辑 专辑包含的歌曲数
    def make_album(singer, album, number=''):
    	'''以字典的方式输出'''
    	message_1 = {'singer' : singer.title(), 'Ablum' : album.title()}
    	if number:
    		int_number = int(number)
    		message_1['number'] = int_number
    	return message_1
    
    # while 循环,录入并输出歌手信息
    while True:
    	print("\nPlease enter the singer's information: ")
    	print("(enter 'q' at any time to quit!)")
    	
    	singer_name = input('singer_name: ')
    	if singer_name == 'q':
    		break
    	
    	singer_album = input('singer_album: ')
    	if singer_album == 'q':
    		break
    	
    	'''询问是否输入歌手专辑的歌曲数'''
    	print("Is it convenient to enter the number of songs contained in the album?(yes/no)")
    	number = input()
    	if number == 'yes':
    		album_number = input('number_of_songs: ')
    		if album_number == 'q':
    			break
    		else:
    			album_number = int(album_number)
    		singer_information = make_album(singer='singer_name', album='singer_album', number=album_number)
    		print("\n")
    		print(singer_information)
    	elif number == 'no':
    		singer_information = make_album(singer='singer_name', album='singer_album')
    		print("\n")
    		print(singer_information)
    
    • 结果:
      在这里插入图片描述

4. 传递列表

  • 向函数传递的列表可能是名字、数字或者更复杂的对象,例如字典;

  • 将列表传递给函数后,函数就可以直接访问其内容;

  • 假设有一个用户列表,我们需要问候每位用户;

    def greet_users(names):
    	"""向列表中的每位用火狐都发出简单的问候"""
    	for name in names:
    		msg = "Hello, " + name.title() + "!"
    		print(msg)
    
    usernames = ['hannah', 'ty', 'margot']
    greet_users(usernames)
    
  • 结果显示:
    在这里插入图片描述

4.1 在函数中修改列表

  • 在函数中对这个列表所做的任何修改都是永久性的,这样可以高效的处理大量的数据;

  • 编写一个函数,需要打印的设计存储在一个列表中,打印后移到另一个列表中;

    def print_models(unprinted_designs, completed_models):
    	"""
    		模拟打印每个设计,直到没有未打印的设计为止
    		打印每个设计后,都将其移到列表 completed_models 中
    	"""
    	while unprinted_designs:
    		current_designs = unprinted_designs.pop()
    	
    		# 模拟根据设计制作 3D 打印模型的过程
    		msg = "Printing model: " + current_designs
    		print(msg)
    		completed_models.append(current_designs)
    
    def show_completed_models(completed_models):
    	"""示打印好的所有模型"""
    	msg = "\nThe following models have been printed: "
    	print(msg)
    	for completed_model in completed_models:
    		print(completed_model)	
    		
    # 创建一个列表,其中包含一些要打印的设计
    unprinted_designs = ['iphone_case', 'robot_pendant', 'dodecahedron']
    completed_models = []
    
    print_models(unprinted_designs, completed_models)
    show_completed_models(completed_models)
    msg = "\nafter modify: "
    print(msg)
    print(unprinted_designs)
    
    • 上述中,将一个函数分开写,每个函数只负责一项具体的工作,这样使得程序更容易维护和扩展;
  • 结果:
    在这里插入图片描述

4.2 禁止函数修改列表

  • 当不允许函数修改列表时,可以向函数传递列表的副本而不是原件;

  • 使用切片法[:] 创建列表副本;

  • 除非有充分的理由需要传递副本,不然应该将原始列表传递给函数;

  • 因为让函数使用现成的列表可避免花时间和内存创建副本,从而提高效率;
    在这里插入图片描述

4.3 练习

  • 创建一个包含魔术师名字的列表,并将其传递给一个名为 show_magicians() 的函数,这个函数打印列表中每个魔术师的名字;
    在这里插入图片描述

  • 在上述例子中,编写一个名为 make_great() 的函数,对魔术师列表进行修改,在每个魔术师的名字后边加入字样 the Great ,调用函数 show_magicians() 确认列表的确变了。
    在这里插入图片描述

  • 将上述例子中的魔术师列表不进行改变,再次编写函数:
    在这里插入图片描述

5. 传递任意数量的实参

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

5.1 使用任意数量的位置实参

  • 当形参为 *names ,表示创建一个名为 names 的空元组,并将所有的值都封装到这个元组;

  • 编写一个名为 make_pizza() 的函数,它需要接受很多配料,所以形参设为空元组;

    def make_pizza(*toppings):
    	"""打印顾客点的所有配料"""
    	print(toppings)
    
    make_pizza('pepperoni')
    make_pizza('mushrooms','green peppers', 'extra cheese')
    
  • 结果:
    在这里插入图片描述

  • 不管收到的实参是多少个,这种语法都管用;

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

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

  • Python 先匹配位置实参和关键字实参,最后将余下的实参都收集到一个形参中;

  • 在前面的函数中定义一个表示比萨尺寸的实参,必须将该形参放在形参 *toppings 的前面;

    def make_pizza(size, *toppings):
    	"""打印顾客点的所有配料"""
    	msg = "\nMaking a " + str(size) + "-inch pizza with the following toppings:"
    	print(msg)
    	for topping in toppings:
    		msg = "- " + topping
    		print(msg)
    
    make_pizza(12, 'pepperoni')
    make_pizza(16, 'mushrooms','green peppers', 'extra cheese')
    
  • 结果:
    在这里插入图片描述

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

  • 当形参为 **names ,表示创建一个名为 names 的空字典,并将所有的名称-值都封装到这个字典中;

  • 编写一个名为 build_profile 的函数,接受名和姓,同时还接受任意数量的关键字实参:

    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', 'einstein', location='princetion', field='physics')
    print(user_profile)
    
  • 结果为:
    在这里插入图片描述

5.4 练习

  • 编写一个函数,它接受顾客要在三明治中添加的一系列食材。这个函数只有一个形参(它收集函数调用中提供的所有食材),并打印一条消息,对顾客点的三明治进行概述;

    # 定义函数,传入的实参为顾客为三明治添加的材料,以元组方式传入
    def add_material(*material):
    	'''判断传入的个数,输出不同的原材料'''
    	num = len(material)
    	'''传入 0 个材料,此处不能写'' ,只要有引号,就代表有东西,判定长度为1 '''
    	if num == 0:
    		msg = "\nThe customer did not add any ingredients to the sandwich."
    		print(msg)
    
    	elif num == 1:
    		msg = "\nThe customer added a material to the sandwich: "
    		print(msg)		
    		for mater in material:
    			msg = "- " + mater
    			print(msg) 
    
    	elif num > 1:
    		msg = "\nThe customer added the following ingredients to the sandwich: "
    		print(msg)		
    		for mater in material:
    			msg = "- " + mater
    			print(msg) 
    
    	else:
    		print("System error!")
    		
    # 定义传入参数元祖,并调用函数
    material = add_material()
    material = add_material('f')
    material = add_material('a', 'b', 'c')
    
  • 结果:
    在这里插入图片描述

6. 将函数存储在模块中

  • 函数的优点之一就是可以将代码块与主程序分离;
  • 将函数存储在被称为模块的独立文件中,再将模块导入主程序中;
  • 模块是扩展名为 .py 的文件;
  • import 语句允许在当前运行的程序文件中使用模块中的代码;
  • 将函数存储在独立的文件中,可隐藏程序代码的细节,将重点放在程序的高层逻辑上;

6.1 导入整个模块

  • 创建一个包含函数 make_pizza() 的模块;

    def make_pizza(size, *toppings):
    	"""打印顾客点的所有配料"""
    	msg = "\nMaking a " + str(size) + "-inch pizza with the following toppings:"
    	print(msg)
    	for topping in toppings:
    		msg = "- " + topping
    		print(msg)
    
  • 在这个函数所在的目录创建另一个名为 make_pizza.py 的文件,使用这个文件导入刚才的模块;

    import pizza
    
    pizza.make_pizza(16, 'pepperoni')
    pizza.make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese')
    
  • 结果为:
    在这里插入图片描述

6.2 导入特定的函数

  • 还可以导入模块中的特定函数,导入语法为:

    from module_name import function_name
    
  • 通过使用逗号分隔函数名,可根据需要从模块中导入任意数量的函数:

    from module_name import function_0, function_1
    
  • 使用这中导入函数时,调用函数时无需使用句点:
    在这里插入图片描述

6.3 使用 as 给函数指定别名

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

  • 别名,函数的另一个名称,类似于外号;

  • 指定别名的通用语法为:

    from module_name import function_name as fn
    
  • 下面给函数 make_pizza() 指定了别名 mp()
    在这里插入图片描述

6.4 使用 as 给模块指定别名

  • 还可以给模块指定别名;

  • 给模块指定别名的通用语法为:

    import module_name as mn
    
  • 下面给模块 pizza 指定别名为 p
    在这里插入图片描述

6.5 导入模块中的所有函数

  • 使用 * 运算符可以导入模块中的所有函数;

  • 由于导入了每个函数,所以可以通过名称来调用每个元素,而无需使用句点表示法;

  • 使用并非自己编写的大型模块时,最好不要采用这种导入方法;

  • 如果模块中有函数与你的项目中使用的名称相同,可能会导致结果出乎意料;

  • 导入所有函数的语法为:

    from module_name import *
    
  • 导入模块 pizza.py 中的所有函数:
    在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值