定义一个函数

函数用关键字def 来定义。def 关键字后跟一个函数的标识符名称,然后跟一对圆括号。圆括号之中可以包括一些变量名,该行以冒号结尾。接下来是一块语句,它们是函数体。

def sayHello():
    print('Hello World!')
#调用
sayHello()

函数的参数

参数在函数定义的圆括号对内指定,用逗号分割。

def printMax(a,b):
    if a > b:
        print(a)
    else:
        print(b)

局部变量

当你在函数定义内声明变量的时候,它们与函数外具有相同名称的其他变量没有任何关系,即变量名称对于函数来说是局部的。这称为变量的作用域。所有变量的作用域是它们被定义的块,从它们的名称被定义的那点开始。

x = 50

def func(x):
    print('x is', x)
    x = 2
    print('Changed local x to', x)

func(x)
print('x is still', x)

使用全局语句

如果你想要为一个定义在函数外的变量赋值,那么你就得告诉Python 这个变量名不是局部的,而是全局的。我们使用global 语句完成这一功能。

你可以使用定义在函数外的变量的值(假设在函数内没有同名的变量)。然而,我并不鼓励你这样做,并且你应该尽量避免这样做,因为这使得程序的读者会不清楚这个变量是在哪里定义的。使用global 语句可以清楚地表明变量是在外面的块定义的。

x = 50

def func(x):
    global x
    print('x is', x)
    x = 2
    print('Changed local x to', x)

func(x)
print('x is still', x)

使用非局部语句

上面给出了如何在局部和全局作用域内使用变量。还有一种作用域叫做“非局部”域,处于这两种作用域之间。
非局部作用域在你定义函数内的函数时会看到。

由于在Python 中,任何事物是可执行的代码,你可以在任何地方定义函数。

def func_outer():
    x = 2
    print('x is',x)

    def func_inner():
        nonlocal x
        x = 5

     func_inner()
     print('Changed local x to',x)

func_outer()

默认参数值

对于一些函数,你可能希望它的一些参数是可选的,如果用户不想要为这些参数提供值的话,这些参数就使用默认值。这个功能借助于默认参数值完成。你可以在函数定义的形参名后加上赋值运算符(=)和默认值,从而给形参指定默认参数值。

def say(message, times = 1):
    print(message * times)

say('Hello')
say('World', 5)

只有在形参表末尾的那些参数可以有默认参数值,即你不能在声明函数形参的时候,先声明有默认值的形参而后声明没有默认值的形参。这是因为赋给形参的值是根据位置而赋值的。例如,def func(a, b=5) 是有效的,但是def func (a=5, b) 是无效的。

关键参数

如果你的某个函数有许多参数,而你只想指定其中的一部分,那么你可以通过命名来为这些参数赋值—— 这被称作关键参数—— 我们使用名字(关键字)而不是位置(我们前面所一直使用的方法)来给函数指定实参。

这样做有两个优势—— 一、由于我们不必担心参数的顺序,使用函数变得更加简单了。二、假设其他参数都有默认值,我们可以只给我们想要的那些参数赋值。

def func(a, b=5, c=10):
    print('a is', a, 'and b is', b, 'and c is', c)

func(3, 7)
func(25, c=24)
func(c=50, a=100)

VarArgs 参数

有时,你或许想定义一个能获取任意个数参数的函数,这可通过使用* 号来实现。

def total(initial=5, *numbers, **keywords):
    count = initial
    for number in numbers:
        count += number
    for key in keywords:
        count += keywords[key]
    return count

print(total(10, 1, 2, 3, vegetables=50, fruits=100))

当我们定义一个带星的参数,像*param 时,从那一点后所有的参数被收集为一个叫做’param’ 的列表。(译者注:如在该例中,首先会给initial 的值由5 变成10 ,然后numbers 将1,2,3,收集作为一个列表numbers=(1,2,3))。

当我们定义一个带两个星的参数,像**param 时,从那一点开始的所有的关键字参数会被收集为一个叫做’param’ 的字典。(译者注:在该例子中,从vegetables=50 后的所有参数收集为一个字典keywords=’vegetables’: 50, ’fruits’:100)。

Keyword-only 参数

如果想指定特定的关键参数为keywor-only 而不是位置参数,可以在带星的参数后声明

def total(initial=5, *numbers, vegetables):
    count = initial
    for number in numbers:
        count += number
    count += vegetables
    return count

print(total(10, 1, 2, 3, vegetables=50))
print(total(10, 1, 2, 3,))
# Raises error because we have not supplied a default argument value for 'vegetables'

在带星号的参数后面申明参数会导致keyword-only 参数。如果这些参数没有默认值,且像上面那样不给关键参数赋值,调用函数的时候会引发错误。

如果你想使用keyword-only 参数,但又不需要带星的参数,可以简单地使用不适用名字的空星,如def total(initial=5, *, vegetables)。

return 语句

return 语句用来从一个函数返回即跳出函数。也可选是否从函数返回一个值。

DocStrings

Python 有一个很奇妙的特性,称为文档字符串,它通常被简称为docstrings 。DocStrings 是一个重要的工具,由于它帮助你的程序文档更加简单易懂,你应该尽量使用它。你甚至可以在程序运行的时候,从函数恢复文档字符串!

    def printMax(x, y):
        '''Prints the maximum of two numbers.

        The two values must be integers.'''
    x = int(x) # convert to integers, if possible
    y = int(y)

    if x > y:
        print(x, 'is maximum')
    else:
        print(y, 'is maximum')

printMax(3, 5)
print(printMax.__doc__)

模块简介

编写模块有各种各样的方法,但最简单的方法就是创建以.py 为扩展名的文件,在文件中包含函数和变量。

模块可以从另外一个程序导入来使用其函数的功能。

使用import sys导入模块

按字节编译的.pyc 文件

导入一个模块相对来说是一个比较费时的事情,所以Python 做了一些技巧,以便使输入模块更加快一些。一种方法是创建按字节编译的文件,这些文件以.pyc 作为扩展名。字节编译的文件与Python 变换程序的中间状态有关。当你在下次从别的程序输入这个模块的时候,.pyc 文件是十分有用的—— 它会快得多,因为一部分输入模块所需的处理已经完成了。另外,这些字节编译的文件也是与平台无关的。

这些.pyc 文件通常与.py 文件相同的方式在相同路径被创建。如果Python 没有写入当前路径的权限,.pyc 文件就不会被创建。

from...import... 语句

如果你想要直接输入argv 变量到你的程序中(避免在每次使用它时打sys.),那么你可以使用from sys import argv 语句。如果你想要输入所有sys 模块使用的名字,那么你可以使用from sys import * 语句。这对于所有模块都适用。

一般说来,应该避免使用from..import 而使用import 语句,因为这样可以使你的程序更加易读,也可以避免名称的冲突。

模块的name

每个模块都有一个名称,在模块中可以通过语句来找出模块的名称。这在一个场合特别有用—— 就如前面所提到的,当一个模块被第一次输入的时候,这个模块的主块将被运行。假如我们只想在程序本身被使用的时候运行主块,而在它被别的模块输入的时候不运行主块,我们该怎么做呢?这可以通过模块的name 属性完成。

if __name__ == '__main__':
    print('This program is being run by itself')
else:
    print('I am being imported from another module')

每个Python 模块都有它的name,如果它是’main’,这说明这个模块被用户单独运行,我们可以进行相应的恰当操作。

创建自己的模块

创建你自己的模块是十分简单的,你一直在这样做!每个Python 程序也是一个模块。你已经确保它具有.py 扩展名了。

def sayhi():
    print('Hi, this is mymodule speaking.')

 __version__ = '0.1'

注意如果已经在导入mymodule 的模块中申明了一个version 的名字,这就会有冲突。这也是有可能的,因为从实际情况来看,每个模块会用这个名字来申明它的版本。因此,推荐选择使用import 语句,虽然会导致程序稍微有点冗长。

包是模块的文件夹,有一个特殊的__init__.py 文件,用来表明这个文件夹是特殊的因为其包含有Python 模块。