目录
这一步的学习四个知识点,如何将语句组织成函数,参数,作用域(scope),和递归
一、函数
1、抽象和结构
抽象可以节省很多的工作量,实际上它的作用更大,它是使得计算机程序让人读懂的关键(这也是最基本的要求,不管是读程序还是写程序。)
2、创建函数
1、使用def函数就可以定义函数,2、2.0python使用callable(<func>),检查函数是否可以被调用,3.0python使用hasattr(func,_call_),。3、函数返回一个以上的的值,在元组中返回即可。
2.1、记录函数
给函数写文档,让使用该函数的人理解两种方式,一种加入注释(#开头)。另一种方式是:直接写上字符串,这类字符串在其他地方可能非常有用。
其中的__doc__可以访问文档字符串。
2.2、并非真正函数的函数
有些python函数不返回任何东西,在其他语言中可能有别的名称,但是python中函数就是函数。即便没有返回值python也会默认返回None。
二、参数魔法
注意 def语句后面的变量通常叫做函数的形式参数,而调用函数的时提供的有值是实际参数,也成参数。
1、我能改变参数吗?
分两种情况:1、字符串元组以及数字,这些不可变参数。在函数内修改参数不会影响到从函数外部传入的参数变量。(因为传递的是副本,也就是值类型)
2、字典,list等这些,传入参数,在函数内部修改会影响到外面传入的这个参数变量。(因为两个变量引用同一个列表。想要不影响函数外面的变量指向的list.。可以对这个list做切片,因为切片总是返回的副本。)
2、为什么想要修改参数
使用函数修改数据结构(比如字典和list)是将程序抽象化的好方法。
例子:做一个存储名字,并能通过,姓字,中间字,和最后字,查询联系人。
实现:
1、先建立storage={} 字典。
2、 建立,first ,middle,last三子字字典
3、存储名字
4、这样存储名字,一两个还好说,如果多个就非常麻烦而且容易出错。这里就需要使用函数封装具体操作。
4.1、封装初始化storage的操作
调用
4.2、在编写存储名字函数之前,先要写获取获取名称的函数
先手动存储一个名字查询名字
4.3、存储名字的函数,注意因为函数修改的是list和字典。所以当函数内修改以后,list或字典也跟着变化。函数返回的是None。
注意:zip是压缩两个list为键值对。 尝试使用
4.4、额外知识
改变不可变参数。例如数字,出入的参数是数字,在函数内部改变,不会影响到函数的外部,这个传入参数变量。
3、关键字参数和默认参数
截至目前,前面学习的都是位置参数。位置参数,位置比他们的名字更重要。
可以看出位置参数,名称不重要。
传入位置参数,结果无区别 接下来传入 关键字参数。那就有区别了
定义带关键字参数函数 因为关键函数可以提供默认值,说以调用可以传空
也可以把位置参数和关键字参数混合使用,但是一般不推荐这样做。除非是强制要求的参数个数比可修改的带具有默认值的参数个数少的时候才使用混合。
4、收集参数
在有些时候让用户输入任意数量的参数是很有必要的。有两中方式实现
1.、def print_params(*params)
pring(params) #这里(*)星号参数的意思是,将所有参数收集到元祖里。如果参数个数为空,那元祖为()。也不会出错。
2、def print_params(**params)
pring(params) #这里(**)双星号参数的意思是,将所有关键字参数收集到字典里。如果关键字参数为空,那字典为{}。也不会出错。
5、反转过程
上节讲的是,定义函数的时候,使用参数收集*和**,将参数收集成元祖和字典。实际反过来同样有效
在函数定义的时候没有使用参数收集,但是使用函数的时候,可以使用*和**传递参数。
(*)元祖的反转 但是要注意(**)这里使用双星(**)和不使用双星(**)得到的结果一样。所以星号只在定义函数(语序使用不定数目的参数)或者调用(“分割”字典或序列)时才有用。
三、作用域
1、到底什么事变量?你可以把它看作值得名称/执行x=1赋值语句后,名称x就引用到值1。这像一个字典吧,实际就是一个不可见的字典。使用vars函数可以返回这个字典。注意vars所返回的字典是不能修改的。根据pyhon官方的说法是,结果未定义,可能得到未知结果。
这个”看不见的字典“叫做命名空间或者作用域,到底什么是命名空间?除了全局作用域外,每个函数调用都会创建一个新的作用域。
这里foo函数改变了(从绑定)了变量x,但是最后,x并没有改变。这是因为当调用foo的时候,新的命名空间就被创建了,它作用于foo内部的代码块。赋值x=42只在内部作用域(局部命名空间)起作用,所以它并不会影响外部(全局)作用域中的x。函数内部的变量成为 局部变量(local variable),与全局变量完全相反的概念。参数的工作原理类似于局部变量,所以用全局变量的名作为参数名并没有问题。
2、如何在函数内部使用全局变量。
在函数内部使用修改全局变量,可以使用global 关键字声明。注意在python3.0中引用了nonlocal关键字,他和global关键字作用类似,可以让用户在函数内部修改外部作用域(但并非全局作用域。)
四,递归
1、递归 函数可以调用自身--如果这么做了就叫递归。一切递归实现的功能都可以使用循环代替。但是使用递归函数更易读懂。
大多数,用递归实现的,有循环实现效率更高。但是递归容易理解。
2、函数式编程
map(func, seq [,seq]) // map函数:对序列中的每个元素,使用func函数。
filter(func,seq) //返回函数为真的元素的列表。
reduce这个函数不常用,将序列的前两个元素相加,然后再用他们的和,同第三个元素相加。直到整个序列处理完毕。//在python3.0去掉这个函数的定义直接使用sum()
sum(seq) //返回序列中所有元素的和。
reply(func[,agrs,]) //调用函数,并提供参数。
学习资料:python基础教程