《Think Python 2e》学习精粹(三): 函数
函数(function) :一个有命名的、执行某个计算的语句序列(sequence of statements);
1、函数调用
函数调用(function call) 方式:函数名(表达式);
调用函数时括号里的表达式称为实参(argument) ;
函数“接受”(accept)实参(有的话)后返回(return)得到一个结果即返回值(return value );
>> > type ( 'Hello, World!' )
< class 'str' >
Python提供了能够将值从一种类型转换为另一种类型的内建函数;
函数 int 接受任意值,并在其能做到的情况下,将该值转换成一个整型数;
函数 float 可以将整型数和字符串转换为浮点数;
函数 str 可以将其实参转换成字符串;
>> > int ( 32.98 )
32
>> > int ( '32' )
32
>> > int ( '32.98' )
Traceback ( most recent call last) :
File "<stdin>" , line 1 , in < module>
ValueError: invalid literal for int ( ) with base 10 : '32.98'
>> > float ( 32 )
32.0
>> > float ( '32.98' )
32.98
>> > str ( 32.98 )
'32.98'
2、数学函数
数学模块(math) 提供了大部分常用的数学函数和变量;
在使用模块之前,需要通过 导入语句(import statement) 导入该模块;
导入语句生成一个模块对象(module object) ,在未导入时未生成模块对象;
>> > math
Traceback ( most recent call last) :
File "<stdin>" , line 1 , in < module>
NameError: name 'math' is not defined
>> > import math
>> > math
< module 'math' ( built- in ) >
模块对象包括了定义在模块内的所有函数和变量;
模块对象中的函数或者变量命名:模块的名字与函数名(变量名)组合而成, 并以点号分隔开来, 这种命名形式被称作点标记法(dot notation) ;
>> > import math
>> > math. pi
3.141592653589793
>> > math. sqrt( 2 )
1.4142135623730951
3、组合
编程语言的最有用特征之一,是能够将小块构建材料(building blocks)组合(compose) 在一起;
值可以是一个任意类型的表达式;
例外: 赋值语句的左侧必须是一个变量名;
>> > hours = 2
>> > minutes = hours * 60
>> > hours * 60 = minutes
File "<stdin>" , line 1
SyntaxError: cannot assign to operator
4、新建函数
函数定义(function definition) :指定新函数的名称、当函数被调用时执行的语句序列;
def 是表明从此行开始是函数定义的关键字;
函数名与变量名具有同样的规则;
函数名后面的括号中是实参(有的话),实参不止一个的话用逗号分隔;
函数定义的构成规定:
函数定义的第一行被称作函数头(header) , 其余部分被称作函数体(body) ;
函数头必须以冒号结尾,而函数体必须缩进(惯例四个空格);
函数体能包含任意条语句,但必须以空行结束;
新建函数调用与内建函数调用一致,包括被应用在另一个函数的内部;
def print_gsf ( ) :
print ( 'I am healthy.' )
print ( 'And I am happy.' )
def print_twice ( ) :
print_gsf( )
print_gsf( )
print_twice( )
PS C: \Users\Administrator> python D: \WorkSpace\thinkpython2e\print_twice. py
I am healthy.
And I am happy.
I am healthy.
And I am happy.
5、定义和使用
函数定义被执行后,创建函数对象;
函数定义内部的语句在函数被调用之前不会执行、不会产生输出;
函数定义必须在其第一次被调用之前执行,未定义先调用会报错,例如:NameError: name 'print_twice' is not defined
;
print_twice( )
def print_gsf ( ) :
print ( 'I am healthy.' )
print ( 'And I am happy.' )
def print_twice ( ) :
print_gsf( )
print_gsf( )
PS C: \Users\Administrator> python D: \WorkSpace\thinkpython2e\print_twice_1. py
Traceback ( most recent call last) :
File "D:\WorkSpace\thinkpython2e\print_twice_1.py" , line 1 , in < module>
print_twice( )
NameError: name 'print_twice' is not defined
6、执行流程
执行流程(flow of execution) : 语句执行的顺序;
执行流程总是从程序的第一条语句开始,自顶向下,每次执行一条语句;
函数定义不改变程序执行的流程,函数不被调用时内部的语句不会执行;
函数调用,执行流程不进入下一条语句,而是跳入函数体,开始执行函数定义里的语句,然后再回到它离开的位置;
7、形参和实参
实参 :调用函数时,(有时候)需要输入参数,输入的一个或者几个参数称为实参;
在函数调用时,实参被赋给函数定义时确定的函数形参(parameters) ;
组合规则适用于内建函数和自定义函数(programmer-defined functions)的实参;
在函数被调用之前,实参会先进行计算再赋给形参;
def print_gsf ( years_old) :
print ( years_old)
def print_twice ( ) :
print_gsf( 2020 - 1968 )
print_gsf( "I'm so young!" )
print_twice( )
PS C: \Users\Administrator> python D: \WorkSpace\thinkpython2e\print_yeas_old. py
52
I'm so young!
8、变量和形参都是局部的
函数定义时创建的变量是局部的(local) , 只在函数内部存在;
当函数调用结束时,变量被销毁,在函数外这个变量是未定义的;
9、堆栈图
堆栈图(stack diagram) : 用以说明每个变量的值、每个变量所属的函数并跟踪哪个变量能在哪儿用的图形;
每个函数用一个栈帧(frame) 表示;
一个栈帧就是一个线框,函数名在旁边,形参以及函数内部的变量则在里面;
栈帧排列成栈的形式,说明了哪个函数调用了哪个函数等信息;
__main__是一个表示最上层栈帧的特殊名字;
如果函数调用时发生错误,Python会打印出错函数的名字以及调用它的函数的名字, 以及调用后面这个函数的函数的名字,一直追溯到__main__为止,这个函数列表被称作回溯(traceback) ;
回溯中的函数顺序,与堆栈图中的函数顺序一致,出错时正在运行的那个函数则位于回溯信息的底部;
10、有返回值函数和无返回值函数
有返回值函数(fruitful functions) :会返回结果的函数;
无返回值函数(void functions) :执行一个动作但是不返回任何值的函数;
在交互模式下调用一个函数时,Python解释器会马上显示结果;
在脚本中,单单调用一个有返回值函数, 返回值就永远丢失;
将无返回值函数的结果赋给一个变量:
会得到特殊值 None ;
None 是一个自己有独立类型的特殊值;
>> > print ( type ( None ) )
< class 'NoneType' >
11、为什么写函数?
给一组语句命名;
消除重复的代码;
分解长程序;
重复使用;
12、调试
调试,是最重要的技能之一;
调试像是侦探工作:面对一些线索,推理出导致结果的进程(processes)和事件(events);
调试也像是一门实验科学:猜测出错的地方,修改程序,再试一次,直至程序正常运行 ;
在某种意义上,编程和调试是同一件事,编程是逐步调试一个程序,直到出现期待结果的过程;
应该从一个能正常运行(working) 的程序开始,每次只做一些小改动,并同步进行调试。