Python中的函数

        函数就是带名字的代码块,用于完成特定的任务。要执行函数定义的特定任务,只需调用该函数。

1、函数的定义

        定义函数可以使用def关键字,def后面是自定义的函数名,函数名后面的括号中用于传入执行该函数所需的信息(函数参数),即使不需要任何参数也不能省略括号,最后以冒号结尾。 

        紧跟在def语句之后的缩进代码块为函数体,函数体中可以用三引号括起的为文档字符串(docstring)的注释,用于描述该函数是做什么的,python使用它们生成程序中函数的文档。

#定义函数
def my_print():
    """打印欢迎"""
    print('Hello!')

#调用函数
my_print()

#结果:
Hello!

代码中的函数名为my_print,且无需任何参数,定义了一个专门的打印欢迎语句的函数。

1.1 向函数传递参数

         改进一下上面的代码,向函数传入参数:

#定义函数
def my_print(name):
    print('Hello!' + name.title())

#调用函数
my_print('jack')

#结果:
Hello!Jack
#定义函数
def my_print(name):
    print('Hello!' + name.title())

#调用函数
my_print('rose')

#结果:
Hello!Rose

1.2 实参和形参

         定义函数时,括号内的参数称为形参,即函数执行中所需的信息(如代码中的name)。而实参则是调用函数时传递给函数的信息,即调用函数时括号中的参数(如代码中的'jack')。

#定义函数
def my_print(name):
    print('Hello!' + name.title())

#调用函数
my_print('jack')

#结果:
Hello!Jack

  2、传递参数

        定义函数中可能有多个形参,调用函数时也可能有多个实参。向函数传递参数的方式有很多种,如位置参数,关键字参数,以及列表和字典。

2.1 位置参数

        位置参数,要求实参的顺序与形参的顺序相同,调用函数时,将函数调用中的每一个实参都关联到函数定义中的每一个形参。

#定义函数
def my_print(name,age):
    print('Hello!' + name.title() + '.')
    print('Your age is ' + str(age))
#调用函数
my_print('rose',21)

#结果:
Hello!Rose.
Your age is 21

 函数定义了两个参数(name和age),调用函数时,也需传入两个实参。更多的参数也是类似,不过一定要注意形参的顺序和实参的顺序要一致。    

2.2 关键字参数

        关键字参数是以名称-值对传递给函数的,直接在调用函数时的实参中将参数名称与值关联起来了,因此传递参数时不会混淆。关键字参数无需考虑函数调用中的实参顺序,指明了函数调用中各个值的用途。

#定义函数
def my_print(name,age):
    print('Hello!' + name.title() + '.')
    print('Your age is ' + str(age))
#调用函数
my_print(age=21,name='jack')

#结果:
Hello!Jack.
Your age is 21

关键字实参的顺序无关紧要,Python知道各个实参应该传递给哪个形参。

2.3 默认值参数

        定义函数时,可以给每个形参指定默认值。如果在调用函数时,给形参传递了具体的实参,则使用具体的实参;如果函数调用时没有指定特定的实参传递给形参,则使用形参的默认值。

#定义函数
def my_print(name,age=21):
    print('Hello!' + name.title() + '.')
    print('Your age is ' + str(age))
#调用函数
my_print('jack',20)
my_print(('loss'))

#结果:
Hello!Jack.
Your age is 20
Hello!Loss.
Your age is 21

代码中,第一次调用函数时给定了形参age具体的实参20,因此使用该实参传递给形参age;第二次调用函数时,并没有给定形参age的具体实参,因此直接使用形参的默认值21。

        在这个函数的定义中,使用了默认值的形参age放在没有使用默认值的形参name的后面。

        因为Python将这些没有默认值的形参视为位置参数,使用默认值时,在形参列表中必须先列出没有默认值的形参,再列出有默认值的实参,让Python能够正确地解读其他位置实参。否则如图报错:

#定义函数
def my_print(name='wumingshi',age):
    print('Hello!' + name.title() + '.')
    print('Your age is ' + str(age))
#调用函数
my_print('jack',20)
my_print(21)

#结果:
  File "E:\mypro.py", line 2
    def my_print(name='wumingshi',age):
                                     ^
SyntaxError: non-default argument follows default argument

3、返回值

        函数可以处理数据,并返回一个或一组值,被称为返回值。在函数中,可以使用return语句将返回值返回到调用函数的代码行,继续运行。返回值可以将程序中大部分繁重工作转移至函数中完成,简化主程序。

3.1 返回简单值

#定义函数
def my_sum(a,b):
    """求两数之和"""
    return a + b
#调用函数
s = my_sum(3,9)
print(s)

#结果:
12

该定义函数返回输入的两数之和。

3.2 返回不同值

        在函数调用中,可以根据不同的输入参数情况,返回不同的值。 

#定义函数
def my_fun(firstname,lastname,middlename=''):
    """返回全名"""
    if middlename:
        fullname = firstname + ' ' + middlename + ' ' + lastname
    else:
        fullname = firstname + ' ' + lastname
    return fullname.title()
#调用函数
s = my_fun('jim','hex','lee')
print(s)
s = my_fun('jim','hex')
print(s)

#结果:
Jim Lee Hex
Jim Hex

3.3 返回字典

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

#定义函数
def my_fun(name,age):
    """返回字典"""
    person = {'name': name,'age': age}
    return person
#调用函数
s = my_fun('Jack',22)
print(s)

#结果:
{'name': 'Jack', 'age': 22}

3.4 结合while循环

#定义函数
def my_print(name):
    return 'Hello!' + name.title()

#调用函数
my_print('jack')
while True:
    print('Please input your name:(enter "q" to quit) ')
    yname = input('Your name: ')
    if yname == 'q':
        break
    fname = my_print(yname)
    print(fname)

#结果:
Please input your name:(enter "q" to quit) 
Your name: liang
Hello!Liang
Please input your name:(enter "q" to quit) 
Your name: q

4、传递列表

        有时候,向函数传递列表很有用,列表元素可能是字符串、数字或更复杂的对象(如字典)。将列表传递给函数后,函数就能直接访问其内容。

#定义函数
def greet(names):
    """问候每个用户"""
    for name in names:
        print('Hello, ' + name)

usernames = ['Jack', 'Bob', 'Mike']
greet(usernames)

#结果:
Hello, Jack
Hello, Bob
Hello, Mike

4.1 在函数中修改列表

        将列表传递给函数之后,函数就可以对其进行修改,所做的修改是永久性的,能够高效地处理大量的数据。

#定义函数
def trans(uncom, com):
    """将一个列表的元素转移到另一个列表"""
    while uncom:
        temp = uncom.pop()
        com.append(temp)

def show(com):
    for each in com:
        print(each)

uncom = [4,3,6,4,2,1]
com = []

trans(uncom, com)
show(com)

#结果:
1
2
4
6
3
4

定义的第一个函数包括两个形参,负责将一个列表的元素转移到另一个列表,第二个函数只有一个参数,负责将新列表中的每个元素打印。使用函数,使程序更容易扩展和维护,每个函数都只负责一项具体的工作。

4.2 禁止函数修改列表

        有时候,需要禁止函数修改列表,即需要保留原来的列表。这种情况下,可以向函数传递列表的副本而不是列表本身,这样函数只修改了副本,而不影响原列表。

        要传递副本,可以使用列表切片:

function_name(list_name[:])

在上述代码中,如果不想改变原列表,可以这样调用函数:

trans(uncom[:], com)

5、传递任意数量的实参

        有时候,并不知道函数需要接收多少个实参,Python允许函数从调用语句中收集任意数量的实参。使用收集参数,可以将收集到的所有参数封装到一个元组中。

#定义函数
def make_juice(*ingredients):
    """打印原料"""
    print(ingredients)
make_juice('apple')
make_juice('banana','apple','orange')

#结果:
('apple',)
('banana', 'apple', 'orange')

 还可以对收集的参数遍历:

#定义函数
def make_juice(*ingredients):
    """打印原料"""
    print('\nThe ingredients: ')
    for ingredient in ingredients:
        print('-' + ingredient)
make_juice('apple')
make_juice('banana','apple','orange')

#结果:

The ingredients: 
-apple

The ingredients: 
-banana
-apple
-orange

5.1 集合位置参数和收集参数

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

#定义函数
def make_juice(size, *ingredients):
    """打印原料"""
    print('\nThe ingredients of the ' + size + ' juice: ')
    for ingredient in ingredients:
        print('-' + ingredient)
make_juice('middle','apple')
make_juice('large','banana','apple','orange')

#结果:

The ingredients of the middle juice: 
-apple

The ingredients of the large juice: 
-banana
-apple
-orange

上述代码中,在函数定义中,将收集参数(*ingredient)放在参数列表的最后,调用函数时,将第一个实参传递给形参size,将余下的实参全部打包给形参*ingredient,并存储在元组ingredient中。

5.2 任意数量的关键字参数

        有时,需要接收任意数量的实参,但预先不知道传递给函数的会是什么样的信息。这时,可以将函数定义为可以接收任意数量的键-值对——调用语句提供多少函数就接收多少。

#定义函数
def users(fname,lname,**other):
    """创建一个字典,其中包含用户的其他信息"""
    users_information= {}
    users_information['firstname'] = fname
    users_information['lastname'] = lname
    for key, value in other.items():
        users_information[key] = value
    return users_information
user1 = users('zhang','liang',age = 22, grade = 95)
print(user1)

#结果:
{'firstname': 'zhang', 'lastname': 'liang', 'age': 22, 'grade': 95}

上述定义的函数接收两个参数(fname和lname),同时还接收任意数量的关键字参数。形参**other的两个星号让Python创建一个名为other的空字典,并将接收的所有名称-值对都封装到这个字典中,在函数中,可以像访问字典一样访问other的名称-值对。

调用这个函数时,可以传递任意多个关键字参数:

#定义函数
def users(fname,lname,**other):
    """创建一个字典,其中包含用户的其他信息"""
    users_information= {}
    users_information['firstname'] = fname
    users_information['lastname'] = lname
    for key, value in other.items():
        users_information[key] = value
    return users_information
user1 = users('zhang','liang',age = 22, grade = 95, subject = 'math')
print(user1)

#结果:
{'firstname': 'zhang', 'lastname': 'liang', 'age': 22, 'grade': 95, 'subject': 'math'}

        编写函数时,可以各种方式混合使用位置参数、关键字参数和收集参数。要正确使用这些参数类型并能在合适的情形下高效地使用,需要一定的练习。

6、将函数存储在模块中

        函数的优点是,使用函数可以将代码块和主程序分离。还可以更进一步,将函数存储在独立的文件中,这个文件被称为模块。使用import语句可以将模块导入到主程序中,允许当前运行的程序中使用模块中的代码。

        将函数存储在独立的文件中后,可以与其他程序员共享这些文件而不是整个程序,知道如何导入模块还能使用其他程序员编写的函数库。

6.1 导入整个模块

        要导入模块,得先创建模块。模块是扩展名为.py的文件,包含要导入到程序中的代码。先创建一个名为juice.py的模块,包含函数make_juice():

juice.py

#定义函数
def make_juice(size, *ingredients):
    """打印原料"""
    print('\nThe ingredients of the ' + size + ' juice: ')
    for ingredient in ingredients:
        print('-' + ingredient)

        接着,在另一个.py文件中导入这个模块,再使用这个函数make_juice():

import juice
juice.make_juice('middle','apple')
juice.make_juice('large','banana','apple','orange')

#结果:

The ingredients of the middle juice: 
-apple

The ingredients of the large juice: 
-banana
-apple
-orange

        python在执行import juice这句代码时,将打开文件juice.py,并将其中的所有函数都复制到这个程序中,然后可以在这个文件中使用juice.py中的所有函数。

        要调用被导入模块的函数,可以指定模块名称和函数名,并用句号.分隔它们,如上述代码。

6.2 导入特定的函数

        还可以直接导入模块中特定的函数,而不是导入整个模块:

from module_name import function_name

        通过逗号分隔函数名,可以导入任意数量的函数:

from module_name import function_0, function_1, function_2

        前面的示例可以改为:

from juice import make_juice
make_juice('middle','apple')
make_juice('large','banana','apple','orange')

        这时,调用函数时,因为我们在import语句中显示地导入了函数make_juice,因此调用时无需指定模块名。

6.3 使用as给函数指定别名

        如果要导入的函数名与当前程序中的现有名称有冲突,或者函数的名称太长,可以重新指定函数的别名,类似于外号,即该模块中的函数在当前程序中的名字。

from juice import make_juice as mj
mj('middle','apple')
mj('large','banana','apple','orange')

        上面的代码中,import语句将make_juice()函数重命名为mj();在这个程序中,需要调用make_juice()函数时,都可以简写为mj(),python将运行juice模块中的make_juice()函数,避免与这个程序中可能的同名函数混淆。

from module_name import function_name as fn

6.4 使用as给模块指定别名

        还可以给模块指定别名,通过给模块指定更简洁的别名,可以方便地调用模块中的函数。

import juice as je
je.make_juice('middle','apple')
je.make_juice('large','banana','apple','orange')

通用语法为:

import module_name as mn

6.5 导入模块中的所有函数

        使用星号(*)可以导入模块中的所有函数:

from mofule_name import *
from juice import *
make_juice('middle','apple')
make_juice('large','banana','apple','orange')

        import语句的*可以将模块中的所有函数都复制到当前程序中,由于导入了所有函数,因此调用时不用指定模块名,可以直接使用函数名。

        然而,使用他人编写的大型模块时,不建议使用这种导入方法:模块中可能有函数名称与你的项目中使用的名称相同,可能导致错误。(python遇到多个名称相同的函数或变量,进而覆盖函数)

        最佳的导入方法为,只导入你需要的模块,或者导入整个模块并使用模块名加函数名的调用方法。这种方法让代码更清晰,易于阅读和理解。

7、函数编写理念

  • 编写函数时,给函数名指定描述性名称,且只在其中使用小写字母和下划线,描述性名称能帮助自己和他人了解函数的大概功能。给模块命名时也是如此。
  • 每个函数都应包含说明其功能的注释,注释紧跟在定义后面,并采用文档字符串的格式。
  • 给形参指定默认值时,等号两边不要空格,实参亦是如此:
    deg function_name(parameter_0,parametrt_1='default valur')
  •  定义函数时,代码行的长度不要超过79字符
    def function_name(
            parameter_0, parameter_1, parameter_2,
            parameter_3, parameter_4, paramerer_5):
        function body...
  • 如果模块包含多个函数,可以使用两个空行将两个相邻的函数分开。
  • 所有import语句都应放在文件的开头,除非文件开头使用了注释来描述整个程序。 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小白的高手之路

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值