1函数定义

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

greet_user()
>>>Today is Sunday!

紧跟在def greet_user(): 后面的所有缩进行构成了函数体。第二行的文本是被称为文档字符串 (docstring)的注释,描述了函数是做什么的。文档字符串用三引号括起,Python使用它们来生成有关程序中函数的文档。

#传递参数

def greet_user(username):
    """显示简单的问候语"""
    print(username.title() + ",Today is Sunday!")

greet_user('Jude')
>>>Jude,Today is Sunday!

2传递实参

2.1位置实参:实参的顺序与形参的顺序相同(顺序一致)

def describe_pet(animal_type,pet_name):
    """显示宠物信息"""
    print("\nI have a " + animal_type + ".")
    print("My " + animal_type + "'s name is " + pet_name.title() + ".")
describe_pet('hamster','harry')
>>>I have a hamster.
>>>My hamster's name is Harry.

2.2关键字实参

关键字实参是传递给函数的名称—值对。直接在实参中将名称和值关联起来了,关键字实参无需考虑函数调用中的实参顺序,还清楚地指出了函数调用中各个值的用途。

def describe_pet(animal_type,pet_name):
    """显示宠物信息"""
    print("\nI have a " + animal_type + ".")
    print("My " + animal_type + "'s name is " + pet_name.title() + ".")
describe_pet(animal_type='hamster',pet_name='harry')
>>>I have a hamster.
>>>My hamster's name is Harry.

关键字实参的顺序无关紧要,因为Python知道各个值该存储到哪个形参中。

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

2.3默认值

def describe_pet(pet_name,animal_type='dog'):
    """显示宠物信息"""
    print("\nI have a " + animal_type + ".")
    print("My " + animal_type + "'s name is " + pet_name.title() + ".")
describe_pet(pet_name='harry')
>>>I have a dog.
>>>My dog's name is Harry.

编写函数时,可给每个形参指定默认值 。在调用函数中给形参提供了实参时,Python将使用指定的实参值;否则,将使用形参的默认值。

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

describe_pet(pet_name='harry',animal_type='cat')
>>>I have a cat.
>>>My cat's name is Harry.

注意:由于给animal_type 指定了默认值,无需通过实参来指定动物类型,因此在函数调用中只包含一个实参:宠物的名字。然而,Python依然将这个实参视为位置实参,因此如果函数调用中只包含宠物的名字,这个实参将关联到函数定义中的第一个形参。否则会报错:

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

describe_pet(pet_name='harry')

>>>SyntaxError: non-default argument follows default argument

即使用默认值时,在形参列表中必须先列出没有默认值的形参,再列出有默认值的实参。这让Python依然能够正确地解读位置实参。

2.4混合使用位置实参,关键值实参,默认值

函数定义:

def describe_pet(pet_name,animal_type='dog'):

调用: 

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

3返回值

3.1 return

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)
>>>Jimi Hendrix

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('john','hooker','lee')
print(musician)
>>>Jimi Hendrix
>>>John Lee Hooker

实参middle_name指定一个默认值——空字符串。

3.3返回字典

def build_person(first_name,last_name,age=''):
    """返回一个字典,包含一个人的信息"""
    person = {'first':first_name,'last':last_name}
    if age:
        person['age'] = age
    return person
musician = build_person('jimi','hendrix',27)
print(musician)
>>>{'first': 'jimi', 'last': 'hendrix', 'age': 27}

函数接受简单的文本信息,将其放在一个更合适的数据结构中。

4传递列表

def greet_users(names):
    for name in usernames:
        msg = "Hello," + name.title() + "!"
        print(msg)
usernames = ['hanna','jude','lily']
greet_users(usernames)
>>>Hello,Hanna!
>>>Hello,Jude!
>>>Hello,Lily!

4.1在函数中修改列表

列表传递给函数后,函数就可对其进行修改。在函数中对这个列表所做的任何修改都是永久性的,这能够高效地处理大量的数据。

unprinted_designs = ['iphone case','robot pendant','hellokity']
completed_models = []

while unprinted_designs:
    current_design = unprinted_designs.pop()
    print("Printing model: " + current_design)
    completed_models.append(current_design)

print("\nThe following models have been printed:")
for completed_model in completed_models:
    print(completed_model)
>>>Printing model: hellokity
>>>Printing model: robot pendant
>>>Printing model: iphone case
>>>The following models have been printed:
>>>hellokity
>>>robot pendant
>>>iphone case

编写函数后:

def print_models(unprinted_designs,completed_models):
    while unprinted_designs:
        current_design = unprinted_designs.pop()
        print("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(completed_model)

unprinted_designs = ['iphone case','robot pendant','hellokity']
completed_models = []
print_models(unprinted_designs,completed_models)
show_completed_models(completed_models)

>>>Printing model: hellokity
>>>Printing model: robot pendant
>>>Printing model: iphone case
>>>The following models have been printed:
>>>hellokity
>>>robot pendant
>>>iphone case

这个程序还演示了这样一种理念 : 即每个函数都应只负责一项具体的工作。第一个函数打印每个设计,而第二个显示打印好的模型;这优于使用一个函数来完成两项工作。编写函数时,如果发现它执行的任务太多,请尝试将这些代码划分到两个函数中。这有助于将复杂的任务划分成一系列的简单任务。

4.2禁止函数修改列表

当你不希望原始列表被改变的时候,可以向函数传递列表的副本:

function_name(list_name[:])

切片表示法 [ : ] 创建列表的副本。上例中,如果不想清空未打印的列表,可修改如下:

print_models(unprinted_designs[:],completed_models)

但除非特殊情况,最好还是将原始列表传递给函数:因为让函数使用现成列表可避免花时间和内存创建副本,从而提高效率,在处理大型列表时尤其如此。

5.传递任意数量的实参

def make_pizza(*toppings):
    """打印所有配料"""
    print(toppings)

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

形参名*toppings 中的星号让Python创建一个名为toppings 的空元组,并将收到的所有值都封装到这个元组中。它以类似的方式处理不同的调用。Python将实参封装到一个元组中,不管多少个实参,即便函数只收到一个值也如此。

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

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

def make_pizza(size,*toppings):
    """制作披萨"""
    print("\nMaking a " + str(size) + "-inch pizza with the following toppings:")
    for topping in toppings:
        print("-" + topping)

make_pizza(16,'pepperoni')
make_pizza(12,'mushrooms','green peppers','cheese')
>>>Making a 16-inch pizza with the following toppings:
>>>-pepperoni
>>>Making a 12-inch pizza with the following toppings:
>>>-mushrooms
>>>-green peppers
>>>-cheese

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

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

示例:创建用户简介,你知道你将收到有关用户的信息,但不确定会是什么样的信息。在下面的示例中,函数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='China',
                             field='physics')
print(user_profile)
>>>{'first name': 'albert', 'last name': 'einstein', 'location': 'China', 'field': 'physics'}

形参**user_info 中的两个星号让Python创建一个名为user_info 的空字典,并将收到的所有名称—值对都封装到这个字典中。在这个函数中,可以像访问其他字典那样访问user_info 中的名称—值对。

编写函数时,可以以各种方式混合使用位置实参、关键字实参和任意数量的实参正确地使用这些类型的实参并知道它们的使用时机。知道在各种情况下哪种方法的效率是最高的。

6.函数编写

  • 命名:应给函数或模块指定描述性名称,且只在其中使用小写字母和下划线。通俗易懂。
  • 注释:每个函数都应包含简要地阐述其功能的注释,该注释应紧跟在函数定义后面,并采用文档字符串格式。
  • 给形参指定默认值时,等号两边不要有空格;
def function_name(parameter_0,parameter_1='default value'):
  • 对于函数调用中的关键字实参,也遵循这种约定:
function_name(value_0,parameter_1='value')
  • 形参过多情形: 
def function_name(
        parameter_0,parameter_1,parameter_2,
        parameter_3,parameter_4,parameter_5):
    function body...
  • 如果程序或模块包含多个函数,可使用两个空行将相邻的函数分开,
  • 所有的import 语句都应放在文件开头,唯一例外的情形是:在文件开头使用了注释来描述整个程序。