在Python中,定义函数的语法如下:
1 def 函数名([参数列表]): 2 ‘‘‘注释‘‘‘ 3 函数体
在Python中使用def关键字来定义函数,然后是一个空格和函数名称,接下来是一对圆括号,在圆括号内是形式参数列表,如果有多个参数则使用逗号分隔开,圆括号之后是一个冒号和换行,最后是必要的注释和函数体代码。定义函数时需要注意的问题:
(1)函数参数不需要声明其类型,也不需要指定函数返回值类型;
(2)即使该函数不需要接受任何参数,也必须保留一对空的圆括号;
(3)括号后面的冒号必不可少;
(4)函数体相对于def关键字必须保持一定的空格缩进。
小提示:注释是软件开发人员的笔记,对代码测试人员和维护人员来说也非常重要。在Python中有两种注释方式:符号 # 后面的内容表示注释,不属于任何语句的一对三引号也表示注释。
小技巧:不少程序员是编写完代码之后再添加适当的注释,我恰恰相反。我一般都是先写注释,以注释的形式用自然语言把程序思路描述出来,然后再把这些注释“翻译”成程序语言,正所谓“代码未动,注释先行”。
下面的函数用来计算斐波那契数列中小于参数 n 的所有值:
1 def fib(n): #定义函数,括号里的n是形式参数 2 a , b = 1 , 1 3 while a < n: 4 if b < n: 5 a , b = b , a + b 6 else: 7 print(a) 8 break 9 10 fib(1000) #调用函数,括号里的1000是实参 11 12 #函数执行结果:987
在定义函数时,开头部分的注释不是必须的,但是如果为函数的定义加上一段注释的话,可以为用户提供友好的提示和使用帮助。例如,把上面生成斐波那契的函数定义加上如下注释:‘‘‘accept an integer n.
return the numbers less than n in Fibonacci sequence.‘‘‘
如此一来,可以使用内置函数help()来查看函数的使用帮助,并且在调用该函数时输入左侧圆括号之后,立刻就会得到该函数的使用说明。
1 print(fib.__doc__) 2 print(‘-‘ * 30) 3 help(fib) 4 5 accept an integer n. 6 7 return the numbers less than n in Fibonacci sequence. 8 ------------------------------ 9 Help on function fib in module __main__: 10 11 fib(n) 12 accept an integer n. 13 14 return the numbers less than n in Fibonacci sequence.
建议:如果代码本身不能提供非常好的可读性,那么最好加上适当的注释来说明,要不然,自己写的代码自己都看不懂了。很多程序员都有过这样的经历。
在Python中,定义函数时不需要声明函数返回值的类型,而是使用return语句结束函数的执行的同时返回任意类型的值,函数返回值类型与return语句返回表达式的类型一致。无论return语句出现在函数的任何位置,一旦得到执行将直接结束函数的执行。如果函数没有return语句或者执行了不返回任何值的return语句,Python将认为该函数以return None结束,即返回空值。
小提示:作为使用者,在调用函数时,一定要注意函数有没有返回值,以及是否会对函数实参的值进行修改。例如,前面介绍的列表方法sort()属于原地操作,没有返回值,而内置函数sorted()则返回排序后的序列,并不对原列表做任何修改。
1 >>> a = [1,2,3,4,9,5,7] 2 >>> print(sorted(a)) 3 [1, 2, 3, 4, 5, 7, 9] 4 >>> 5 >>> a 6 [1, 2, 3, 4, 9, 5, 7] #原列表内容没变 7 >>> 8 >>> print(a.sort()) #列表对象的sort()方法没有返回值 9 None 10 >>> 11 >>> print(a) 12 [1, 2, 3, 4, 5, 7, 9] 13 >>>
扩展知识:函数属于可调用对象。由于构造函数的存在,类也是可调用的。另外,任何包含__call__()方法的类的对象都是可调用的。例如,下面的代码演示了函数嵌套定义情况:
1 def linear(a,b): 2 def result(x): #在Python中,函数是可以使用嵌套定义的 3 return a * x + b 4 return result 5 6 #下面的代码演示了可调用对象类的定义: 7 8 class linear: 9 def __init__(self,a,b): 10 self.a = a 11 self.b = b 12 13 def __call__(self,x): 14 return self.a * x + self.b 15 16 #使用上面的嵌套函数和类这两种方式中任何一个,都可以通过以下的方式来定义一个可调用对象: 17 18 taxes = linear(0.3,2) 19 20 #然后通过下面的方式来调用该对象: 21 22 taxes(5) 23 24 #下面的代码完整地演示了嵌套函数定义与使用的方法,有效利用了用户名检查功能的代码,关于面向对象编程的知识请参考第4章。 25 26 def check_permission(func): 27 def wrapper(*args, **kwargs): 28 if kwargs.get(‘username‘) != ‘admin‘: 29 raise Exception(‘Sorry. You are not allowed. ‘) 30 return func(*args,**kwargs) 31 return wrapper 32 33 class ReadWriteFile(): 34 35 @check_permission 36 def read(self,username,filename): 37 return open(filename,‘r‘).read() 38 39 def write(self,username,filename,content): 40 open(filename,‘a+‘).write(content) 41 42 #把函数check_permission作为普通函数使用 43 write = check_permission(write) 44 45 if __name__ == ‘__main__‘: 46 t = ReadWriteFile() 47 print(‘Originally‘) 48 print(t.read(username=‘admin‘,filename=r‘d:\sample.txt‘)) 49 print(‘Now,try to write to a file...‘) 50 t.write(username=‘admin‘,filename=r‘d:\sample.txt‘,content=‘\nhello world‘) 51 print(‘After calling to write...‘) 52 print(t.read(username=‘admin‘,filename=r‘d:\sample.txt‘)) 53 54 55 # Originally 56 57 # Now,try to write to a file... 58 # After calling to write... 59 60 # hello world