+关注
已关注

分类  

暂无分类

标签  

暂无标签

日期归档  

2019-07(2)

2019-08(89)

2019-09(94)

2019-10(15)

2019-11(5)

学习如何编写函数

发布于2020-11-09 19:37     阅读(598)     评论(0)     点赞(11)     收藏(3)


0

1

2

3

4

5

学习编写函数

                                                                                             作者:雷蕾

函数是带名字的代码块,用于完成具体的工作。要执行函数定义的特定任务,可调用该函数。
(一)定义函数
我们先来看一个最简单的函数结构:

def greet_user(): 
    '''这是一个简单的问候语'''
    print('Hello')
greet_user()

我们试着来解读这段代码:第一行代码行使用关键字def来告诉python,我要定义一个函数,向python指定函数名为greet_user,还可以在圆括号内指出函数为完成任务需要什么样的信息,因为在这次代码中,我们不需要任何信息就能完成工作,因此圆括号内是空的,最后以冒号结束。
紧跟在def greet_user():后面的所有缩进构成了函数体, ‘’‘这是一个简单的问候语’’'称为文档字符串的注释,描述了该函数是做什么。文档字符串用三引号括起。
第三行代码: print(‘Hello’)是函数体内唯一一行代码,因此greet_user()只做一项工作:打印Hello。
第四行代码是调用函数,要调用函数,可依次指出函数名以及用圆括号括起来的必要信息,在这次代码中,调用函数只要输入greet_user()就可以。
运行结果:

Hello

(二)向函数传递信息
我们先来看一段简单的代码:

def greet_user(username): 
    '''这是一个简单的问候语''' 
    print(f'Hello,{username.title()}')
greet_user('sarah')

和上个示例不同,这次我们不仅让greet_user()能完成打印Hello的任务,还能将用户的名字打印。
我们在函数定义def greet_user()的括号内添加了username,通过添加,可让函数接受我们给username指定的任何值。
第一行代码就是要求你调用它时给username指定一个值。
第四行代码调用函数greet_user()时,将’sarah’传递给了它。
运行结果:

Hello,Sarah

还有一点就是我们都很容易形参、实参不分,那该如何区分形参和实参呢?
在上述代码中,def greet_user(username):圆括号内的username就是形参,即函数完成任务所需要的信息,greet_user(‘sarah’)圆括号内的’sarah’就是实参,即调用函数时传递给它的信息,实参’sarah’被赋给了形参username。
(三)传递实参
我们在定义函数时可能包括多个形参,相应地,我们也应该将多个实参赋给形参。
向函数传递实参的方法主要有这几种方式:
(1)位置实参
(2)关键字实参
(3)使用列表和字典
我们来学习位置实参,先看两个示例代码以及运行结果
示例1:

def describe_pet(animal_type,animal_name):
    '''这是显示宠物的信息'''
    print(f"\ni have a {animal_type}")
    print(f"{animal_type}'s name is {animal_name}")
describe_pet('hamster','harry')

运行结果:

i have a hamster
hamster's name is harry

示例2:

def describe_pet(animal_type,animal_name):
    '''这是显示宠物的信息'''
    print(f"\ni have a{animal_type}")
    print(f"{animal_type}'s name is{animal_name}")
describe_pet('harry','hamster')

运行结果:

i have a hamster
hamster's name is hamster

我们仔细观察两个示例的运行结果发现相反,调用函数时,python必须将函数调用中的每个实参都关联到函数定义中的每一个形参,但在函数调用时将两个实参赋给形参的顺序不一样导致最后的结果也不一样,由此我们可知:
位置实参要求实参的顺序与形参的顺序相同,不然会导致逻辑错误。
我们可以根据需要调用函数任意次:

#传递实参
#关键字实参
def describe_pet(animal_type,animal_name):
    '''这是显示宠物的信息'''
    print(f"\ni have a {animal_type}")
    print(f"{animal_type}'s name is {animal_name}")
describe_pet('hamster','harry')
describe_pet('dog','willie')

运行结果:

i have a hamster
hamster's name is harry

i have a dog
dog's name is willie

关键字实参是传递给函数的名称值对,直接在实参中将名称和值关联起来。
先看一段代码:

def describe_pet(animal_type,animal_name):
    '''这是显示宠物的信息'''
    print(f"\ni have a {animal_type}")
    print(f"{animal_type}'s name is  {animal_name}")
describe_pet(animal_type='hamster',animal_name='harry')
describe_pet(animal_name='willie',animal_type='dog')

运行结果:

i have a  hamster
hamster's name is harry

i have a  dog
dog's name is willie

关键字实参让我们无需考虑函数调用的实参顺序,还能够清楚地指出了函数调用中各个值地用途。
默认值:编写函数时,可给每个形参指定默认值。
在调用函数时,我们给形参指定了实参,python会使用指定地实参值,否则会使用默认。

def describe_pet(animal_name,animal_type='dog'):
    '''这是显示宠物的信息'''
    print(f"\ni have a  {animal_type}")
    print(f"{animal_type}'s name is  {animal_name}")
describe_pet(animal_name='harry')
describe_pet('willie')

运行结果:

i have a dog
dog's name is harry

i have a dog
dog's name is willie

但值得注意的一点是:使用默认值时,必须先在形参列表中列出没有默认值的形参,再列出有默认值的实参
在进行函数调用时,我们要避免实参错误:形参与实参不匹配,这样的情况可能我们提供的实参多于或少于了形参数。

def describe_pet(animal_type,animal_name):
    '''这是显示宠物的信息'''
    print(f"\ni have a{animal_type}")
    print(f"{animal_type}'s name is{animal_name}")
describe_pet()

运行结果:

   Traceback (most recent call last):
  File "C:\Users\12184\Desktop\pet.py", line 7, in <module>
    describe_pet()
TypeError: describe_pet() missing 2 required positional arguments: 'animal_type' and 'animal_name'

运行报错: Traceback指出了问题所在,它让我们回去找函数调用中的错误,也指出了该函数调用过程中少了两个实参并指出了两个相应形参的名称。
(四)返回值
函数返回的值称为返回值,在函数中,可使用return语句将值返回到调用函数的代码行。
先看一个函数,它接受名和姓,并返回整洁的姓名:

def get_formatted_name(first_name,last_name):
    '''返回整洁的姓名'''
    full_name=f"{first_name} {last_name}"
    return full_name.title() #将值返回到调用函数的代码行
musician=get_formatted_name('jimin','hendrix')
print(musician)

运行结果:

Jimin Hendrix

试着解读这段代码:
第一行函数get_formatted_name()的定义通过形参接受名和姓;
第三行是将名和姓合一并赋给变量full_name;
第四行将full_name的值首字母大写并返回到函数调用(第五行);
第五行就是函数调用。
我们还可以让实参变成可选的,前面有提到,当实参赋予形参值时,我们使用所赋予的,其他时候可使用默认值。

#让实参变成可选的
#可使用默认值让实参变成可选的
def get_formatted_name(first_name,last_name,middle_name=''):
    '''返回整洁的姓名'''
    if middle_name:
        full_name=f"{first_name}  {middle_name} {last_name}"
        return full_name.title() #将值返回到调用函数的代码行
    else:
      full_name=f"{first_name}  {last_name}"
      return full_name.title() #将值返回到调用函数的代码行
musician=get_formatted_name('jimin','lee','hendrix')
print(musician)
musician=get_formatted_name('jimin','hendrix')
print(musician)

运行结果:

Jimin  Hendrix Lee
Jimin  Hendrix

值得注意的是:形参middle_name的默认值设置为空字符串,必须将其移到形参列表的末尾
返回字典:
函数可返回任何类型的值,包括列表和字典等较复杂的数据结构。

def bulid_person(first_name,last_name):
    '''返回一段字典,其中包含一个人的信息'''
    person={'first':first_name,'last':last_name}
    return person
musician=bulid_peson('jimin','hendrix')
print(musician)

运行结果:

{'first': 'jimin', 'last': 'hendrix'}

结合使用函数和while循环:

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")
    f_name=input("first:")
    l_name=input("last:")
    formatted_name=get_formatted_name(f_name,l_name)
    print(f"hello,{formatted_name}")

运行结果:

please tell me your name
first:lee
last:willie
hello,Lee Willie

please tell me your name
first:

上述代码有一个缺陷就是会无限循环下去,我们是否能添加一段让循环停止的命令行呢?

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")
    f_name=input("first:")
    if f_name=='q': #输入q循环停止
        break
    l_name=input("last:")#输入q循环停止
    if l_name=='q':
        break
    formatted_name=get_formatted_name(f_name,l_name)
    print(f"hello,{formatted_name}")

运行结果:

please tell me your name
first:lee
last:willie
hello,Lee Willie

please tell me your name
first:q
>>> 

我们通过添加下面两行简单的代码,当输入’q’是循环停止。

  if f_name=='q': #输入q循环停止
        break

(五)传递列表
假设我们用一个用户列表,我们现在我们需要向用户列表中的每一个用户问候:

def greet_users(names):
    '''向列表中的每位用户发出简单的问候'''
    for name in names:
        print(f"hello,{name.title()}")
usernames=['hanah','ty','margot']
greet_users(usernames)

运行结果:

hello,Hanah
hello,Ty
hello,Margot

我们将列表传递给函数后,函数可对其进行修改,我们先看一段不需要函数的情况下如何模拟打印过程:

#首先创建一个列表,其中包含一些要打印的设计
unprinted_designs=['phone case','robot pendant','dodecahedron']
completed_models=[]
#模拟打印每个设计,直到没有未打印的设计为止
#打印每个设计后,都将其移到列表completed_models中
while unprinted_designs:
    current_design=unprinted_designs.pop()
    completed_models.append(current_design)
    print(f"printing models: {current_design}")
#显示打印好的所有模型
for  completed_model in  completed_models:
    print(f"\nthe follwing models have been printed:{ completed_model}")

运行结果:

printing models: dodecahedron
printing models: robot pendant
printing models: phone case

the follwing models have been printed:dodecahedron

the follwing models have been printed:robot pendant

the follwing models have been printed:phone case

下面看一段在定义函数的情况下模拟打印过程:

def print_models(unprinted_models,completed_models):
    '''
模拟打印每个设计,直到没有未打印的设计为止
打印每个设计后,都将移动到列表completed_models中
'''
    while unprinted_models:
        current_design=unprinted_models.pop()
        completed_models.append(current_design)
        print(f"printing models: {current_design}")
def show_completed_models(completed_models):
    '''现实打印好的所有模型'''
    for completed_model in completed_models:
        print(f"\nthe follwing models have been printed: {completed_model}")
unprinted_models=['phone case','robot pendant','dodecahedron']
completed_models=[]
print_models(unprinted_models,completed_models)
show_completed_models(completed_models)

运行结果:

printing models: dodecahedron
printing models: robot pendant
printing models: phone case

the follwing models have been printed: dodecahedron

the follwing models have been printed: robot pendant

the follwing models have been printed: phone case

上述两段代码的运行结果一模一样,但使用函数的版本,以后我们需要打印其他设计只需再次调用print_models()就可以。
在上述使用函数的示例中,每个函数只负责一项具体的工作,print_models打印每一个设计,show_completed_models显示打印好的所有模型,这也使得程序看起来更加简洁明了。

(六)传递任意数量的实参
python允许函数从调用语句中收集任意数量的实参,当不知道函数需要接受多少个实参时,我们可对形参名使用*(星号)

def make_pizza(*toppings):
    '''打印顾客点的所有配料'''
    print(toppings)
make_pizza('pepperoni')
make_pizza('mushroom','green peppers','extre chees')

运行结果:

('pepperoni',)
('mushroom', 'green peppers', 'extre chees')

形参名*toppings中的星号可以让python创建一个名为toppings的空元组,并将所有收到的所有值都封装在这个元组中。
我们可将其变为一个循环,遍历toppings所存储的值:

def make_pizza(*toppings):
    '''打印顾客点的所有配料'''
    for topping in toppings:
        print(topping)
make_pizza('pepperoni')
make_pizza('mushroom','green peppers','extre chees')

运行结果:

pepperoni
mushroom
green peppers
extre chees

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

def make_pizza(size,*toppings):
    '''打印顾客点的所有配料'''
    print(f"\nmake a {size} pizza with the following toppings:")
    for topping in toppings:
        print(topping)
make_pizza(12,'pepperoni')
make_pizza(16,'mushroom','green peppers','extre chees')

运行结果:

make a 12 pizza with the following toppings:
pepperoni

make a 16 pizza with the following toppings:
mushroom
green peppers
extre chees

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

def bulid_profile(first,last,**user_info):
    '''创建一个字典,其中包含我们所知道的有关用户的一切'''
    user_info['first']=first
    user_info['last']=last
    return user_info
user_profile=bulid_profile('albert','einstein',
                           location='princeton',
                           field='phycics'
                           )
print(user_profile)

运行结果:

{'location': 'princeton', 'field': 'phycics', 'first': 'albert', 'last': 'einstein'}

形参**user_info中的两个星号让python创建一个名为user_info的空字典,并将收到的所有名字存储在这个字典中。

0

1

2

3

4

5

6

7

8



所属网站分类: 技术文章 > 博客

作者:天青色等烟雨

链接: https://www.pythonheidong.com/blog/article/612130/970cf9a8927e2d340862/

来源: python黑洞网

任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任

11 0
收藏该文
已收藏

评论内容:(最多支持255个字符)