python学习心得第五章
1.冒泡排序:
冒泡是一种基础的算法,通过这算法可以将一堆值进行有效的排列,可以是从大到小,可以从小到大,条件是任意给出的。
冒泡的原理:
将需要比较的数(n个)有序的两个两个的进行比较,直到第一次所有的值都比较完成,就可以得出第1次排列的顺序,同理第二次将(n-1)个数进行比较,得到第二次排列的结果,n为1
的时候结束比较,其实就是5个数需要比较4次,每一次都是两个数进行两两比较,因为比较的方式就像水里面冒泡的现象所以称为冒泡算法。
由上述代码可以看出冒泡算法的核心就在于比较两个值得时候怎么交换两个值得顺序,这个交换的关键就是借助第三个变量,如果条件成立则让比较的第一个值赋值给第三个变量,让
第二个值赋值给第一个值,让第三个变量赋值给第二个值,这样一交换,原来的第一个值就变成了第二个值,第二个值变成了第一个值,第三个变量会被py在内存里垃圾回收。
2.递归
递归是函数嵌套的一种应用,它的特殊之处在于它是自己嵌套自己,所以称为递归
上面代码中就是递归的简单应用,注意递归的递和归是两个完全相反的过程,这种递和归的形式就是利用了函数的嵌套,
递:函数执行以后传入参数1,输出1,由于不满足条件,执行函数并且传入参数(i+1),函数就这样一直执行下去的过程称为递
归:当i=10的时候输出10,并且满足条件这个时候注意了,条件里面有一个return值,这个时候函数执行到第十次的时候由于return结束了函数,并且把函数值传给了第10次执行的函数,
所以r =l(i+1)里面的r就是第十次return的返回值,由于第十次的函数已经执行结束,由于第十次的执行函数是包含在第九次整个函数体里面,所以第十次函数结束以后继续执行下面的return
代码,则结束第九次函数,就这样一直结束到整个嵌套退出,利用返回值的传递可以把最内层的返回值传到第一层的返回值,最后输出。
利用递归还可以做斐波那契数列0,1,1,2,3,5,8.。。前两个数相加等于后面那个数
斐波拉契数列数列的第十个就是34
3.装饰器
装饰器的由来
由于面对大型的项目,里面有很多的代码,在这些代码里面最重要的就是最底层的代码,所有的功能都需要调用底层的代码,如果项目需要修改很有肯能就要改变底层的代码
但是底层代码的修改是非常麻烦的一件事,它不仅庞大而且繁琐,并且如果不同的程序员都来进行修改过,则最初的原始功能可能就会面目,所以在做大型项目的时候,最好让底层代码简洁易懂
并且在不改变它代码的同时,可以添加新的功能。这个时候我们就要用到装饰器。
装饰器的原理:
上面代码中liu()是底层代码,不能进行修改的,如果想要执行liu()增加功能则需要使用装饰器,我们新定义一个函数outer()在outer()里面再定义一个inner()函数,并且在outer里面传入
参数func,这个时候我们在liu()函数的上面输入代码@outer,当我们执行这些代码的时候会发什么呢?
@outer是python里面固有的一项功能,它可以把@下面紧接着的函数作为参数传给@后面紧跟这个函数,并且把@后面函数的返回值赋值给@下面的函数
有了@的功能我们来看一下整个代码的执行,首先我们把liu()作为参数传到outer里面接着把inner赋值给liu(),最后执行liu函数
由于liu被inner赋值以后内存地址改变,执行liu的时候其实执行的是inner,所以liu()==inner()当执行liu()时候inner()函数开始执行。并且中间会执行func这个参数,由于第一次执行outer
时候已经把func和inner一起刷到了内存,所以当执行inner的时候func也是可以执行的,我们知道@outer让最开始的liu()是作为参数传给了outer,所以liu==func,当执行func的时候就是执行
liu最开始对应的函数。这个就是整个整个装饰器的原理,本质就是创建一个新的函数且函数里面含有原来的函数,这样只用调节装饰器一个代码块就可以控制任意的底层函数,你可以不加,或者
选择性的加装饰器,让想要增加或删除功能的底层代码随意的变化,且又不改变原来的底层代码。
装饰器的参数
装饰器传参数就是正常往要执行的函数和装饰器里面对应的函数写参数。但是如果我们对应的底层函数是多个,并且每一个底层函数传的参数都不一样,应该怎么才能让同一个装饰器
传不同的参数都可以执行呢?
利用*args **kwargs这两个万能参数就可以解决,python自己在内部进行了处理
上面代码中只要装饰器里面的参数为*args **kwargs,我们在底层传参数的时候传几个参数都是可以的。
应用多个装饰器
注意多个装饰器应该在同一个函数上面的时候最外层是第一装饰器,第二层是第二个装饰器,最内层是底层函数
原理与一个装饰器的时候相同,其实就是把第一次用装饰器以后函数liu()变成了inner(),再用装饰器的时候就是对inner()这个函数,就是一种函数的嵌套
第一次把liu嵌套在inner里面第二层把inner嵌套在一个新的inner里面,由于python的代码是从上往下执行的所以在执行最后嵌套完的函数的时候,先执行最外面装饰器的代码,
执行到func函数的时候,执行第一次嵌套的代码(针对两个装饰器),开始执行第一次的inner函数里面的代码,执行到func的时候,这时才执行底层的代码,最后函数执行结束
退出,继续执行第一次嵌套,等第一次嵌套结束以后,接着执行第二次嵌套,最后执行完整个嵌套的函数。得到返回值。最后利用return的传递,输出的还是底层代码的返回值
4.字符串格式化:
为什么有字符串格式化:
由于在拼接字符串的时候如果用+会太过繁琐而且特别消耗内存,比如四个字符串用+拼接就会在内存里面产生四个新的字符串,其中的三个是我们用不到的,只有最后一个是需要的。
百分号方式:
%s可以传入任何参数,%d只能传入数字
可以用名字代替格式化的内容
用.数字可以控制数字的位数并且四舍五入
用名字带入
名字后面可以跟+—空格和0来控制字符串的左右,后面的数字控制位置的长短,最后是位数的保持,顺序不能变,如果传的是数字并且后面是用0来控制左右的话,就会用0来填充空白。
字符串格式化里面如果想要输出%只能用%%表示
format方式:
没有规定传入参数类型{}里面什么都可以穿
利用*【】传参顺序一一对应
利用索引传参
利用名字参数名传参
利用**{}把参数传入
利用索引对应的元素值进行传参
使用{:字母}以后必须按照规定传参,s只能传字符串,d只能传数字,f只能传小数,如果是整数,传入以后会变成小数。
规定类型的帯名传参
5.生成器和迭代器
迭代器
迭代器是访问集合的一种方式,迭代器从集合的第一个元素开始访问,直到所有的元素访问结束,迭代器只能向前访问,不能退后,迭代器在访问的过程中,没有访问的元素可以存在
也可以不存在,只有迭代到该元素的时候才会被计算,这也是迭代器的优点。
迭代器内部使用__next__()进行迭代的。生成器通过__next__()和next()进行迭代。
iter()是生成器生成的一种方式
生成器
生成器是把集合的元素放在一个特殊的对象里面,这对象就是生成器,生成器里面的元素只有在使用的时候才会在内存里面创造出来,函数里面含有yield就是生成器函数。
拿生成器里面的函数需要用迭代器,例如rang()函数就是一个生成器函数。
注意生成器如果每次都用函数直接.__next__()只会拿到第一个元素的值,因为每次都重新创造了一个生成器
rang函数的原理
生成器表达式:
生成器表达式和for循环长得很像但是不一样。生成器表达式只能用next(),__next__()和for循环取里面的元素。
列表的一种表达式:
生成器表达式的应用:
三元运算的应用
多元素生成器表达式:
多元素表达式的本质:
注意:在执行生成器函数的时候每次用__next__或者next()以后,执行的都是两个yield里面的代码,就是上一次执行到的yield开始到离它最近的那个yield
之间的代码,当有多元素表达式的时候逗号只用在表达式最开始的元素位置,两个for表达式之间绝对不要有逗号。
(x for x in (y.doSomething() for y in lst) )万能格式