6.1懒惰即美德
计算斐波那契额数列
fibs = [0,1]
for i in range(8):
fibs.append(fibs[-2]+fibs[-1])
print fibs
6.2抽象和结构
计算机非常乐于处理精确和具体的指令,但是人可就不同了
6.3创建函数
函数:函数是可以调用的,它执行某种行为并且返回一个值。
callable函数:用来判断函数是否可调用 (python3.0中不再可用)
>>> import math
>>> x = 1
>>> y = math.sqrt
>>> callable(x)
False
>>> callable(y)
True
>>>
如何定义函数:使用def(函数定义)语句
return语句:用来从函数中返回值
补充:函数可以返回一个以上的值,在元组中返回即可
def hello(name):
return 'Hello.'+name+'!'
print hello('Gumby')
6.3.1文档化函数
如果在函数的开头写下字符串,他就会作为函数的一部分进行存储,这称为文档字符串
def square(x):
'calculates the square of the number x.'
return x*x
print square(2)
print 'print doc'
print square.__doc__
说明:doc是函数的属性
补充::help函数——help(func)可以的到关于函数,包括它的文档字符串的信息
6.3.2并非真正函数的函数‘
1、数学意义上的函数总在计算器参数后返回点什么。
2、Python有些函数不返回任何东西,有的编程语言中把这样的函数称为'过程'
3、return语句只起到结束函数的作用
def test():
print 'this is printed'
return
print 'this is not'
x = test()
print x
(1)实际上,Python中所有的函数的确都返回了东西:当不需要它嗯返回值的时候,他们就返回None。
(2)python的函数就是函数,即便它从学术上讲并不是函数,没有return语句,或者有return语句但return后边没有跟任何值的函数,不返回值
6.4参数魔法
6.4.1值从哪里来
形参:写在def语句中函数名后面的变量
实参:在函数调用中提供的值
6.4.2我能改变参数吗
1、在函数内为参数赋予新值不会改变外部任何变量的值
2、参数存储在局部作用域
将可变数据结构作为参数会发生什么
def change(n):
n[0] = "Mr.Gumby"
names = ['Mr.Entity' ,'Mrs.Thing']
change(names)
print names
>>>['Mr.Gumby', 'Mrs.Thing']
奇怪吧!参数被改变了;为什么呢?当两个变量同时引用一个列表的时候,他们确是同时引用一个列表,就是这么简单。可以复制一个列表的副本,来避免出现这种情况,比如所对序列进行切片(切片总是返回序列的一个副本)。
为什么要修改参数?
1、使用函数改变数据结构是一种将程序抽象化的好方法,
如果我的参数不可变呢?
1、不好意思,没有办法
2、Python中,函数只能修改参数对象本身
3、这个时候你应该选择从该函数中返回所有你需要的值,或者将值放在列表中再传递给函数。
6.4.3关键字参数和默认值
1、目前位置我们所使用的参数都叫做位置参数,因为他们的位置很总要,事实上比他们的名字更总要。
回避位置问题
1、有些时候(尤其是参数很多的时候),参数的顺序是很难记住的。为了让事情简单些,可以提供参数的名字
def hello_1(greeting,name):
print '%s.%s!'%(greeting,name)
def hello_2(name,greeting):
print '%s,%s!'%(name,greeting)
#参数的顺序不同但是输出的结果却相同
print 'this is hello_1()'
hello_1('Hello','world')
print 'this is hello_2()'
hello_2('Hello','world')
#为传入的实参提供具体的形参参数名后
print 'hello_2() parameter with name'
hello_2(greeting='Hello',name='world')
>>>
>this is hello_1()
Hello.world!
this is hello_2()
Hello,world!
hello_2() parameter with name
world,Hello!
关键字参数使用参数名提供的参数,它的主要作用在于可以明确每个参数的作用。
1、关键字参数最厉害的地方——可以在函数中给参数提供默认值,
2、参数具有默认值的时候,调用的时候就不用提供参数了,可以不提供,提供一些,或提供所有参数,没有提供参数的变量,会使用默认值。
def hello_3(greeting='Hello',name='world'):
print '%s.%s'%(greeting,name)
#这种调用方法必须为所有的参数提供默认值,否则就会产生异常
print 'hello_3()'
hello_3()
print "hello_3('Greeting')"
hello_3('Greeting')
print "hello_3('Greeting','universe')"
hello_3('Greeting','universe')
6.4.4收集参数
如何让用户提供任意数量的参数:在参数前加星号*
“*”的含义:收集其余位置的参数。如果不提供任何供收集的元素,params(下例中)就是个空元组
def print_params(*params):
print params
print_params('Testing')
print_params(1,2,3)
#与普通参数联合使用
def print_params_2(title,*params):
print title
print params
print_params_2('Params:',1,2,3)
能否联合关键字参数使用
答案是不能:需要提供宁外一个能处理关键字参数的‘收集’操作。即在参数前加**,含义是收集其余位置的关键字参数,如果没有多余的的关键字参数就是返回空字典{}
def print_params_3(**params):
print params
print "print_params_3(x=1,y=2,z=3)"
print_params_3(x=1,y=2,z=3)
print '\n'
def print_params_4(x,y,z=3,*pospar,**keypar):
print x,y,z
print pospar
print keypar
print "print_params_4(1,2,3,5,6,7,foo=1,bar=2)"
print_params_4(1,2,3,5,6,7,foo=1,bar=2)
>>>
print_params_3(x=1,y=2,z=3)
{'y': 2, 'x': 1, 'z': 3}
print_params_4(1,2,3,5,6,7,foo=1,bar=2)
1 2 3
(5, 6, 7)
{'foo': 1, 'bar': 2}
6.4.5参数收集的逆过程:
1、何为参数收集的逆过程:即参数分配
2、区别:参数收集是在“函数定义中”使用*或**将函数调用时传入的多余参数用元组或字典收集起来,而参数分配是在“函数调用”的过程中使用*或**将元组或字典中的值分配到函数所声明的参数中去。
def add(x,y):return x+y
params = (1,2)
print add(*params)
3
def hello_3(greeting = "Hello",name = 'world'):
print '%s.%s'%(greeting,name)
params = {'name':'sir Robin'}
hello_3(**params)
>>>
Hello.sir Robin
6.4.6练习使用参数
6.5作用域
关于变量的思考:变量可以看做是值的名字。变量和所对应的值可以看做是个不可见的字典。内建vars函数可以返回这个字典:
x = 1
scope = vars()
scope['x']
1
1、这类不可见的字典叫做命名空间或者作用域
2、除了全局作用域外,每个函数调用都会创建一个新的作用域
3、函数内的变量成为局部变量
4、参数的工作原理类似于局部变量,所以用全局变量的名字作为参数名并没有问题,因为它们虽然名字相同,但却处于不同的作用域
如果局部变量或者参数的名字和想要访问的全局变量名相同的话,就不能直接访问了,全局变量会被局部变量所屏蔽,如果确切需要的话,可以使用globals函数获取全局变量值,类似的还有vars函数返回全局变量的字典,locals函数返回局部变量的字典
1、重绑定全局变量
如果在函数内部将值赋予一个变量,它会自动成为局部变量,除非告知Python将其声明为全局变量,小菜一碟!
x = 1
def change_global():
global x
x = x + 1
print x
change_global()
print x
2嵌套作用域:也就是说将一个函数放在另一个里面。
应用:嵌套一般说不是那么有用,但它有一个很突出的应用,例如需要一个函数“创建 ”另一个函数
def multiplier(factor):
def multiplyByFactor(number):
return number*factor
return multiplyByFactor
double = multiplier(2)
print 'double(5)'
print double(5)
triple = multiplier(3)
print 'double(3)'
print triple(3)
print "multiplier(5)(4)"
print multiplier(5)(4)
分析:一个函数位于另外一个里面,外层函数返回里层函数,也就是说函数本身被返回了,但并没被调用 ,总要的是返回的函数还可以访问它的定义所在的作用域
闭包:类似于multiplyByFactory函数存储子封闭作用域的行为就叫做闭包
6.6递归
原理:函数可以调用自身
递归含义:引用自身的意思
有用的递归函数所应该包含的部分
1、当函数直接返回值时,有基本实例(最小可能性问题)
2、递归实例,包括一个或多个问题较小部分的递归调用
全文引用于:作者: Magnus Lie Hetland
出版社: 人民邮电出版社
原作名: Beginning Python: From Novice to Professional, Second Edition
译者: 司维 / 曾军崴 / 谭颖华
出版年: 2010-7
页数: 471
定价: 69.00元
装帧: 平装
丛书: 图灵程序设计丛书
ISBN: 9787115230270