标签:
第五天:抽象
1、 函数
检测函数是否可调用:callable
>>> import math
>>> y=math.sqrt
>>> callable(y)
True
>>> x=1
>>> callable(x)
False
注意:Python3.0不在支持callable,需要使用表达式hasattr(func,_call_call_)代替
创建函数:def functionname(params):
>>>def fibs(num):
... ‘Get fibonaqi sequnce! ‘
... result=[0,1]
... for i in range(num-2):
... result.append(result[-2]+result[-1])
... return result
...
>>>fibs(10)
[0, 1,1, 2, 3, 5, 8, 13, 21, 34]
用于def后面的‘Getfibonaqi sequnce! ‘添加文档字符串,相当于注释#,使用help()可以查询函数的文档字符串
help(fibs)
Help on function fibs in module __main__:
fibs(num)
Getfibonaqi sequnce!
...skipping...
Help on function fibs in module __main__:
fibs(num)
Getfibonaqi sequnce!
return后不加值,只表示函数的结束,而没有返回值,这样可以避免应该返回序列时,意外返回None
>>> def test():
... print ‘tanggao‘
... return
... print ‘tanggao isgood‘
...
>>> x=test()
tanggao
>>> print x
None
2、 参数对外部变量影响
函数内给参数赋值,不会改变外部变量的值,参数存储在局部作用域中
>>> def try_to_change(n):
... n=3
...
>>> t=4
>>> try_to_change(t)#虽然在函数内部重新赋值,但外部不变
>>> t
4
但是对于可改变的数据结构,如列表,参数的内部赋值会改变外部变量的值
内部参数与外部变量指向同一个列表,所以会被修改
若不想改变外部列表,可以传进一个副本
>>> def change(n):
... n[0]=‘tanggao‘
...
>>> names=[‘hello‘,‘world‘]
>>> change(names)
>>> names
[‘tanggao‘, ‘world‘]
>>> #采用普通方法进行模拟
...
>>> names=[‘hello‘,‘world‘]
>>> n=names
>>> n[0]=‘tanggao‘
>>> names
[‘tanggao‘, ‘world‘]
完整示例——存储名字,并能用名字、中间名或姓来查找联系人
若名字为‘MagusLie Hetland‘存储格式类似
data = {
‘first‘:{ ‘Magus‘: ‘Magus Lie Hetland‘},
‘middle‘:{‘Lie‘: ‘Magus Lie Hetland‘},
‘last‘:{‘Hetland‘: ‘Magus Lie Hetland‘}
}
注意insert(index,value)函数,在列表的索引位置插入值
1. >>> def init(data): #data作为存储表,初始化
2. data[‘first‘] = {}
3. data[‘middle‘] = {}
4. data[‘last‘] = {}
5.
6. >>> def store(data, full_name): #存储,将全名存储到表中
7. names = full_name.split() #将名字按空格(即first,middle,last)分开,返回列表,如‘Ma Li He‘返回[‘Ma‘, ‘Li‘, ‘He‘]
8. if len(names) == 2: names.insert(1, ‘‘)#若无中间名,则插入空来表示中间名[‘Mr‘, ‘Zha‘]返回[‘Mr‘, ‘‘, ‘Zha‘]
9. labels = ‘first‘, ‘middle‘, ‘last‘ #元组
10. for label, name in zip(labels, names): #元组与序列间也可使用zip
11. people = lookup(data, label, name)
12. if people:
13. people.append(full_name)
14. else:
15. data[label][name] = [full_name] #当键不存在时,自动添加键值对,
16. #但如果输出不存在键对应值,则报错
17.
18. >>> def lookup(data, label, name): #查找,根据label查找是name的中间人
19. return data[label].get(name)
20.
21.
22. >>> MyNames = {}
23. >>> init(MyNames)
24. >>> store(MyNames, ‘Magnus Lie Hetland‘)
25. >>> lookup(MyNames, ‘middle‘, ‘Lie‘)
26. [‘Magnus Lie Hetland‘]
27. >>> store(MyNames, ‘Robin Hood‘)
28. >>> store(MyNames, ‘Robin Locksley‘)
29. >>> lookup(MyNames, ‘first‘, ‘Robin‘)
30. [‘Robin Hood‘, ‘Robin Locksley‘]
31. >>> store(MyNames, ‘Mr. Gumby‘)
32. >>> lookup(MyNames, ‘middle‘, ‘‘)
33. [‘Robin Hood‘, ‘Robin Locksley‘, ‘Mr. Gumby‘]
例2. 不可变的数字和可改变的参数
1. >>> def inc(x): return x + 1
2.
3. >>> foo = 10
4. >>> inc(foo)
5. 11
6. >>> foo #外部变量未发生变化
7. 10
8. >>> foo = inc(foo) #将foo重新赋值
9. >>> foo
10. 11
使用列表外部变量foo改变了
1. >>> def inc(x): x[0] = x[0] + 1
2.
3. >>> foo = [10]
4. >>> inc(foo)
5. >>> foo
6. [11]
3. 关键字参数和默认值
位置:是指根据参数的对应位置传参,如def a(a,b,c):,调用a(1,2,3),1传给a,2传给b,3传给c,这样参数位置容易记混。
关键字参数,适用于大规模程序,清晰
1. >>> def hello(name, greeting):
2. print ‘%s, %s!‘ %(greeting, name)
3.
4.
5. >>> hello(‘sun‘, ‘Hello‘) #位置参数
6. Hello, sun!
7. >>> hello(name = ‘Sun‘, greeting = ‘Hello‘) #关键字参数
8. Hello, Sun!
9. >>> hello(greeting = ‘Hello‘, name = ‘Sun‘) #关键字参数,不必关心位置
10. Hello, Sun!
默认值
1. >>> def hello(name = ‘world‘, greeting = ‘Hello‘):
2. print ‘%s, %s!‘ %(greeting, name)
3.
4.
5. >>> hello()
6. Hello, world!
7. >>> hello(‘Sun‘)
8. Hello, Sun!
9. >>> hello(greeting = ‘Hi‘)
10. Hi, world!
位置参数与关键字参数混用,将位置参数放在前面。尽量避免这么用,容易引起混乱。
1. >>> def hello(name, greeting = ‘Hello‘, punc = ‘!‘):
2. print ‘%s, %s%s‘ %(greeting, name, punc)
3.
4.
5. >>> hello(‘Sun‘)
6. Hello, Sun!
7. >>> hello(‘Sun‘, ‘Hi‘)
8. Hi, Sun!
9. >>> hello(‘Sun‘, punc = ‘..‘)
10. Hello, Sun..
11. >>> hello() #因为name是必须要有,若有默认值,则可没有
12.
13. Traceback (most recent call last):
14. File "<pyshell#385>", line 1, in <module>
15. hello()
16. TypeError: hello() takes at least 1 argument (0 given)
17. >>>
4. 收集参数——在定义时使用*或**,用来收集参数,允许使用不定数量的参数
*:收集其余的位置参数并作为元组 返回
1. >>> def print_params2(title, *params):
2. print title
3. print params
4.
5.
6. >>> print_params2(‘Param:‘, 1, 2, 3)
7. Param:
8. (1, 2, 3) #以元组形式返回
9. >>> print_params2(‘Param:‘) #不提供收集元素时,返回空元组
10. Param:
11. ()
12. >>> print_params2(‘Param:‘, 1)
13. Param:
14. (1,) #只有一个元素时,仍为元组
**:收集其余的关键字参数并作为字典 返回,可与其他混用
1. >>> def print_params3(x, y, z = 3, *pospar, **keypar):
2. print x, y, z
3. print pospar
4. print keypar
5.
6.
7. >>> print_params3(1,2,3,4,5,6,7, fool = 1, bar = 2)
8. 1 2 3
9. (4, 5, 6, 7)
10. {‘fool‘: 1, ‘bar‘: 2}
11. >>> print_params3(1,2)
12. 1 2 3
13. ()
14. {}
5. 收集参数的翻转过程——在调用时使用*或**,将参数分配到定义的参数中,用于字典或列表分割时
用于列表
1. >>> def add(x,y): return x + y
2.
3. >>> params = (1,2)
4. >>> add(*params)
5. 3
用于字典
1. >>> def hello(name, greeting):
2. print ‘%s, %s!‘ %(greeting, name)
3.
4.
5. >>> params = {‘name‘: ‘Sir Robin‘, ‘greeting‘: ‘Welcome‘}
6. >>> hello(**params)
7. Welcome, Sir Robin!
8.
9.
参数使用实例
1. #模拟步长大于0的range()
2. >>> interval(10)
3. start = 0 stop = 10 step = 1
4. [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
5. >>> def interval(start, stop=None, step=1):
6. ‘Imitates range() for step > 0‘
7. if stop is None: #若未给stop指定值
8. start, stop = 0, start #多个赋值,0赋值给start,start的值赋值给stop
9. result = []
10. i = start
11. while i < stop:
12. result.append(i)
13. i += step
14. return result
15.
16. #
17. >>> def story(**kwds):
18. return ‘%(job)s called %(name)s.‘ %kwds
19.
20. >>> def power(x, y ,*others):
21. if others:
22. print ‘Received redundant parameters:‘,others
23. return pow(x,y)
24.
25. #使用
26. >>> params = {‘job‘:‘language‘,‘name‘:‘python‘}
27. >>> print story(**params) #调用时分割字典,定义中收集
28. language called python.
29. >>> del params[‘job‘]
30. >>> print story(job=‘test‘, **params)
31.
32. >>> power(2,3,‘test‘)
33. Received redundant parameters: test
34.
35. >>> params = (5,) * 2 #即(5,5)
36. >>> power(*params) #先分割,在赋给x,y
37. 3125
6.作用域
x = 1, 将名字x引用到值1上,类似字典
内建函数vars()返回这个字典
1. >>> x = 1
2. >>> scope = vars()
3. >>> scope[‘x‘]
4. 1
5. >>> scope[‘x‘] += 1 #一般情况下,vars()返回的字典不能修改
6. >>> x
7. 2
局部变量,全局变量
函数内部访问全局变量,慎用!
1. >>> def com(para): print para + external
2.
3. >>> external = ‘external‘
4. >>> com(‘param ‘)
5. param external
若全局变量与局部变量名字相同,会被局部变量覆盖,可使用global()类似vars(),获得全局变量的字典
1. >>> def com(para): print para + globals()[‘para‘]
2.
3. >>> para = ‘berry‘
4. >>> com(‘test ‘)
5. test berry
重绑定全局变量,将变量引用到其他新值——函数内部声明全局变量
1. >>> x = 1
2. >>> def change_global():
3. global x
4. x = x + 1
5.
6.
7. >>> change_global()
8. >>> x
9. 2
嵌套作用域——函数中定义函数,例如闭包
外部作用域中的变量一般不能被改变,但是用闭包,每次调用外层函数,内部函数都会被重新绑定,也即外部作用域factor每次都有一个新值
1. >>> def multiplier(factor):
2. def multiplyByFactor(number):
3. return number * factor
4. return multiplyByFactor #返回一个函数,这时并未调用
5.
6. >>> double = multiplier(2) #double是一个函数
7. >>> double #double是一个函数
8. <function multiplyByFactor at 0x0214C6F0>
9. >>> double(5) #调用multiplyByFactor(number)
10. 10
11. >>> multiplier(2)(5) #效果同上
12. 10
7. 递归——每调用一个函数,都会创建一个新的命名空间,意味着当函数调用自身时,实际上调用的是两个不同的函数
阶乘
1. >>> def factorial(n):
2. if n == 1:
3. return 1
4. else:
5. return n * factorial(n-1)
6.
7. >>> factorial(5)
8. 120
幂
1. >>> def power(x, n):
2. if n == 0:
3. return 1
4. else:
5. return x * power(x, n - 1)
6.
7.
8. >>> power(2,3)
9. 8
递归实例——二元搜索
前提:排好序
若上下限相同,则那就是数字所在位置,返回;
否则,找到两者的中间,查找数字是在左侧还是右侧,继续查找数字所在的那半部分。
1. >>> def search(sequence, number, lower = 0, upper = None):
2. if upper is None: upper = len(sequence) - 1
3. if lower == upper:
4. assert number == sequence[upper]
5. return upper
6. else:
7. middle = (lower + upper) // 2
8. if number > sequence[middle]:
9. return search(sequence, number, middle + 1, upper)
10. else:
11. return search(sequence, number, lower, middle)
12.
13.
14. >>> seq = [34, 67, 8, 123, 4, 100, 95]
15. >>> seq.sort()
16. >>> seq
17. [4, 8, 34, 67, 95, 100, 123]
18. >>> search(seq, 34)
19. 2
总结:
元组输出格式化,直接使用键,而不需要加引号
1. >>> d = {‘a‘:1, ‘b‘:2}
2. >>> print ‘%(a)s corresponds to %(b)s.‘ %d #注意a有括号,无引号
3. 1 corresponds to 2.
标签:
原文地址:http://blog.csdn.net/tanggao1314/article/details/52206874