3.3.1 基本语法
在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