1 函数概述

函数定义以def开头,后面跟着函数名、参数和一个冒号。Python中没有代码块符号,例如C++中的开始花括号和结束花括号。

在Python中,函数的结尾是未定义的,假设函数在下一个未缩进的行之前结束。
函数定义必须位于函数调用的上方。
函数是带名字的代码块,用于完成具体的工作。要执行函数定义的特定任务,可调用该函数。
在程序中多次执行同一项任务,只需要执行该任务的函数。调用函数多次是一种效率极高的工作方式。

def demo():
    print("Hello, world!")
    print("demo")


def demo1(a, b):
    print(a, b)


def my_sum(a, b):
    return a + b


demo1(a=[1, 2, 3], b={1: 1, 2: 2})
print(my_sum(1, 2))
print(my_sum([1, 2, 3, 4], [7, 8, 9, 0]))

2 代码定义方法

  • 1、使用def关键字来告诉Python要定义一个函数,这是函数定义
  • 2、向Python指出函数名,还可能在括号内指出函数为完成其任务需要什么样的消息,它不需要任何信息就能完成任务,因此括号是空的。
  • 3、最后,定义以冒号结尾

注意:

  • 函数定义后面的所有缩进行构成了函数体。6个双引号构成的注释被称为文档字符串,这描述了函数是做什么的。
  • 函数调用让Python执行函数的代码。要调用函数,可依次指定函数名以及用括号括起来的必要信息。

3 实参和形参

实参是调用函数时传递给函数的信息。当我们调用函数时,将要让函数使用的信息放在括号内,实参放在函数内的括号,将实参传递给函数,这个值被存储在形参中。

实参:函数定义中的变量称为实参
形参:函数调用中的变量称为形参

4 传递实参

函数定义中可能包含多个形参,因此函数调用中也能包含多个实参。

4.1 位置实参

Python必须将函数调用中的每个实参都关联到函数定义中的一个形参。

最简单的关联方式是基于实参的顺序。在函数中,可根据需要使用任意数量的位置实参,Python将按顺序将函数调用中的实参关联到函数定义中的相应的形参。

4.2 关键字实参

关键字实参是传递给函数的名称——值对。程序员可以直接在实参中将名称和值关联起来,因此向函数传递实参时不会混淆

  • 关键字实参让程序员无需考虑函数调用中的实参顺序,清楚地指出函数调用中各值的用途。
  • 使用关键字实参时,必须准确指定函数定义中的形参名

4.3 让实参变成可选的

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

4.3 默认值

编写函数时,可以给每个形参指定默认值。给形参指定默认值后,可在函数调用中省略相应的实参。使用默认值可简化函数调用,清楚地指出函数的典型用法。

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

def test(a, b=False):
    if b:
        return a
    else:
        return a * a


print(test(a=2))
print(test(a=2, b=True))

5 返回值

函数并非总是直接显示输出,相反,它可以处理一些数据,并返回一个或一组值。函数返回的值被称为返回值。

在函数中,可使用return语句将值返回到调用函数的代码行。
返回值让程序员能够让程序的大部分繁重工作移到函数中去完成,从而简化主程序。

6 传递列表

向函数传递列表很有用,这种列表包含的可能是名字、数字或更复杂的对象(例如字典)。

将列表传递给函数后,函数就能直接访问其内容

6.1 在函数中修改列表

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

6.2 禁止函数修改列表

有时候,需要禁止函数修改列表。为了解决这个问题,可向函数传递列表的副本而不是原件。这样函数所作出的任何修改只影响副本,而不丝毫影响原件。

6.2.1 切片表示法

function_name(list_name[:])

切边表示法[:]创建列表的副本。这样函数依然能够完成其工作,但函数所作的修改不会影响到列表。

虽然向函数传递列表的副本可保留原始列表的内容,但除非有充分的理由需要传递副本,否则还是应该将原始列表传递给函数,从而提高效率,在处理大型列表时尤其如此。

7 传递任意数量的实参

有时候,程序员不知道函数需要接受多少个实参,Python允许函数从调用语句中手机任意数量的实参。

(*)让Python创建一个空元组,并将收到的所有值都封装到这个元组中。(即便函数只收到一个值也如此。)

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

如果要让函数接收不同类型的实参,必须在函数定义中将接纳任意数量实参的形参放在最后

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

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

(**)让Python创建一个空字典,并将收到的所有名称——值对都封装到这个字典中。
小结:编写函数时,可以使用各种方式混合使用位置实参、关键字实参和任意数量的实参。

10 将函数存储在模块中

Python模块主要分为以下3种:

  • 1、内置模块,即Python自带的模块,如sys、time、math等。
  • 2、第三方的开源模块,即通常所说的模块就是指开源模块,这类模块是由程序员或企业开发并免费分享给大家使用的,通常能够实现某个一个大类的功能,如xlwings模块就是专门用于控制Excel的模块。
  • 3、自定义模块,Python用户可以将自己编写的代码或函数封装成模块,以方便在编写奇特程序时调用。注意:自定义模块不能和内置模块重名,否则不能导入内置模块。

函数的优点之一是,使用函数可将代码块和主程序分离。

通过给函数指定描述性名称,增加主程序的可读性。
将函数存储在被称为模块的独立文件中,再将模块导入到主程序中,隐藏程序代码的细节,将重点放在程序的高层逻辑上。

import语句允许在当前运行的程序文件中使用模块中的代码。

10.1 导入整个模块

只需要编写一条Import语句并在其中只当模块名,就可在程序中使用该模块中所有的函数。
语法如下:

module_name.function_name()

要让函数可导入,先创建模块。

  • 在主程序所在的目录创建另一个.py文件,这个文件导入刚创建的模块。
  • Python读取这个文件时,并将其中的所有函数都复制到程序中。

10.2 导入特定的函数

导入模块中的特定函数。
语法如下:

from module_name import function_name

通过逗号分割函数名,可根据需要从模块中导入任意数量的函数。
语法如下:

from module_name import function_0, function_1, function_2

小结:若使用这种语法,调用函数时就无需使用句点。由于我们在import语句中显式地导入了函数,因此调用函数时只需要指定其名称。

10.3 使用as给函数指定别名

若导入的函数名和程序现有的名称冲突,或函数名太长,便可指定简短而独一无二的别名——函数的另一个外号,类似于外号。

在导入时给函数指定别名。
语法如下:

from module_name import function_name as fn

10.4 使用as给模块指定别名

给模块指定别名,让程序员更加轻松地调用模块中的函数。

  • 这样使代码更加简洁,还可让程序员不在关注模块名,而专注于描述性的函数名。
  • 这些函数名明确地指出函数的功能。
    语法如下:
import module_name as mn

10.5 导入模块中的所有函数

使用(*)运算符让Python导入模块中的所有函数。
语法如下:

from module_name import *
  • (*)让模块中的每个函数都复制到这个程序文件中。由于导入了每个函数,而无需使用句点表示法。
  • 注意:使用非自己编写的大型模块,最好不要采用这种导入方法。若模块中函数名称与主函数中发生名称冲突,Python遇到多个名称相同的函数或变量,进而覆盖函数。
  • 只导入自己需要的函数,或导入整个模块并使用句点表示法(增加代码的可读性)

10.6 第三方开源模块的安装方法

  • 使用pip命令安装;
  • 通过编辑器(如Pycharm)安装。

10.6.1 用pip命令安装模块

pip是Python提供的一个命令,主要功能是安装和卸载第三方模块。

这种方法默认将模块安装在Python安装目录中的“site-packages”文件夹。

pip命令下载模块时默认访问的服务器设在国外,速度不稳定,可能会导致失败。这里,可以使用国内的院校设立的镜像服务器来安装模块。

例如从清华大学的镜像服务器安装xlwings模块的命令为“pip install xlwings -i https://pypi.yuna.tsinghua.edu.cn/simple”。

  • 命令中的“-i”是一个参数,用于指定pip命令下载模块的服务器地址。
  • “https://pypi.yuna.tsinghua.edu.cn/simple”是清华大学设立的模块镜像服务器地址。

10.6.2 在Pycahrm中安装模块

以下以安装xlwings模块为例。

  • 启动Pythcarm,单击菜单栏中的“File”按钮,在展开的菜单中单击“Settings”命令。
  • “Settings”对话框中展开“Project:python”选项组,在展开的列表中单击“ProjectInterpreter”选项,在右侧的界面中可看到系统中已安装的模块,单击右侧的按钮。
  • 对话框中输入模块名,如“xlwings”,按Enter键,在搜索结果中选择要安装的模块,单击左下角的“Install Package”按钮,如下图所示。安装完成后关闭对话框。

注意:在安装一个模块时,有可能会同时安装一些该模块需要调用的其他模块。

11 函数编写指南

  • 给函数只当描述性名称,且只在其中使用小写字母和下划线。
  • 每个函数都应包含简要阐述其功能的注释,盖住是应紧跟在函数定义后面,并采用文档字符串格式。
  • 只需了解函数的名称、需要的实参以及返回值的类型。
  • 给形参指定默认值,等号两边不要有空格。(函数调用中的关键字实参同理)
  • 对于程序或模块包含多个函数,可使用两个空行将相邻函数分开,这样更容易了解前一个函数在什么地方结束,下一个函数从什么地方开始。

12 顺序化编程

顺序化程序要求在每行代码之前都要有行号,但顺序式程序倾向于陷入某程度的复杂性,使得代码变得那一识别或无法修改。

13 助记式编程

开发者编写的代码更接近于计算机硬件的层级。有一个汇编器程序,就像编译器一样,但是,它会将助记式的指令直接转换为对象或二进制文件中的机器代码,让处理器一次一个字节地运行。

一条汇编式的助记式指令,直接关联到处理器所能理解的一条机器指令

14 可变参数

14.1 可变参数args

def add(*args):
    result = 0
    for item in args:
        result += item
    return result


print(add(1, 2, 3))

14.2 可变参数kwargs

def test(a, b):
    print(a + b)


def add(x, **kwargs):
    if x == 2:
        test(**kwargs)


add(x=2, a=1, b=2)

13 递归的实现

def function_0(n):
    result = 1
    for item in range(1, n + 1):
        result *= item
    return result


def function_1(n):
    if n == 1:
        return n
    return n * function_1(n - 1)

动手试一试

8-1 消息:

def display_message():
    print("Today we learned functions.")
display_message()

8-2 喜欢的图书:

def favorite_book(title):
    print("One of my favorite books is " + title.title() + ".")
favorite_book('I want to be Yama')

8-3 T恤:

def make_shirt(size, text):
    print("The size of this T-shirt is " + size + '.')
    print("The text of this T-shirt is " + text + '.')
make_shirt('12', 'flower')
make_shirt(size='18', text='dog')

8-4 大号T恤:

def make_shirt(size='big', text='I love Python'):
    print("The size of this T-shirt is " + size + '.')
    print("The text of this T-shirt is " + text + '.')
make_shirt()
print()
make_shirt(size='medium')
print()
make_shirt(text='I love china')

8-5 城市:

def describe_city(city_name, city_county='china'):
    print(city_name.title() + " is in " + city_county + ".")
describe_city('hongkong')
describe_city('beijing')
describe_city('reykjavik')

8-6 城市名:

def city_country(city_name, city_coun):
    message = city_name + ", " + city_coun
    return message
message = city_country('honkong', 'china')
print(message)
message = city_country('beijing', 'china')
print(message)
message = city_country('shanghai', 'china')
print(message)

8-7 专辑:

def make_album(singer_name, album_name, song_num=''):
    album = {'singer_name': singer_name, 'album_name': album_name}
    if song_num:
        album['song_num'] = song_num
    return album
album = make_album('刘欢', '快乐齐天')
print(album)
album = make_album('张学友', '遥远的她')
print(album)
album = make_album('杨坤', '空城')
print(album)
album = make_album('贝多芬', '命运交响曲', '19')
print(album)

8-8 用户的专辑:

def make_album(singer_name, album_name, song_num=''):
    album = {'singer_name': singer_name, 'album_name': album_name}
    if song_num:
        album['song_num'] = song_num
    return album
while True:
    singerName = input("SingerName: ")
    if singerName == 'q':
        break
    AlbumName = input("AlbumName: ")
    if AlbumName == 'q':
        break
    Album = make_album(singerName, AlbumName)
    print(Album)

8-9 魔术师:

def show_magicians(magicians):
    for name in magicians:
        print(name)
magicians = ['dog', 'kate', 'jobs']
show_magicians(magicians)

8-10 不变的魔术师:

def show_magicians(magicians):
    for name in magicians:
        print(name)
def make_magicians(magicians):
    new_magicians = []
    while magicians:
        current = magicians.pop()
        current = 'the great ' + current
        new_magicians.append(current)
    return new_magicians
magicians = ['dog', 'kate', 'jobs']
show_magicians(magicians)
magicians = make_magicians(magicians)
print()
show_magicians(magicians)

三明治:

def add_ingredients(*ingredients):
    for ingredient in ingredients:
        print("The ingredients you're adding are: " + ingredient)
add_ingredients('lobster', 'Braise in soy sauce meat')
add_ingredients('cheese', 'Bluefin tuna', 'Foie gras')
add_ingredients('bacon')

用户简介:

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='princeton', field='physics', country='china')
print(user_profile)

汽车:

def add_car_info(manufacturers, models, **info):
    car = {}
    car['manufacturers'] = manufacturers
    car['models'] = models
    for key, value in info.items():
        car[key] = value
    return car
car = add_car_info('subaru', 'outback', color='blue', tow_package=True)
print(car)