第四章 抽象
懒惰即美德
抽象和结构
创建函数,示例代码如下:
检查函数是否可以调用:
Hasattr(func,__call__)
>>> def hello(name):
return 'hello,'+name+'!'
>>> print (hello('retacn'))
hello,retacn!
>>> def fibs(num):
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]
>>> fibs(15)
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377]
记录函数
文档字符串
>>> def square(x):
'Calculates the squareof the number x.'
return x*x
查看文档字符串,__doc__是函数属性
>>> square.__doc__
'Calculates the square of the number x.'
也可以使内建的help函数
参数魔法
局部作用域,函数外的参数不会受到影响
>>> def try_to_change(n):
n='Mr. yue'
>>> name='Mr.retacn'
>>> try_to_change(name)
>>> name
'Mr.retacn'
可变的数据结构如列表:
>>> def change(n):
n[0]='Mr.yue'
>>> names=['Mrs.three','Mr.retacn']
>>> change(names)
>>> names
['Mr.yue', 'Mr.retacn']
注:如果两个变量同时引用一个列表的时候,就需要复制一个列表的副本
N=name[:]
参数可变的场景
#抽象的初始化工作
def init(data):
data['first']={}
data['middle']={}
data['last']={}
def lookup(data,label,name):
returndata[label].get(name)
def store(data,full_name):
#得到names列表
names=full_name.split()
#如果名字只有首名和末名,则插入空白中间名
if len(names)==2:
names.insert(1,'')
#将三个元组存储到labels中
labels='first','middle','last'
#使用zip函数联合标签和名字
for label,name inzip(labels,names):
#取得属于给定标签 的名字和列表
people=lookup(data,label,name)
#添加到列表或插入一个新列表
if people:
people.append(full_name)
else:
data[label][name]=[full_name]
测试上面的函数
>>> MyNames={}
>>> init(MyNames)
>>> store(MyNames,'Retacn yue three')
>>> lookup(MyNames,'middle','yue')
['Retacn yue three']
>>> store(MyNames,'robin hood')
>>> store(MyNames,'robin locksley')
>>> store(MyNames,'mr, yue')
>>> lookup(MyNames,'first','robin')
['robin hood', 'robin locksley']
>>> lookup(MyNames,'middle','')
['robin hood', 'robin locksley', 'mr, yue']
参数不可变的场景,还想要改变的话:
#使用返回值的方式
>>>foo=10
>>>foo=inc(foo)
>>> foo
11
>>> definc2(x):x[0]=x[0]+1
#可以将值放到列表中
>>>foo=[10]
>>>inc2(foo)
>>> foo
[11]
关键字参数和默认值
#位置参数
>>> hello_one('hello','word')
hello,word!
>>> def hello_two(name,greeting):
print('%s,%s' %(name,greeting))
>>> hello_two('hello','word')
hello,word
#为了不防止参数顺序出错,可以使用关键字参数,示例代码如下:
hello_one(name='word',greeting='hello')
hello,word!
#给参数提供默认值
>>> def hello_three(greeting='hello',name='word'):
print('%s,%s !' %(greeting,name))
>>> hello_three()
hello,word !
收集参数
有点象java 中的可变参数
#收集位置参数
>>> def print_params(*params):
print(params)
>>> print_params(1,2,3,4)
(1, 2, 3, 4)
#收集关键字参数
>>> def print_params_two(**params):
print(params)
>>> print_params_two(x=1,y=2,z=3)
{'y': 2, 'x': 1, 'z': 3}
>>>
反转过程
>>> def add(x,y): return x+y
>>> params=(1,2)
>>> add(*params)
3
def with_starts(**kwds):
print(kwds['name'],'is',str(kwds['age']),'years old')
with_starts(**args)
retacn is 32 years old
def without_starts(kwds):
print(kwds['name'],'is',kwds['age'],'years old')
>>> without_starts(args)
retacn is 32 years old
作用域
#局部变量
>>>Def foo():x=42
#全局变量
>>>X=1
>>>Foo()
>>>X
1
#函数中声明全局变量,示例代码如下
>>> x=1
>>> def change_global():
global x
x=x+1
>>> change_global()
>>> x
2
递归
#计算阶乘
def factorial(n):
if n==1:
return 1
else:
returnn*factorial(n-1)
>>> factorial(3)
6
#计算幂
>>> def power(x,n):
if n==0:
return 1
else:
returnx*power(x,n-1)
>>> power(2,3)
8
二元搜索:(折半查找)
>>> def search(sequence,number,lower=0,upper=None):
ifupper==None:upper=len(sequence)-1
if lower==upper:
assertnumber==sequence[upper]
return upper
else:
middle=(lower+upper)//2
ifnumber>sequence[middle]:
return search(sequence,number,middle+1,upper)
else:
returnsearch(sequence,number,lower,middle)
>>>seq=[34,67,8,123,4,100,95]
>>>seq.sort()
>>> seq
[4, 8, 34, 67,95, 100, 123]
>>>search(seq,34)
>>> search(seq,34)
2