1.2.声明函数

      Python像其它编程语言一样也有函数,但是却没有像C++那样的头文件或者像Pascal那样的interface/implementation部分.当你需要一个函数时,只要像下面一样声明就可以了:

def approximate_size(size, a_kilobyte_is_1024_bytes=True):

     函数的开始是关键字def,紧跟着是函数名,然后是括号中的参数.参数之间用逗号分隔.

另外需要注意的是函数没有返回类型.Python函数不指定特定的返回类型,甚至不需要指定是否返回一个值.(实际上,每一个python函数都会返回一个值.如果执行了return语句,那么它会返回这个值,否则,它返回一个None.None是Python的null值.)

 注:在某些编程语言中,函数(那些有返回值的)以function开头,而子程序(那些没有返回值的)以sub开头.在Python中没有子程序的概念.每个都是函数,每个函数都有返回值(即使它是None),每个函数都以def开头. 

     函数approximate_size()有两个返回值--size和a_kilobyte_is_1024_bytes,但是每个都没有指定类型.在Python中,变量从不需要指定类型.Python会自己辨识类型并对其进行跟踪.

注:在java和其它强类型编程语言,你必须指定函数返回值和参数的类型.在Python中你不需要为任何东西指定数据类型.根据赋值时的值类型,python会自动跟踪值的类型. 

1.2.1.可选参数和定名参数(Optional and named arguments)

      Python允许函数参数有默认值.如果函数在调用时没有给该参数赋值,则该参数会被赋成默认值.更进一步,通过定名参数,可以以任意顺序来给参数赋值.

      让我们再重新审视一下approximate_size()的函数声明.

def approximate_size(size, a_kilobyte_is_1024_bytes=True):

第二个参数a_kilobyte_is_1024_bytes的默认值为True.这意味着该参数是可选的:你可以不给该参数赋值而调用函数,Python会为其赋值为True.

现在让我们来看下底部的脚本:

if __name__ == '__main__':
    print(approximate_size(1000000000000, False))    ①
    print(approximate_size(1000000000000))           ②

 1.这次函数调用有两个参数.在函数approximate_size中,a_kilobyte_is_1024_bytes会被赋值为False,因为你已经明确这样做了.

2.这次函数调用只有一个参数.但是这样没有问题,因为第二个参数是可选的.既然函数调用时没有特别指定,第二个参数会被赋值为默认值True,就像函数声明中所说的那样. 

你甚至可以通过参数名称将值传到函数中.

>>> from humansize import approximate_size
>>> approximate_size(4000, a_kilobyte_is_1024_bytes=False) ①
'4.0 KB'
>>> approximate_size(size=4000, a_kilobyte_is_1024_bytes=False) ②
'4.0 KB'
>>> approximate_size(a_kilobyte_is_1024_bytes=False, size=4000) ③
'4.0 KB'
>>> approximate_size(a_kilobyte_is_1024_bytes=False, 4000) ④
File "<stdin>", line 1
SyntaxError: non-keyword arg after keyword arg
>>> approximate_size(size=4000, False) ⑤
File "<stdin>", line 1
SyntaxError: non-keyword arg after keyword arg

1.这次调用将4000赋给第一个参数size,将False赋给一个名叫a_kilobyte_is_1024_bytes的参数.(这正好是第二个参数,不过没有关系,我们呆会儿将会再次看到这种用法.)

2.这次调用将4000赋给名叫size的参数,将False赋给名叫a_kilobyte_is_1024_bytes的参数.(这次定名参数的顺序正好与函数声明的参数顺序相同,不过仍然没有关系)

3.这次调用将False赋值给a_kilobyte_is_1024_bytes,将4000赋值给size.(看,我告诉过你参数顺序没有关系吧)

4.这次调用失败了,因为你在定名参数后面跟了一个非定名参数,这永远不可行.参数列表从左到右,如果你碰到了一个定名参数,那么它后面的参数必须都是定名参数.

5.这次调用也失败了,原因因上次一样.不管怎么说,你将4000赋给了一个名叫size的参数,所以"理所当然地"False会赋值给a_kilobyte_is_1024_bytes.但是这种方式在Python下可行不通.只要你碰到一个定名参数,它后面的所有参数都必须是定名参数.