本文介绍了抽象(函数)的概念,将详细介绍参数(parameter)和作用域(scope)的概念,以及递归(Recursion)的概念及其在程序中的用途。
1.函数概念
1.1 创建函数
def fib(num):
fibs = [0,1]
for i in range(num):
fibs.append(fibs[-2]+fibs[-1])
if i==num-1:
print fibs
fib(8)
1.2 文档化函数
文档字符串:在函数的开头写下字符串,它就会作为函数的一部分进行存储。
>>> def square(x):
>>> 'Calculates the square of the number x.'
>>> return x*x
>>> square(2)
4
>>> square.__doc__
Calculates the square of the number x.
2 参数
函数中有两类参数:位置参数和关键字参数。
2.1 位置参数
调用函数时根据函数定义的参数位置来传递参数。
# 两个参数的顺序必须一一对应,且少一个参数都不可以
def hello_1(greeting,name):
print '%s,%s!'% (greeting,name)
hello_1('hello','world')
def hello_2(name,greeting):
print '%s,%s!'%(name,greeting)
hello_2('hello','world')
2.2 关键字参数
用于函数调用,通过“键-值”形式加以指定。可以让函数更加清晰、容易使用,同时也清除了参数的顺序需求。
>>> hello_1(greeting= 'hello',name = 'world')
hello,world!
>>> hello_1(name= 'hello',greeting = 'world')
world,hello!
总结:有位置参数时,位置参数必须在关键字参数的前面,但关键字参数之间不存在先后顺序的
2.3 默认参数
用于定义函数,为参数提供默认值,调用函数时可传可不传该默认参数的值(注意:所有位置参数必须出现在默认参数前,包括函数定义和调用)
# 正确的默认参数定义方式--> 位置参数在前,默认参数在后
def hello_4(name,greeting='hello',punctuation='!'):
print '%s,%s%s' % (greeting,name,punctuation)
hello_4('Candy','HELLO','.')
输出如下:
HELLO,Candy.
2.4 可变参数
定义函数时,有时候我们不确定调用的时候会传递多少个参数(不传参也可以)。此时,可用包裹(packing)位置参数,或者包裹关键字参数,来进行参数传递,会显得非常方便。
1.包裹位置参数
我们传进的所有参数都会被args变量收集,它会根据传进参数的位置合并为一个元组(tuple),args是元组类型,这就是包裹位置传递。
def func(*args):
....
# func()
# func(a)
# func(a, b, c)
2.包裹关键值参数
def func(**kargs):
....
# func(a=1)
# func(a=1, b=2, c=3)
kargs是一个字典(dict),收集所有关键字参数
2.5 解包裹参数
和*,也可以在函数调用的时候使用,称之为解包裹(unpacking)
1、在传递元组时,让元组的每一个元素对应一个位置参数
使用*号运算符是在调用而不是定义时使用:
Demo1:
def add(x,y):
return x+y
params =(1,2)
add (*params)
Demo2:
def print_hello(name, sex):
print name, sex
# args = ('tanggu', '男')
# print_hello(*args)
# tanggu 男
2、在传递词典字典时,让词典的每个键值对作为一个关键字参数传递给函数
def print_hello(name, sex):
print name, sex
# args = ('tanggu', '男')
# print_hello(*args)
# tanggu 男
2.6 位置参数、默认参数、可变参数的混合使用
基本原则是:先位置参数,默认参数,包裹位置,包裹关键字(定义和调用都应遵循)
典型应用如下:
def func(name, age, sex=1, *args, **kargs):
print name, age, sex, args, kargs
# func('tanggu', 25, 2, 'music', 'sport', class=2)
# tanggu 25 1 ('music', 'sport') {'class'=2}
3.作用域(命名空间)
变量存储在作用域(也叫命名空间)中,Python中有两类主要的作用域-全局作用域和局部作用域,学过C语言的同学这点非常好理解。
>>> def foo(): x=42
>>> x=1
>>> foo()
>>> x
1
>>> def output(x):print x
>>> x=1
>>> y=2
>>> output(y)
2
重绑定全局变量
>>> x=1
>>> def change_global():
>>> global x
>>> x = x +1
>>> change_global()
>>> x
2
4.递归
函数调用本身-递归。
4.1 阶乘和幂
#阶乘
def fac(n):
if n==0:
return 1;
else:
return n*fac(n-1)
print fac(3)
#幂
4.2 二分查找
5.函数式编程
1.lambda函数
lambda函数也叫匿名函数,即,函数没有具体的名称,而用def创建的方法是有名称的。
1.无参数
如果没有参数,则lambda冒号前面就没有。
#利用def
def foo():return 'beginman' #Python中单行参数可以和标题写在一行
#用lambda函数
bar = lambda:'beginman'
print bar() #beginman
#或者直接使用
print lambda:'beginman'
2.有参数
lambda语句中,冒号前是参数,可以有多个,用逗号隔开,冒号右边是返回值。
# 利用def定义
def add(x,y):return x+y
# 利用lambda定义
add2 = lambda x,y:x+y
print add2(1,2) #3
Python有一些进行函数型编程的机制。包括lambda表达式以及map、filter和reduce函数。
2.filter()函数
filter()函数可以对序列做过滤处理,就是说可以使用一个自定的函数过滤一个序列,把序列的每一项传到自定义的过滤函数里处理,并返回结果做过滤。最终一次性返回过滤后的结果。
>>> def is_odd(x):
>>> return x % 2 == 1
>>> filter(is_odd, [1, 4, 6, 7, 9, 12, 17])
[1, 7, 9, 17]
>>> import math
>>> def is_sqr(x):
>>> return math.sqrt(x) % 1 == 0
>>> print filter(is_sqr, range(1, 101))
结果:
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
3.map()函数
格式:
map( func, seq1[, seq2…] )
map()是 Python 内置的高阶函数,它接收一个函数 f 和一个 list,并通过把函数 f 依次作用在 list 的每个元素上,得到一个新的 list 并返回。
>>> map(str,range(10))
['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
Python函数式编程之map使用(多个seq)
print map( lambda x, y: ( x * y, x + y), [1, 2, 3], [4, 5, 6] ) # [(4, 5), (10, 7), (18, 9)]
Python函数式编程之map使用(func为None)
#函数为None
# 将多个列表相同位置的元素归并到一个元组,在现在已经有了专用的函数zip()了
print map( None, [1, 2, 3], [4, 5, 6] ) # [(1, 4), (2, 5), (3, 6)]
print zip( [1, 2, 3], [4, 5, 6] ) # [(1, 4), (2, 5), (3, 6)]
map()函数是python内置的高阶函数,对传入的list的每一个元素进行映射,返回一个新的映射之后的list
4.reduce()函数
格式:
reduce( func, seq[, init] )
reduce函数即为化简,它是这样一个过程:每次迭代,将上一次的迭代结果(第一次时为init的元素,如没有init则为seq的第一个元素)与下一个元素一同执行一个二元的func函数。在reduce函数中,init是可选的,如果使用,则作为第一次迭代的第一个元素使用。
简单来说,可以用这样一个形象化的式子来说明:
reduce( func, [1, 2,3] ) = func( func(1, 2), 3)
Python函数式编程之reduce使用
n = 5
print reduce(lambda x, y: x * y, range(1, n + 1)) # 120
那么,如果我们希望得到2倍阶乘的值呢?这就可以用到init这个可选参数了。
m = 2
n = 5
print reduce( lambda x, y: x * y, range( 1, n + 1 ), m ) # 240
最好的将map()和reduce()的例子:
http://www.pythoner.com/46.html