python学习笔记-函数篇

时间:2020-12-20 17:16:40
首先以一小段很精炼的代码开头
  
  
  
def fib(num):
'斐波那契数列'
fibs = [0,1]
for i in range(num):
fibs.append(fibs[-2]+fibs[-1])
return fibs

抽象

--独立的函数定义

创建函数

--函数定义语法

记录函数

--在函数的开头写下字符串,它就会作为函数的一部分进行存储,称为“文档字符串”。

  
  
  
def fib(num):
'斐波那契数列'
#...
通过 fib.func_doc来显示字符串内容。

无“返回值”的函数返回甚?

--返回了None

  
  
  
>>> def func():
return
 
>>> x = func()
>>> print x
None

参数参数参数

--形参vs实参

--能否改变参数?

    python倒是没有什么按值传递、按址传递,和java一样,统统都是引用(在对象上)。参数存储在局部作用域(local scope)内,字符串、数字、元组

是不可变的,即无法被修改(只能是被新的值覆盖),所以这仨作实参传入函数后是不能被修改的。如果可变的数据结构例如列表、字典啥的作实参传

入,一旦函数内对这些可变数据结构修改,在函数外,函数内的修改同样是有效的——这个就要说到多个变量同时引用同一个对象了

  
  
  
>>> x = dict(name = 'liu',age = 21)
>>> y = x
>>> y['age'] = 22
>>> x
{'age': 22, 'name': 'liu'}
解释的很明白了,
    那么如何避免?当传入可变数据结构时,将该数据结构的整个的切片传入进去 list[:]

--但是实际中,我们需要传入的参数是不可变的数据类型,偏偏需要函数能够对值进行修改而且这个修改对函数外仍然有影响,咋整?再加上需要返回
多个值,又咋整?
    提供两个解决方案:
    1.将不可变参数以可变数据类型包装后传入函数——将值放入列表中
    2.让函数返回多个值,这些多个值以元组包装起来。
  
  
  
def test(x,y,z):
return x+1,y+1,z+1
 
x = 1
y = 2
z = 3
list_ = test(x,y,z)
print list(list_)

关键字参数和默认值

--我们之前用的参数都叫“位置参数”,它们的位置很重要,重要到比名字还重要。

--关键字参数 函数的使用,定义还原来的定义方式,只不过需要把函数形参名字记住了...

  
  
  
>>> def hello(greeting ,name):
print greeting,name
>>> hello(name = 'liuliuliu',greeting = 'hello')
hello liuliuliu
--关键字参数厉害的地方在于可以再函数中给参数提供关键字

  
  
  
def hello(greeting = 'Hello',name = 'liu'):
print greeting,name

收集参数

--使得函数可以接收任意数量的参数

  
  
  
def print_params(*params):
print params
--在函数体内部,参数被元组包装起来了,*的意思就是“收集其余的位置参数”

--注意一下,一个*表示收集的参数应该都是没有映射关系的,自成一体的,所以一个*不能处理关键字参数,只能处理位置参数。

--那么要处理 位置参数 ,该怎么办呢?用2个*~~~
   
   
   
>>> def print_params(**params):
print params
>>> print_params(greeting = 'hello',name = 'liu')
{'greeting': 'hello', 'name': 'liu'}
可以看到,返回值成了字典而不是元组了,将所有的多余关键字参数放置在该字典中。

反转过程

--和上面收集多余位置的参数类似,只不过上面是将多余位置的参数包装成元组或者字典,而这个讲的是将元组或者字典进行解包装。

 当为函数提供的参数是元组或字典时,有两种情况。
 
      一、函数定义时在参数前使用*或**来收集参数。那么为该函数传递元组或字典时,需要在是实参前也相应的加上*或**来对实参进行反转。
 
     二、函数定义时,形参是一个普通参数。那么为该函数传递元组或字典时,不用在实参前加*或**了,直接在函数内部将该参数作为元组或字典使用。
   
   
   
def with_twostars(**params):
print params['name']
def with_nostar(param2):
print param2['name']
#调用函数方法
var1={'name':'jinglingshu','sex':'female'}
with_twostars(**var1) #实参需要进行反转
with_nostar(var1)

作用域

--每个变量都有其有效的范围,这个范围就是作用域(命名空间)。

--在不同的作用域中发生变量重名的问题时,在哪个作用域中,优先默认使用哪个变量。但是在某个函数的命名空间中,想使用一个已经在该作用域声

明过的变量的同名全局变量:

  
  
  
x = 1
def func():
x = 2
y = 3
x = x + globals()['x']
print x
--那么如何在函数内部声明一个全局变量呢?
   
   
   
global x
--嵌套的作用域

由于函数是可以相互嵌套的,即函数内部可以声明新的函数,而内部函数也可以被当做函数返回值返回。
   
   
   
def plusx):
def plusplusy):
return x+y
return plusplus

递归

--根据个人的思考,我总结的递归需要注意的两个问题

    1.递归应该是由大到小的再到大的过程,所以就像剥洋葱一样,一次剥几层洋葱皮是一个需要考虑的问题。

    2.递归的终止条件,啥时候该结束了一定需要一个这样的结束,剥到多少层才是头?

附上前两天写的汉诺塔实现

  
  
  
#将n号盘子从from_挪到to_,中转为temp_
def hanoi(n,from_,to_,temp_):
'''
1.将前n-1个盘子从A挪到B,C为中转
2.将第n个盘子从A挪到C,B为中转
3.将前n-1个盘子从B挪到C,A为中转
'''
if n == 1:
print 'Move',n,'from',from_,'to',to_
return
hanoi(n-1,from_,temp_,to_)
print 'Move',n,'from',from_,'to',to_
hanoi(n-1,temp_,to_,from_)
 
 
hanoi(int(raw_input()),'A','C','B')