[python笔记]7.函数

浪子不回头ぞ 提交于 2020-01-31 23:36:35

一.定义函数

1)def

使用关键字def定义函数,后面跟函数名,括号中为参数,以冒号结尾,后面的缩进行为函数体,
eg:

def greeter_user():
    print("hello world")
greeter_user()

输出:

hello world

二.给函数传递参数

1)位置实参

eg1:

def great_user(user_name):
    '''显示其简单的问候语'''
    print("Hello, " + user_name.title() + "!")
great_user('jesse')

输出:

Hello, Jesse!

其中user_name作为形式参数,jesse作为实际参数传给great_user函数保存在user_name中
eg2:

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')
describe_pet('dog', 'willie')

输出

I have a hamster.
My hamster's name is Harry.

I have a dog.
My dog's name is Willie.

2)关键字实参

将形式参数与实际参数的内容绑定,形成名称-值对,则此时传递实参的顺序就无关紧要了,下面程序段两端输出相同结果
eg:

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')
describe_pet(pet_name = 'harry', animal_type = 'hamster')

输出:

I have a hamster.
My hamster's name is Harry.

I have a dog.
My dog's name is Willie.

3)默认值

编写函数时,可以给每个形参指定默认值,在调用函数中给形参提供了实参时,将使用指定的实参值,否则,将使用形参的默认值,指定默认值后,在调用的过程中可以简化调用
在定义函数时有默认值的形参需要放在没有默认值的形参后面
给形参指定默认值,等号两边不要有空格
eg1:

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 = 'willie')

输出:

I have a dog.
My dog's name is Willie.

如果将有默认值的形参放在没有默认值的前面,会出现错误、

eg2:

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 = 'willie')

输出

SyntaxError: non-default argument follows default argument

原因在于由于给animal_name指定了默认值,无需通过实参来指定动物类型,因此在函数调用中只跑含一个实参即宠物的名字,然而python依然将这个实参视为位置实参,因此如果值包含宠物的名字,这个实参视为位置实参,关联到第一个形参。

如果需要描述其他的动物,则需要手动给参数赋值
eg:

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 = 'willie', animal_type = 'hamster')

输出:

My hamster's name is Willie.

三.返回值

1)返回简单值

函数返回一个值或是一组值,函数返回的值称为返回值,在函数中,可以使用return语句返回调用函数的代码行。
eg:

def get_formatted(first_name, last_name):
    full_name = first_name + " " + last_name
    return full_name.title()
musician = get_formatted('jimi', 'hendrix')
print(musician)

函数将full_name的首字母大写返回,调用时保存在musician中
输出:

Jimi Hendrix

2)可选实参

使用默认值让实参变为可选的,使用函数的人只需要在必要时提供额外的信息
eg:

def get_formatted(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
musician = get_formatted('jimi', 'hendrix')
print(musician)
musician = get_formatted('join', 'hooker', 'lee')
print(musician)

middle_name默认为空字符串,在使用时才手动传参数。
如果使用位置参数,要使用middle_name,就必须保证它是最后一个实参

3)返回字典

eg:

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',age = 27)
print(musician)

输出

{'first': 'jimi', 'last': 'hendrix', 'age': 27}

4)函数与while循环

def get_formatted(first_name, last_name):
    full_name = first_name + " " + last_name
    return full_name.title()
while True:
    print("\nPlease tell me your name:")
    print("(enter 'q' at any time to qiut)")
    f_name = input("First Name: ")
    if f_name == 'q':
        break
    l_name = input("Last Name: ")
    if l_name == 'q':
        break
    formatted_name = get_formatted(f_name, l_name)
    print("\nHello " + formatted_name + "!")

输出

Please tell me your name:
(enter 'q' at any time to qiut)
First Name: eric
Last Name: matthes

Hello Eric Matthes!

Please tell me your name:
(enter 'q' at any time to qiut)
First Name: q

四.传递列表

eg

def greet_users(names):
    for name in names:
        msg = "Hello, " + name.title() + "!"
        print(msg)
usernames = ['hannah', 'try', 'margot']
greet_users(usernames)

输出

Hello, Hannah!
Hello, Try!
Hello, Margot!

1)在函数中修改列表

将列表传递给函数后,函数就可以进行修改,在函数中对列表所作的任何修改都是永久性
eg1:

unprinted_designs = ['iphone case', 'robot pendant', 'dodecahedron']
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: dodecahedron
Printing model: robot pendant
Printing model: iphone case

The following models have been printed:
dodecahedron
robot pendant
iphone case

对该列表修改的例子可以重新组织,定义两个函数,分别为处理函数和显示函数,每个函数都应该只负责一项具体工作。便于阅读与维护
eg2:

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(completed_models):
    print("\nThe following models have been printed")
    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(completed_models)

输出:

Printing model: dodecahedron
Printing model: robot pendant
Printing model: iphone case

The following models have been printed
dodecahedron
robot pendant
iphone case

2)禁止函数修改列表

在上一个例子中,执行结束后unprinted_designs全部移植到completed_models中,此时列表unprinted_designs为空,如果需要保存unprinted_designs的初始状态,则可以向函数传递参数时不传递原件而是副本function_name(list_name[:])
即采用切片表示法传递副本
这种效率会降低,因为要花时间保留副本,所以除非有充分的理由需要传递副本,否则还是应该将原始列表传递给函数
eg:

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(completed_models):
    print("\nThe following models have been printed")
    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(completed_models)
print(unprinted_designs)

输出:

Printing model: dodecahedron
Printing model: robot pendant
Printing model: iphone case

The following models have been printed
dodecahedron
robot pendant
iphone case
['iphone case', 'robot pendant', 'dodecahedron']

五.传递任意数量的实参

eg:

def make_pizza(*toppings):
    print("\nMaking a pizza with the following toppings: ")
    for topping in toppings:
        print("- " + topping)
make_pizza('pepperoin')
make_pizza('mushrooms', 'green peppers', 'extra cheese')

输出

Making a pizza with the following toppings:
- pepperoin

Making a pizza with the following toppings:
- mushrooms
- green peppers
- extra cheese

*toppings可以创建一个名为toppings的空元组,并将接收到的所有值(不论多少)装入这个元组之中

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

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

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', 'extra cheese')

输出:

Making a 16-inch pizza with the following toppings:
- pepperoni

Making a 12-inch pizza with the following toppings:
- mushrooms
- green peppers
- extra cheese

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

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

eg1:

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_pofile('albert', 'einstein', location='princetin', filed='physics')
print(user_profile)

本例中build_profile()的定义要求提供名和姓,同时需要用户根据需要提供任意数量的名称-值对。形参**user_info中的两个星号让python创建一个名为user_info的空字典,并将收到的所有名称-值对都封装到这个字典中,在这个函数中,可以像访问其他字典那样访问user_info中的名称-值对。
调用这个函数,不管额外提供了多少键-值对,它都能够正确处理。
输出:

{'first_name': 'albert', 'last_name': 'einstein', 'location': 'princetin', 'filed': 'physics'} 

传递任意个参数用 * 代表创建一个元组
传递任意个参数用 ** 代表创建一个字典

eg2:

def make_car(car_name, car_type,**car_info):
    car = {}
    car['name'] = car_name
    car['type'] = car_type
    for key, value in car_info.items():
        car[key] = value
    return car
car1 = make_car('subaru', 'outback', color='blue', two_package=True)
print(car1)

输出

{'name': 'subaru', 'type': 'outback', 'color': 'blue', 'two_package': True}

六.将函数存储在模块中

使用函数可以将代码块与主程序分离。通过给函数指定描述性名称,让主程序更容易理解。进一步将函数存储在称为模块的独立文件中,再将模块导入主程序中。使用import语句允许当前运行的程序文件中使用模块中的代码
(类似C++中#include<>)

1)导入整个模块

首先要创建模块,模块是拓展名为.py的文件,包含要导入程序中的代码

module_name.function_name()

要调用被导入模块中的函数,可指定导入的模块的名称pizza和函数名make_pizza(),并用句点分割他们,这些代码的输出与没有导入模块的原始程序相同

eg1:

#pizza.py
def make_pizza(size, *toppings):
    print("\nMaking a " + str(size) + 
        "-inch pizza with the following toppings: ")
    for topping in toppings:
        print("- "+topping)       
#making_pizza.py
import pizza
pizza.make_pizza(16, 'pepperoni')
pizza.make_pizza(16, 'mushroom', 'green peppers', 'extra cheese')

输出

Making a 16-inch pizza with the following toppings:       
- pepperoni

Making a 16-inch pizza with the following toppings:       
- mushroom
- green peppers
- extra cheese

Python读取这个文件时。通过代码行import pizza让Python打开文件pizza.py,并将其所有的函数都复制到这个程序中去,复制过程在后台进行,所以在making_pizza.py中可以使用pizza.py中的所有函数

2)导入特定的函数

即从模块中导入任意数量的函数

from module_name import function0, function1, function2

eg:

#making_pizza.py
from pizza import make_pizza
make_pizza(16, 'pepperoni')
make_pizza(16, 'mushroom', 'green peppers', 'extra cheese')

输出
这里在import中显示的导入make_pizza(),因此调用它时只需指定其名称

3)使用as给函数指定别名

在2)的例子中 引入了pizza.py中的make_pizza()函数,则在现有的程序中就不能存在名为make_pizza()的函数,否则会产生冲突,此时就需要将引入的函数设置一个别名
eg:

#making_pizza.py
from pizza import make_pizza as mp
def make_pizza():
    print("hello world")
mp(16, 'pepperoni')
mp(16, 'mushroom', 'green peppers', 'extra cheese')
make_pizza()

输出

Making a 16-inch pizza with the following toppings:
- pepperoni

Making a 16-inch pizza with the following toppings:
- mushroom
- green peppers
- extra cheese
hello world

这里将引入的make_pizza()声明为别名mp,这样就不会与程序本身的make_pizza()产生冲突
如果不声明
eg:

#making_pizza.py
from pizza import make_pizza
def make_pizza():
    print("hello world")
make_pizza(16, 'pepperoni')
make_pizza(16, 'mushroom', 'green peppers', 'extra cheese')
make_pizza()

输出:

make_pizza(16, 'pepperoni')
TypeError: make_pizza() takes 0 positional arguments but 2 were given
#产生冲突 

4)使用as给模块指定别名

操作同上 import moudle_name as mn
eg:

#making_pizza.py
import pizza as p
p.make_pizza(16, 'pepperoni')
p.make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese')

输出

Making a 16-inch pizza with the following toppings:
- pepperoni

Making a 12-inch pizza with the following toppings:
- mushrooms
- green peppers
- extra cheese

5)导入模块中的所有函数

使用*运算符可让python导入所有模块中的函数

from moudle_name import * 

eg:

#making_pizza.py
from pizza import *
make_pizza(16, 'pepperoni')
make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese')

输出

Making a 16-inch pizza with the following toppings:
- pepperoni

Making a 12-inch pizza with the following toppings:
- mushrooms
- green peppers
- extra cheese

容易产生冲突,尽量不要用,道理同3)

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!