函数
函数是可重复使用的程序片段:它允许你为 某个代码块 命名,允许通过这一特殊的名字在你程序的任何地方来运行代码块,并可重复使用。这就是所谓的“调用”函数(calling)。(我们已经使用过很多内置函数,比如len和range)
函数可以通过关键字def来定义。这一关键字后面跟一个函数的标识符名称,再跟一对括号,括号内可以包括一些变量的名称,再以冒号结尾,结束这一行;随后的语句块是函数的一部分。
def say_hello(): #下面这一代码块属于这一函数 print('hello world') say_hello() #调用函数 say_hello() #再次调用函数
输出为:
hello world hello world
这个函数不使用参数,因此在括号里面没有声明变量
函数参数
def print_max(a, b): if a > b: print(a, "is maximum") elif a == b: print(a, "is equal to", b) else: print(b, "is maxmum")
print_max(3, 4) 4 is maximum
x = 3 y = 8 print_max(x, y) 8 is maximum
函数可以获取参数,参数由你来提供,借此函数便可以来利用这些参数做一些事情。
这些参数和变量类似:这些变量的值在我们调用函数的时候已经被定义,且在函数运行时均已赋值完成
函数的参数在用以定义函数的( )中指定,用逗号隔开; 当我们调用函数时,需要以同样的形式提供所需的值——注意,在定义函数时给定的参数名称叫做“形参”(parameters)(如上面例子中的a和b; 在你调用函数的时候你所提供给函数的括号里面的值叫做“实参”(arguments)(如上例中的3,4; x, y)
上例工作方式:
将函数命名为print_max并且提供两个形参,分别为a和b; 第一次调用函数时,直接以实参的形式向函数提供两个数字,3和4; 第二次调用函数时,将变量(x,y)作为实参提供给函数,使得实参x,y的值被赋给了形参a,b。
局部变量
x = 50 def func(x): print('x is', x) x = 2 print('changed local x to', x) func(x) print('out of the func, x is still', x)
输出为:
x is 50 changed local x to 2 out of the func, x is still 50
上例工作方式:
在第一次打印x时,使用的是函数声明之上,主代码块中的声明的x这一实参的值;第二次打印x时,x已经被赋值为2,但是这一实参是这一函数的局部变量——我们在改变函数中x的值的时候,外部主代码块中的x的值是不受影响的;因此最后一句print依然打印出主代码块中x的值。
当你在一个函数的定义中声明变量时,它们不会以任何形式和函数代码块之外的、具有相同名称的变量产生关系——因为函数中的变量名只存在于函数这一局部(local),这被称为函数的作用域(scope)。所有函数的作用域是它们被定义的块,从它们名字的定义点开始。
global语句
x = 50 def func(): global x print('now x is", x) x = 2 print('changed global x to', x) func() print('now the value of x is', x)
输出为:
now x is 50 changed global x to 2 now the value of x is 2
上例工作方式:
global语句声明x是一个全局变量——因此在函数中给x赋值为2时,将会影响到主代码中x的值。
你可以在同一global语句中指定不止一个全局变量:global x, y , z
如果你想给一个程序顶层的变量赋值(也即是这一变量不存在于任何作用域中,无论是函数还是类),那么你必须告诉Python这一变量不是局部的,而是全局的(global)。
默认参数值
对于一些函数来说,你可能希望一些参数可选并且使用默认的值,以避免用户不想提供值的情况。 你可以通过函数定义时附加一个赋值运算符(=)来为参数指定一个默认值。注意默认值是常数(constant),确切地说,默认参数值是不可变的。
def say(message, times = 1): print(message * times) say('hello ') say('world ', 5)
输出为:
hello world world world world world
上例工作方式:
say函数用以按照给定的次数打印一串字符串。如果用户没有提供一个数值,那么则按照默认设置,只打印一次,这通过给参数times设定默认参数值1来实现。
第一次调用say函数时,用户只提供了字符串,因此字符串只打印一次。第二次调用时,既提供了字符串,又提供了参数5,声明用户希望打印5次message。
注意:只有位于参数列表末尾的参数才能被赋予默认参数值
关键字参数(keyword arguments)
如果你有一些具有许多参数的函数,而你又只希望对其中的一些进行指定,那么你可以通过命名它们来给参数赋值 --这就是关键字参数(keyword arguments)--我们使用命名,而非位置,来指定函数中的参数。
这种做法有两大有点:其一是,我们不需要考虑参数的顺序,函数的使用会更容易;其二是,我们可以只对那些我们希望赋值的参数赋值,只要其他参数都具有默认参数值。
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)
输出为:
a is 3 and b is 7 and c is 10
a is 25 and b is 5 and c is 24
a is 100 and b is 5 and c is 50
工作方式:
名为func的函数有一个没有默认值的参数,后边两个参数有默认值。
第一次调用函数func时,func(3, 7)使得a获得了3的值,b获得了7的值,而c获得默认参数值10。
第二次调用函数func时,func(25, c=24),由于位置,a首先获得25的值;由于命名(既关键字参数指定),c获得24的值。b获得默认值5。
第三次调用函数时,全部用关键字参数来指定值。
可变参数
如果你想让你定义的函数里有任意数量的变量(即是参数数量是可以改变的),可以通过使用星号来实现。
当我们声明一个诸如*param的星号参数时,从此处开始到结束所有的位置参数(positional arguments)都将被收集并汇集成一个名为param的元组(tuple)
当我们声明一个诸如**param的双星号参数时,从此处开始到结束所有的关键字参数(keyword arguments)都将被收集并汇集成一个称为param的字典(dictionary)
后续章节会继续介绍元组和字典。
def total(a = 5, *numbers, **phonebook): print('a', a) #遍历元组中所有项目 for single_item in numbers: print('single_item', single_item) 遍历字典中所有项目 for first_part, second_part in phonebook.items(): print(first_part, second_part) print(total(10, 1, 2, 3, jack = 1123, john = 2231, inge = 1560))
输出为:
a 10
single_item 1
single_item 2
single_item 3
jack 1123
john 2231
inge 1560
return语句
return用于从函数中返回,也就是中断函数
def maximum(x,y): if x > y: return x elif x == y; return 'the numbers are euqal' else: return y print(2,3)
输出为:
3
注意,如果return语句没有搭配任何一个值则返回none。 none在py中是一个特殊类型,代表“虚无”,用于指示一个变量没有值,如果有值,值便是none(虚无)。
每个函数都在其末尾隐含了一句return None,除非你写了自己的return语句。
DocStrings:Py的文档字符串
我们可以通过一个函数来获取文档:
def print_max(x, y): '''打印这两个数值中的最大值 这两个数都应该是整数''' #将x和y转化为整数类型 x = int(x) y = int(y) if x > y: print(x) elif x == y: print('equal') else: print(y) print_max(2,3) print(print_max.__doc__)
输出为:
3
打印这两个数值中的最大值
这两个数都应该是整数
函数的第一逻辑行中的字符串是该函数的“文档字符串(DocStrings)”,文档字符串不仅适用于函数,也适用于后边章节提到的模块(modules)和类(class);
该文档字符串约定的是一串多行字符,第一行以某大写字母开始,以句号结束;第二行为空行;第三行开始是任何详细的解释说明。强烈建议在所有重要功能的所有文档字符串都遵守这一约定。
我们通过使用函数的doc属性来获取函数的文档字符串。
强烈推荐给所有重要函数配备文档字符串