Python函数学习
这一节还没有涉及到面向对象, 主要关注如何定义和使用python的函数. 下文以简单问答形式呈现.
1. 函数要有一个返回值, 该如何写?
这个很简单, return ret_value
2. 函数要返回多个返回值, 该如何写?
python处理这个也很简单, 格式可以为:
return ret_value1,ret_value2 或者为
return (ret_value1,ret_value2) 这两种写法的效果是一样的, 都是返回一个tuple
3. 如果一个函数没有return语句, 那么函数有没有返回值?
答案是, 有返回值, 返回值是一个特殊的None值.
4. python函数有没有overload?
在C#等语言中, 你可以定义一系列同名函数, 这些函数的参数个数或者参数类型可能不同, 但只要这些函数的返回值一样, 就是允许的,这叫做overload.
但在python中, 我们不可以有2个同名的函数的, 即使函数的参数个数或类型不同. 但python支持默认参数, 所以overload的意义也就并不大了.
5. 推荐的函数体的注释形式
如果函数头后紧跟一个合法的string(不管这个字符串是以', 还是", 还是'''括起来的), python都认为这个字符串是函数的docstrings. 在这里讲一下, 推荐的docstrings写法, 每个函数都应该在函数头的下一行, 写docstrings, 除非这个函数特别简单. docstrings的是由'''(三个')括起来, 第一个是函数的整体功能介绍, 然后空一行, 第3行是详细的说明. docstrings不同于一般的注释, 我们甚至可以通过print(myFunc.__doc__)来输出docstrings.
6. 关键字参数
一般地, 我们给形参传值的时候, 都是按照形参的次序, 依次将实参传过去的. python还支持类似于给形参赋值的传参方式, 即关键字传参方式. 甚至, 我们可以在调用一个函数时,混用两种传参方式(python有自己的规则来将形参和实参对应起来). 我个人不推荐这种混用方式, 程序的可读性将变得非常差.
def greetEveryone5(greet, person):
print (greet+person)
greetEveryone5("hello ","Robert") #这是一般传参方式
greetEveryone5(greet="hello ", person="Jason") #这是关键字传参方式
greetEveryone5(person="Jason", greet="hello ")#这是关键字传参方式, 注意这时, 实参的位置和函数定义可以不同
7. 元组参数(*arg类型的参数)
C#中有一个开放数组的概念, 即函数数组型形参如果以params 修饰符声明, 我们就可以将任意个数的参数传给函数. Python也有类似的东西, 即 *arg类型的参数, 我们可以将任意多个实参传给一个*arg形参, 在函数中, 该arg参数其实是一个tuple, 注意为*arg参数传值时, 不能再画蛇添足地加(), 因为python会自动将函数最后的几个参数组成一个tuple(这句话不严密, 应该是函数最后几个合适的参数组成一个tuple, 参见下面小节 函数参数调用的顺序).
比如
def greetEveryone(greet, *people):
#print(type(people)) #output is:<type 'tuple'>
for item in people:
print (greet+item)
greetEveryone("Hello ", "Jason","David","Harry") #这行是正确的传值方式
greetEveryone("Hello ", ("Jason","David","Harry")) #这行是错误的传值方式, 这样传值, 在函数内部, arg的第一个item是一个tuple, 其值为("Jason","David","Harry")
8. 字典参数(**arg类型的参数)
我们可以将任意多的key value pair, 传给**arg参数, 在函数内部arg其实就是一个dict, 注意传值时的写法, 必须是key1=value1, key2=value2, .... , 这些key一定是str类型, 需要注意的是key, 是不能用""括起来, 另外不能用{}将这些key=value pair括起来.
def greetEveryone4(period, **greetPeople):
#print (type(greetPeople)) #<type 'dict'>
for item in greetPeople.keys():
#print (type(item)) #output is:<type 'str'>
print(period+", "+item+" "+greetPeople[item])
greetEveryone4('morning', {"Boss" :"drothy", "Clerk" :"Jason"})#这行是错误的传值方式
greetEveryone4('morning', "Boss" :"drothy", "Clerk" :"Jason")#这行是错误的传值方式
greetEveryone4('morning', "Boss" ="drothy", "Clerk" ="Jason")#这行是错误的传值方式
greetEveryone4('morning', Boss ="drothy", Clerk ="Jason")#这行是正确的传值方式
9. 函数参数调用的顺序
字典参数的写法和关键字参数一摸一样, 那么python是如何区分哪个是哪个呢? 答案是python有一套规则(下面内容出自 <从C#到Python —— 3 函数及函数编程> http://www.cnblogs.com/yanxy/archive/2010/03/28/c2p_3.html)
调用Python函数时,参数书写的顺序分别为:非关键字参数,关键字参数,元组参数,字典参数。请记住以下几点规则:
* 通过位置分配非关键字参数
* 通过匹配变量名分配关键字参数
* 其他额外的非关键字参数分配到*arg元组中
* 其他额外的关键字参数分配到**arg的字典中
* 用默认值分配给在调用时未得到分配的参数
一般说来,实参表中非关键字参数在前,关键字参数在后,关键字名字必须是形参名字。形参有没有缺省值都可以用关键字参数的形式调用。每一形参至多只能对应一个实参,因此,已经由位置参数传入值的形参就不能在同一调用中再作为关键字参数。另外一个函数定义中, 只能使用一个*arg和**arg参数