python学习笔记——第六章 抽象

1、函数 def function(arg)

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]

2、记录函数:在函数的开头写下字符串,作为函数的一部分进行存储,称为文档字符串

def square(x):
    'Calculates the square of the number x.'
    return x*x
文档字符串的访问方式:
>>> square.__doc__  #__doc__是函数属性,属性名中的双下划线表示它是个特殊属性
'Calculates the square of the number x.'
>>> help(square) #内建的help函数非常有用
Help on function square in module __main__:

square(x)
    Calculates the square of the number x.
3、函数的参数
形参:写在def语句中函数名后面的变量通常叫做函数的形式参数;
实参:调用函数的时候,提供的值是实际参数。
在函数内为参数赋予新值不会改变外部任何变量的值

参数储存在局部作用域(local scope)内

>>> def try_to_change(n):
	n='JACK'

	
>>> name = 'Tom'
>>> try_to_change(name)
>>> name
'Tom'

3.1
#字符串(以及数字和元组)是不可变的,即无法被修改(也就是说只能用新的值覆盖)
#列表用作参数的改变:
# 函数的局部名称--包括参数在内---并不和外面的函数名称(全局的)冲突。


对于可改变的数据结构,如列表,参数的内部赋值会改变外部变量的值
内部参数与外部变量指向同一个列表,所以会被修改
若不想改变外部列表,可以传进一个副本

>>> def change(n):
	n[0]='1'

	
>>> names= ['2','3','4']
>>> change(names)  #参数被改变
>>> names
['1', '3', '4']

#采用普通方法进行模拟
>>> names = ['2','3','4']
>>> n=names #模拟传参行为
>>> n[0]='1'  #改变列表
>>> names
['1', '3', '4']

3.2修改参数
例:用名字、中间名或姓查找联系人的程序

若名字为'Magus Lie Hetland'存储格式类似
   data = {
                  'first': { 'Magus': 'Magus Lie Hetland'},
                  'middle': {'Lie': 'Magus Lie Hetland'},
                  'last': {'Hetland': 'Magus Lie Hetland'}
                }
   注意insert(index,value)函数,在列表的索引位置插入值

>>> def init(data):   #data作为存储表,初始化 
	data['first']={}
	data['middle']={}
	data['last']={}

	
>>> storage ={}
>>> init(storage)
>>> storage
{'middle': {}, 'last': {}, 'first': {}}


>>> def store(data,full_name):  #存储,将全名存储到表中
	names = full_name.split()   #将名字按空格(即first,middle,last)分开,返回列表,如'jack wang feng' 返回【'jack','wang','feng'】
	if len(names)==2: names.insert(1, '') #如果names的长度为2(只有首名和末名),插入一个空字符串作为中间名,如无中间名【'tom','ping'】返回【'tom','','ping'】
	labels = 'first','middle','last'   #元组
	for label,name in zip(labels,names):  #元组与序列间也可使用zip  
		people = lookup(data ,label,name)
		if people:
			people.apend(full_name)
		else:
			data[label][name]=[full_name]

# 获得名字的函数:
>>> def lookup(data,label,name):
	return data[label].get(name)

#输出
>>> MyNames = {}
>>> init(MyNames)
>>> store(MyNames, 'Magnus Lie Hetland')
>>> lookup(MyNames, 'middle','Lie')
['Magnus Lie Hetland']

3.3 不可变的数字和可改变的参数 

>>> def inc(x): return x+1   #将变量的数值增1的函数如下:

>>> foo=10
>>> inc(foo)
11
>>> foo #外部变量未发生变化
10
>>> foo=inc(foo) #将foo重新赋值
>>> foo
11

#改变参数,将值放置在列表中 (使用列表外部变量foo改变了)
>>> def inc(x): x[0]=x[0]+1

>>> foo=[10]
>>> inc(foo)
>>> foo
[11]

3.4 关键字参数和默认值

位置参数:如下例子,如果参数有多个,参数的顺序很难记起。

>>> def hello(greeting,name):
	print('%s,%s!' %(greeting,name))

	
>>> hello('hello','world')
hello,world!
关键字参数:使用参数名提供的参数叫做关键字参数。使用于大程序,关键字参数就是提供一个默认值
>>> def hello(greeting,name):
	print('%s,%s!' %(greeting,name))

	
>>> hello(name='world',greeting='hello')  #关键字参数最厉害的地方在于可以在函数中给参数提供默认值
hello,world!
# 关键字参数和位置参数可以混合使用,注意把位置参数放置在前面就可以。
函数的调用方式:
>>> def hello_1(name,greeting='Hello',punctuation='!'):
	print('%s,%s%s' %(greeting,name,punctuation))

	
>>> hello_1('Mars')
Hello,Mars!
>>> hello_1('WSF','Howdy')
Howdy,WSF!
>>> hello_1('WSF','Howdy','....')
Howdy,WSF....
>>> hello_1('WSF',punctuation='.')
Hello,WSF.
>>> hello_1('WSF',greeting='Top of the morning to ya')
Top of the morning to ya,WSF!
>>> hello_1()
Traceback (most recent call last):
  File "<pyshell#17>", line 1, in <module>
    hello_1()
TypeError: hello_1() takes at least 1 positional argument (0 given)

3.5 收集参数

给函数提供任意多的参数

>>> def print_params(*params):   #参数前的星号将所有值放置在同一个元组中,将这些值收集起来
	print(params)

	 
>>> print_params('Testing')
('Testing',)               #结果作为元组打印出来


#用来联合普通参数,星号的意思就是收集其余的位置参数
>>> def print_params_2(title,*params):  # *返回的是元组
	print(title)
	print(params)

	
>>> print_params_2('params:',1,2,3)
params:
(1, 2, 3)

>>> print_params_2('Nothing:')  #不提供任何供收集的元素,params就是个空元组
Nothing:
()

>>> print_params_2('Hmm...',something=42) #不能处理关键字参数
Traceback (most recent call last):
  File "<pyshell#12>", line 1, in <module>
    print_params_2('Hmm...',something=42)
TypeError: print_params_2() got an unexpected keyword argument 'something'

>>> def print_params_3(**params):  #处理关键字参数收集操作,**返回的是字典
	print(params)

	
>>> print_params_3(x=1,y=2,z=3) #返回字典而不是元组
{'y': 2, 'x': 1, 'z': 3}

>>> def print_params_4(x,y,z=3,*pospar,**keypar):
	print(x,y,z)
	print(pospar)
	print(keypar)

	
>>> print_params_4(1,2,3,5,6,7,foo=1,bar=2)  #混合使用
1 2 3
(5, 6, 7)
{'foo': 1, 'bar': 2}
>>> print_params_4(1,2)
1 2 3
()
{}

完整例子:实现多个名字同时存储
>>> def store(data,*full_names):
	for full_name in full_names:
		names=full_name.split()
		if len(names)==2: names.insert(1,'')
		labels = 'first','middle','last'
		for label,name in zip(labels,names):
			people =lookup(data,label,name)
			if people:
				people.append(full_name)
			else:
				data[label][name]=[full_name]

3.6 反转过程 
收集参数的反转过程——在调用时使用*或**,将参数分配到定义的参数中,用于字典或列表分割时

用于列表:

>>> def add(x,y):return x+y

>>> params=(1,2)
>>> add(*params)
3

用于字典:

>>> def hello(name, greeting):
	print('%s, %s!' %(greeting,name))

	
>>> params={'name': 'Sir Robin','greeting': 'Well met'}
>>> hello(**params)
Well met, Sir Robin!

练习使用参数

>>> def story(**kwds):
	return 'Once upon a time,there was a ' \
	       '%(job)s called %(name)s,' %kwds

>>> def power(x,y,*others):
	if others:
		print('Received redundant parameters:', others)
	return pow(x,y)

>>> def interval(start ,stop=None,step=1):
	'Imitates range() for step > 0'
	if stop is None:
		start,stop = 0,start
	result = []
	i = start
	while i < stop:
		result.append(i)
		i += step
	return result

#结果输出
>>> print(story(job='king',name='Gumby'))
Once upon a time,there was a king called Gumby,
>>> print(story(name='Sir Robin', job = 'brave knight'))
Once upon a time,there was a brave knight called Sir Robin,
>>> params = {'job': 'language', 'name': 'Python'}
>>> print(story(**params))  #调用时分割字典,定义中收集 
Once upon a time,there was a language called Python,
>>> del params['job']
>>> print(story(job='stroke of genius', **params))
Once upon a time,there was a stroke of genius called Python,
>>> power(2,3)
8
>>> power(3,2)
9
>>> power(y=3,x=2)
8
>>> params = (5,) * 2  #即(5,5) 
>>> power(*params)   #先分割,在赋给x,y  
3125

4、作用域
作用域:"不可见字典"叫做命名空间或者作用域。
局部变量:函数内的变量称为局部变量(local variable)

>>> def output(x):
	print(x)

	
>>> x=1
>>> y=2
>>> output(y)
2

在函数内部访问全局变量,会引发错误,慎重使用全局变量

>>> def combine(parameter):
	print(parameter+external)

	
>>> external = 'berry'
>>> combine('Shrub')
Shrubberry

 若全局变量与局部变量名字相同,会被局部变量覆盖,可使用global()类似vars(),获得全局变量的字典

>>> def combine(parameter):
	print(parameter + globals()['parameter'])

	
>>> parameter='berry'   #全局变量
>>> combine('Shrub')
Shrubberry
重绑定全局变量,(使变量引用其他新值)--函数内部声明全局变量,用global语句申明

>>> x=1
>>> def change_global():
	global x
	x = x + 1

	
>>> change_global()
>>> x
2

嵌套作用域--一个函数放在另一个函数里面
外部作用域中的变量一般不能被改变,但是用闭包,每次调用外层函数,内部函数都会被重新绑定,也即外部作用域factor每次都有一个新值

>>> def multiplier(factor):
	def multiplyByFactor(number):
		return number*factor
	return multiplyByFactor  #返回一个函数,这时并未调用  

>>> double = multiplier(2)  #double是一个函数
>>> double(5)  #调用multiplyByFactor(number)  
10
>>> triple = multiplier(3)
>>> triple(3)
9
>>> multiplier(5)(4)
20

5、递归:函数调用自身
阶乘
n的阶乘定义为n*(n-1)*(n-2)*....*1
循环的实现形式:

>>> def factorial(n):
	result = n
	for i in range(1,n):
		result *=i
	return result

>>> factorial(6)
720

用递归的实现:

>>> def factorial(n):
	if n == 1:
	   return 1
	else:
           return n * factorial(n-1)

        
>>> factorial(6)
720

幂:像内建的pow函数或者××运算符一样
power(x,n) (x为n的幂次)是x自乘n-1次的结果(所以x用作乘数n次)
循环实现:

>>> def power(x,n):
	result =1
	for i in range(n):
		result *=x
	return result

>>> power(3,3)
27

递归实现:

>>> def power(x,n):
	if n ==0:
	   return 1
	else:
           return x*power(x,n-1)

        
>>> power(3,4)
81
二元查找
递归实例——二元搜索
前提:排好序
若上下限相同,则那就是数字所在位置,返回;
否则,找到两者的中间,查找数字是在左侧还是右侧,继续查找数字所在的那半部分。

>>> def search(sequence,number,lower,upper):
	if upper is None: upper = len(sequence)-1
	if lower==upper:
		assert number == sequence[upper]
		return upper
	else:
		middle = (lower+upper)//2
		if number > sequence[middle]:
			return search(sequence,number,middle+1,upper)
		else:
			return search(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)
2





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值