Python编程:函数

1.定义函数

        下面是一个打印问候语的简单函数,名为greet_user():

def greet_user():
    """显示简单的问候语"""
    print("Hello!")

greet_user()

         其中,def关键字告诉Python你要定义一个函数,然后提供了名为greet_user的函数名,在其后的圆括号内指出函数要完成这项功能,需要什么信息(参数)。冒号后缩进的代码段被称为函数体,第二行的文本称为“文档字符串”的注释,描述函数是做什么的,用三引号括起。第三行处的代码为函数要执行的代码。

1.1向函数传递信息

        可以通过在函数名圆括号里添加信息,来向函数传递信息。

def greet_user(username):
    """显示简单的问候语"""
    print(f"Hello,{username.title()}")

greet_user('john')

1.2实参和形参

        通常情况下,我们把在函数定义中在函数名后括号里添加的变量称为形参,把实际调用时在函数名后括号里添加的变量叫实参。

2.传递实参

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

2.1位置参数

        调用函数时,Python必须将函数调用时的每个实参都关联到函数定义中的每个形参。为此,最简单的方式是基于实参顺序。这种关联方式叫做位置实参。

def describe_pet(animal_type,pet_name):
    """显示宠物信息"""
    print(f"\nI have a {animal_type}.")
    print(f"My {animal_type}'s name is {pet_name.title()}.")

describe_pet('hamster','harry')
describe_pet('dog','willing')

        注意:(1)实参的顺序与形参顺序相同,这很重要。(2)可以根据需要调用任意次函数。

2.2关键字实参

        关键字实参是传递给函数名称值对,因为直接在实参中将名称和值关联起来,所以向函数传递实参时不会混淆。关键字实参让你无需考虑函数调用中实参的顺序,还清楚的指出了各个值的用途。

def describe_pet(animal_type,pet_name):
    """显示宠物信息"""
    print(f"\nI have a {animal_type}.")
    print(f"My {animal_type}'s name is {pet_name.title()}.")

describe_pet(animal_type = 'hamster',pet_name = 'harry')
describe_pet(pet_name = 'harry',animal_type = 'hamster')

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

2.3默认值

        编写函数时,可以给每个形参指定默认值。这样在调用函数时指定了实参,函数会使用指定

的实参,否则,使用形参的默认值。因此,给形参指定默认值后,可在函数调用时省略相应的实参。

def describe_pet(pet_name,animal_type='dog'):
    """显示宠物信息"""
    print(f"\nI have a {animal_type}.")
    print(f"My {animal_type}'s name is {pet_name.title()}.")
describe_pet('willing')
describe_pet(pet_name='willing')

        注意,这里修改了函数的定义,因为给animal_type指定了'dog'的默认值,所以无需通过实参来指定动物的类型,所以在函数调用时可以只包含一个实参,即动物的名字。但是,Python依然将这个实参看作是位置实参,所以要改变函数定义时形参的位置。

        综上,在使用默认值时,必须先列出未定义默认值的实参,再列出已定义默认值的实参。

2.4等效的函数调用

        鉴于可以混合使用位置实参、默认值、关键字实参,通常有多种等效的函数调用。

def describe_pet(pet_name,animal_type='dog'):
    """显示宠物信息"""
    print(f"\nI have a {animal_type}.")
    print(f"My {animal_type}'s name is {pet_name.title()}.")

describe_pet('willing')
describe_pet(pet_name='willing')
describe_pet('willing','dog')
describe_pet('harry','hamster')
describe_pet(pet_name='harry',animal_type='hamster')

        使用那种调用方式并不重要,主要是能达到你的预期,方便你的理解。

2.5避免实参错误

       在调用函数时,会出现实参不匹配错误,这是要注意函数定义中的形参顺序要与函数定义中的实参顺序一致。

3.返回值

        函数并非总是直接显示输出的,还可以处理一些数据,并返回一个或一组值。函数返回的值称为返回值。在函数中可以使用return语句将值返回到调用函数的代码行。

3.1返回简单值

        返回函数调用值的时候,注意要设置一个变量,以便将函数返回值赋给它。

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)

3.2让实参变成可选的

        有时候,要将实参变成可选的,这样使用函数的人只要在必要的时候提供额外的信息即可。可以使用默认值来让实参变成可选的。

        例如,假设要扩展函数get_formatted_name(),使其能处理中间名。可以作如下修改:

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

musician = get_formatted_name('john','lee','hooker')
print(musician)

        但是,并非所有的人都有中间名,所以要让中间名变成可选的,可以给中间名设定一个默认值,即空集,还要注意一旦使用了默认值,要将未定义默认值的形参放在前面,定义过默认值的形参放在后面,代码如下:

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()

musician = get_formatted_name('jimi','hendrix')
print(musician)
musician = get_formatted_name('john','lee','hooker')
print(musician)

3.3返回字典

        函数可以返回任何数据结构,包括字典(一系列键值对)、列表等复杂的数据结构。

def build_persion(first_name, last_name):
    """返回一个字典,其中包含一个人的信息"""
    persion = {'first': first_name, 'last': last_name}
    return persion
musician = build_persion('jimi','hendrix')
print(musician)

        让函数接收简单的文本信息,并将其放在一个更合适的数据结构中,会让你更好的处理他们。如下,我们可以在上面代码段的基础上,添加年龄。

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

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

        我们在上述代码段中加入了age,但是,并不是所有的人都要加入age选项,所以要使用默认值将其变为可选的,一旦使用了默认值,就必须把未用默认值的形参放在函数定义中的前面,已定义默认值的实参放在函数定义的后面。

3.4结合使用函数和while循环

        可将函数与本书介绍过的任何Python结构结合起来使用,如下:

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 tine 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}!")

4.传递列表

        将列表传递给函数,函数就可以直接访问列表。如下:

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

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

4.1在函数中修改列表

        将列表传递给函数后,函数就可以对其进行修改。在函数中对列表进行的修改都是永久性的,这让你能高效的处理列表中的数据。

def print_models(unprinted_design, completed_design):
    """模拟打印每个设计,直到未打印的设计都打印完毕"""
    while unprinted_design:
        current_design = unprinted_design.pop()
        print(f"Printing model: {current_design}")
        completed_design.append(current_design)

def show_completed_models(completed_models):
    """显示打印好的模型"""
    print("\nThe following models have been printed:")
    for completed_model in completed_models:
        print(completed_model)

unprinted_designs = ['phone case', 'robot pendant', 'dade']
completed_models=[]

print_models(unprinted_designs, completed_models)
show_completed_models(completed_models)

        上段代码中,定义了两个函数来实现这一功能。注意,我们在定义一个函数时,如果这一函数要实现的功能太多,要们要将它拆分成多个函数,分别实现一个功能,这样易于理解与修改。在定义第一个函数时,使用了.pop()弹出末尾元素,以及.append()将元素添加到列表末尾这两条语句,第二个函数使用了for循环。然后,在实现相应功能时,分别调用相应的函数即可。

4.2禁止函数修改列表

        有时候,需要禁止函数修改列表。这样我们要向函数提供一个原函数的副本,即:切片就可以实现该功能。如下:

print_models(unprinted_designs[:], completed_models)

        切片表示法([:])可以创建列表副本,这样传递给函数的就是列表的副本,而不是列表原件。但是,要注意这样做的话会花费更多的时间和内存。

5.传递任意数量的实参

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

def make_pizza(*toppings):
    """概述要制作的比萨"""
    for topping in toppings:
        print(f"- {topping}")

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

        *toppings创建了一个空元组,并将收到的值都封装到这个元组中,这样函数就可以从这个元组中调用提供的任意数量的实参。

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

         如果要让函数接受不同类型的实参,必须在函数定义中将接纳任意数量实参的形参放在最后,让Python先匹配位置实参和关键字实参,再将余下的实参收集到最后一个形参中。

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(31, 'mushrooms', 'green peppers', 'extra cheese')

        基于上述函数的定义,Python将第一个实参赋值给size,将其后所有的实参赋给*toppings。要注意,你经常会看到通用形参名*args,它也是收集任意数量的位置实参。

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

         有时候,要接受任意数量的实参,但预先不知道传递给函数的时什么样的信息,在这种情况下可以将函数编写成可以接受任意数量的键值对——调用语句提供了多少就接受多少。

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)

        形参**user_info的两个星号是让Python创建名为user_info的空字典并将所有接收到的名称值对都放到这个字典中。这样,函数可以向访问其它字典那样访问user_info中的名称值对。其中,定义location、field时使用了关键字实参。注意,一是要把定义的任意数量的关键字实参放在最后,二是你经常会看到形参名**kwargs,它用于收集任意数量的关键字实参。

6.将函数储存在模块中

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

6.1导入整个模块

        要让函数导入模块,首先得出创建模块。模块是名为.py的文件,包含要导入到程序中的代码。

import pizza

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

        pizza是模块所在的文件名,导入后,就可以直接调用函数。

6.2导入特定函数

from module_name import function_name

from module_name import function_0, function_1, function_2

        可以通过上述第一种方法,导入一个特定函数吗,也可以使用第二种方法,导入多个特定函数。

6.3使用as给函数指定别名

       还可以给函数指定别名。通过给函数指定一个简短的别名,让你能够更轻松地调用模块中的函数。

import module_name as mn

import pizza as p

p.make_pizza(16,'pepperoni')

6.4导入模块中的所有函数

        使用星号(*)运算符可以让Python导入模块中的所有函数。

from pizza import *

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

from module_name import *

7.函数编写指南

         编写函数时,应给函数指定描述性名称,并采用文档字符串格式简要介绍其功能,还要注意,一是,给形参指定默认值时,等号两边不要有空格,调用关键字实参时,也不要有空格。二是,如果程序包含多个模块和函数应该使用两个空行将其分开。三是,import语句都应该放在开头。

你可能感兴趣的:(python,1024程序员节)