# Python教程-6. 函数

## Functions

Posted by xuepro on November 15, 2017

## 函数Functions

def 函数名( 参数 ):
"函数_文档字符串"
函数体（语句块）
return 表达式]


>>> def fib(n):    # write Fibonacci series up to n
...     """Print a Fibonacci series up to n."""
...     a, b = 0, 1
...     while a < n:
...         print(a, end=' ')
...         a, b = b, a+b
...     print()
...
>>> # 现在我们可以调用刚刚定义的函数fib,传递一个实际参数2000给被调用函数的参数n:
... fib(2000)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597


>>> fib
<function fib at 10042ed0>
>>> f = fib
>>> f(100)
0 1 1 2 3 5 8 13 21 34 55 89


>>> fib(0)
>>> print(fib(0))
None


>>> def fib2(n):  # return Fibonacci series up to n
...     """Return a list containing the Fibonacci series up to n."""
...     result = []
...     a, b = 0, 1
...     while a < n:
...         result.append(a)    # see below
...         a, b = b, a+b
...     return result
...
>>> f100 = fib2(100)    # call it
>>> f100                # write the result
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]


• append()是列表对象result的一个方法（所谓的“方法”就是属于一个对象的函数），用于在列表后面添加元素。可以通过”对象A.方法名m”来调用一个”对象A”的”方法名m”。

• 方法体的开头可以有用三引号”"”括起来的“函数文档串”，用于说明这个函数的目的和作用等。可以用print等内在函数得到这个函数的文档串。例如：

>>> def my_function():
...     """Do nothing, but document it.
...
...     No, really, it doesn't do anything.
...     """
...     pass
...
>>> print(my_function.__doc__)
Do nothing, but document it.

No, really, it doesn't do anything.


 x = 0
y = 0
def incr(x):
y = x + 1
return y
incr(5)
print (x, y)        # print是系统定义的函数叫做内在函数


0 0


def incr2(x):
global y
y =  x + 1
return y
incr2(5)
print x, y


0 6


## 默认参数:

def enroll(name, gender, age=6, city='Beijing'):
print 'name:', name
print 'gender:', gender
print 'age:', age
print 'city:', city
enroll('Sarah', 'F')
enroll('Scott', 'F')
enroll('Jone', 'T')
enroll('Bob', 'M', 7)
enroll('Adam', 'M', city='Tianjin')


i = 5
def f(arg=i):
print(arg)

i = 6
f()   # 将输出: 5


def f(a, L=[]):
L.append(a)
return L

print(f(1))
print(f(2))
print(f(3))


[1]
[1, 2]
[1, 2, 3]


def f(a, L=None):
if L is None:
L = []
L.append(a)
return L


## 关键字参数:

def parrot(voltage, state='a stiff', action='voom', type='Norwegian Blue'):
print("-- This parrot wouldn't", action, end=' ')
print("if you put", voltage, "volts through it.")
print("-- Lovely plumage, the", type)
print("-- It's", state, "!")


parrot(1000)                                          # 1 个 位置参数
parrot(voltage=1000)                                  # 1 个关键字参数
parrot(voltage=1000000, action='VOOOOOM')             # 2 个关键字参数
parrot(action='VOOOOOM', voltage=1000000)             # 2 个关键字参数
parrot('a million', 'bereft of life', 'jump')         # 3 个位置参数
parrot('a thousand', state='pushing up the daisies')  # 1 个 位置参数, 1 个关键字参数


parrot()                     # 缺少必须参数
parrot(voltage=5.0, 'dead')  # “关键字参数”后不能有“非关键字参数”
parrot(110, voltage=220)     # 同意参数提供了2个值
parrot(actor='John Cleese')  # 未知的关键字参数


“关键字参数”必须在”位置参数”后面。所有“关键字参数”的“关键字”必须匹配函数定义中的参数名字（包括必须参数）。不能给一个参数提供多个值。再如：

>>> def function(a):
...     pass
...
>>> function(0, a=0)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: function() got multiple values for keyword argument 'a'


## 可变参数和字典参数

 参数名前有2个星号的参数 “ **name ” 表示可以接受一个字典参数。

参数名前有1个星号的参数 “ *name ” 表示可以接受一个tuple参数。

注意：*name 参数必须出现在 **name 参数前.


>>> def concat(*args, sep="/"):
...     return sep.join(args)
...
>>> concat("earth", "mars", "venus")
'earth/mars/venus'
>>> concat("earth", "mars", "venus", sep=".")
'earth.mars.venus'


def cheeseshop(kind, *arguments, **keywords):
print("-- Do you have any", kind, "?")
print("-- I'm sorry, we're all out of", kind)
for arg in arguments:
print(arg)
print("-" * 40)
for kw in keywords:
print(kw, ":", keywords[kw])


 cheeseshop("Limburger", "It's very runny, sir.",
"It's really very, VERY runny, sir.",
shopkeeper="Michael Palin",
client="John Cleese",
sketch="Cheese Shop Sketch")


-- Do you have any Limburger ?
-- I'm sorry, we're all out of Limburger
It's very runny, sir.
It's really very, VERY runny, sir.
----------------------------------------
shopkeeper : Michael Palin
client : John Cleese
sketch : Cheese Shop Sketch


## 解封参数列表

>>> args = [3, 6]
>>> list(range(*args))            # call with arguments unpacked from a list
[3, 4, 5]


>>> def parrot(voltage, state='a stiff', action='voom'):
...     print("-- This parrot wouldn't", action, end=' ')
...     print("if you put", voltage, "volts through it.", end=' ')
...     print("E's", state, "!")
...
>>> d = {"voltage": "four million", "state": "bleedin' demised", "action": "VOOM"}
>>> parrot(**d)
-- This parrot wouldn't VOOM if you put four million volts through it. E's bleedin' demised !


## Lambda Expressions （Lambda表达式）

lambda a, b: a+b


lambda表达式的格式

 func = lambda 参数: 调用参数的表达式


def add(x, y):
return x + y
print add(1,2)


add=lambda x,y : x + y    ## 将lambda表达式匿名函数）赋给变量add。
print add(1,2)            ## 通过add调用lambda表达式（匿名函数）


>>> def make_incrementor(n):
...     return lambda x: x + n
...
>>> f = make_incrementor(42)
>>> f(0)
42
>>> f(1)
43


list = [1,3,4,6,7,9]
newlist = [ ]
for i in list:
newlist.append(i*i)
print(newlist) #输出： [1, 9, 16, 36, 49, 81]


sqr = lambda a: a*a
print ( map(sqr, [1,3,4,6,7,9]) )  #输出： [1, 9, 16, 36, 49, 81]


Map函数的使用格式如下： newlist = Map(func, list)，将list中每个元素都进行一个func函数的计算，生成一个新的list 这种一个函数可以接受另外一个函数作为参数的编程方式叫作“函数式编程”。

def square(x):
return x*x
print( map(sqr, [1,3,4,6,7,9]) )   #输出： [1, 9, 16, 36, 49, 81]


      result = reduce(func, 容器对象)


result = reduce(func, [a1, a2, a3…]) 对列表list [a1, a2, a3…]中元素，左到右进行func计算，先计算func(a1, a2), 在计算func(func(a1, a2), a3)…。

# reduce(f, [x1, x2, x3, x4])，其效果就是：f(f(f(x1, x2), x3), x4)
from functools import reduce
def add(x, y):
return x + y
print ( reduce(add, [47,11,42,13]) )   #输出：113

# We can also use lambda expression as the first parameter
add_ = lambda a,b: a+b
print ( reduce(add_,[47,11,42,13]) )   #输出：113

#
print(  reduce(lambda a,b: a+b,[47,11,42,13]) )  #输出：113


## 递归函数：调用自身的函数。

def fact(n):
if n==1:  ## 如果n等于1，就直接返回值1
return 1
return n * fact(n - 1)
fact(5)             # 输出： 120


fact(5)的计算过程

===> fact(5)
===> 5 * fact(4)
===> 5 * (4 * fact(3))
===> 5 * (4 * (3 * fact(2)))
===> 5 * (4 * (3 * (2 * fact(1))))
===> 5 * (4 * (3 * (2 * 1)))
===> 5 * (4 * (3 * 2))
===> 5 * (4 * 6)
===> 5 * 24
===> 120


def quicksort(arr):
if len(arr) <= 1:                          ## 如果 输入序列长度小于等于1，直接返回
return arr
pivot = arr[len(arr) // 2]                  ##任意选择一个如中间元素作为基准元素，将原序列一分为二
left = [x for x in arr if x < pivot]        ## left是小于基准元素组成的子序列
middle = [x for x in arr if x == pivot]     ## middle是等于基准元素组成的子序列
right = [x for x in arr if x > pivot]       ##  right是大于基准元素组成的子序列
return quicksort(left) + middle + quicksort(right)  ##对left、right重复上述过程

print(quicksort([3,6,8,10,1,2,1]))
# Prints "[1, 1, 2, 3, 6, 8, 10]"


Refer to:

https://docs.python.org/3/tutorial/controlflow.html