代码改变世界

python第四天:迭代器、生成器、装饰器、内置函数

2017-05-22 14:49  明月照花眠  阅读(146)  评论(0)    收藏  举报

课前复习

鸡汤部分

语言的学习,就是各种语法要形成本能。不要多想,想了就会拖慢进度,导致无法继续进行下去。

编码

 将人类的字符转化为计算机可识别的字符。可以认为是字符与数字的对应关系。内存当中默认的编码是unicode

字符---->decode---->unicode

unicode---->encode---->字符(bytes类型)

文件操作

with open(‘filename’,’r’,encoding=’utf-8’)

注意的问题:文件写入的时候用什么字符集存的,就用什么样的字符集来取。

r模式

f.read

f.seek

f.readline

f.readlines

f.tell

w模式

f.write

f.writelines

函数

①为什么要用函数

函数主要是用来使整个程序逻辑架构更清晰,维护方便。

②函数的分类:内置函数,自定义函数。

内置函数使解释器在启动的时候自动加载在内置命名空间里的函数,自定义函数使由程序员自己使用def定义的系统。

③函数的定义阶段和使用阶段

定义阶段只检查语法是否正确,而不执行,使用阶段会执行,同时会做出一个独立的局部命名空间出来。

④函数的注意事项:

名字要反应意义,函数的文档注释,函数的主体和返回值。

⑤函数的三种形式:无参,有参,空函数。

也可以通过是否有返回值来区分。

⑥函数传参的奇技淫巧:foo(1,2,*[3,4,5]) 可以理解为foo(1,2,3,4,5)**{}同理,这个方法可以用作函数里面调用另一个函数,然后给这个参数传参使用。

eg

def  f11(*args):

  print(args)

def  foo(*args):

 print(type(args))

  f11(args,*args)

今天上课的内容

一、函数对象

 1、可以被引用。

    我们定义完函数以后,函数名就可以理解为是变量名,里面存储的是一个指向函数对象的内存地址,所以我们可以把这个值赋予给另一个变量,通过调用另一个变量来调用这个函数。

def foo():

pass

   ff = foo

ff()

2、可以被当做参数来使用

   函数可以直接当另外一个函数的参数使用(这里指函数本身,而不是返回值什么的)。然后在另外一个函数内部对其进行操作。

   例子

def  foo():

print(‘hello world’)

def  f11(fun):

fun()

  3、可以作为一个返回值

可以将函数本身作为一个返回值。

def foo():

pass

def bar(foo):

  return foo

4、可以作为容器类的对象的值(字典,列表)

   dic = {‘fun’:1}

这样可以把比如

if xxx = select:

pass

   elif xxx= insert:

   pass

...

都写成for n in fun_dic:

if n = input:

nb

二、函数嵌套

①函数的嵌套调用

嵌套调用的话,是整合逻辑的时候比较方便,而且也方便工具细化,维护和使用起来更加方便灵活。

def max2(x,y):

...

 def max4(x,y,z):

res = max2(x,y)

res1 = max2(res,z)

②函数的嵌套定义

函数嵌套定义的时候就会用到了命名空间的概念,在函数内部调用变量的时候,首先在自己的命名空间里面找,然后找不到在上一级的空间里面你找,比如这里的f3现在自己里面找,然后去f2,然后去f1,最后是全局。

def f1(x):

print(‘f1’)

def f2():

x =1

def f3():

print(‘from f3’)

print(x)

三、名称空间

名称空间:可以简单的理解为存放名字的地方。

Python中有三种名称空间:

1.内置名称空间:内置到python解释器里面的名字。在python解释器一启动的时候,就会定义很多的名称。

2.全局名称空间:文件的执行会产生全局名称空间,指得是文件级别定义的名称空间。

内置名称空间加上全局名称空间合起来叫做全局作用域。

3.局部名称空间:调用函数的时候会产生局部名称空间。只在函数调用的时候临时绑定,调用结束了以后就解除绑定。

局部作用域就是局部名称空面。

四、作用域

 分为全局作用域和局部作用域。作用域主要是用来确定函数内部在调用一个变量的时候,查找这个变量的顺序。一般的顺序就是局部作用域→全局作用于,查找到了值就会停止查找。

查看全局作用域内名字的方法gloabls()

查找过程中是以字典的形式打印出来的,变量名和变量值。其中内置名称空间的函数都是这个__builtins__

查看局部作用域内的名字locals():这个方法只会打印keyvalue的值,而不会打印函数自己本身。

不同作用域的特点

1.全局作用域是全局有效在任何位置都能被访问到,全局作用域的变量除非del删掉,否则一直存在。

2.局部作用域的名字:局部有效,只能在局部范围调用。局部作用域的变量只在函数调用的时候才有效,函数调用结束就生效了。

五、闭包函数

 嵌套函数中定义在内部函数包含对外部作用域而非全局作用域的引用。该内部函数就称为闭包函数。

eg

def f1(x=1):

def f2():

print(x)

return f2

 这样直接调用f1就相当于执行了f2,返回了print

闭包函数的特性:把一个东西给包裹起来了,不会受外界的影响

像上面的函数。这里包裹的东西,不光包括了函数f2还包含了变量X

f=f1()

f不光是一个函数f2,还相当于加了xx

闭包函数的原理:作用域是慢慢往前找的。只要外部空间有,就不会找全局空间。就把变量给控制住了,不会受外界的影响。而函数的话通过内部定义函数,然后在返回这个函数的名字。

闭包函数有一个独特的方法:__clousure__

可以通过fun.__closure__[0].cell_contents来找到闭包函数所包的变量名。

六、装饰器

装饰器:装饰器就是修饰别人的工具,在python里面修饰是添加功能,工具指的是函数。

装饰器本身是任何可调用对象,被装饰的对象也可以是任意可调用对象。目前只接触到了函数这个可调用对象,就没有太多的问题了。

为什么要使用装饰器:开放封闭原则:对修改是封闭的,对扩展是开放的。装饰器可以在不修改被装饰对象的源代码以及调用方式的前提下,为其添加新功能。

闭包函数可以就作为一个装饰器使用

def fun_zs(fun):

def fun_1():

print(‘hello boy’)

fun()

return fun_1

 使用装饰器的话要解决三点问题:

①给被装饰的函数传参数。

②要能正确的传递函数的返回值

③然后装饰器本身也要支持各种参数(可以被复用)。

一个一个解决:

①给被装饰的函数传参数:根据装饰器的特点,执行原来的函数最后就是相当于被封装起来的函数,所以只需要给被封装的函数传参数,再传到真实函数里面即可。

def fun_zs(fun):

def fun_1(*args,**kwargs):

print(‘hello boy’)

fun(*args,**kwargs)

return fun_1

②获取函数的正确返回值:和上面一样,根据装饰器的特点,只要给被封装的函数加一个返回值,其值是原函数的返回值即可。

def fun_zs(fun):

def fun_1(*args,**kwargs):

print(‘hello boy’)

return fun(*args,**kwargs)

return fun_1

   ③给装饰器配函数:装饰器也可以多种选择,比如常用作装饰器的认证模块,可能通过账号密码,友公司登陆等多种方式来进行登录。这个传参的过程,比如是在最外层传参。

 def fun_zs(login):

 def fun1(fun):

 def fun2(*args,**kwargs):

    if login == “weixin”:

 print(‘hello world’)

 return fun(*args,**kwargs)

             else:

                print(“认证失败”)

          return fun2

       return fun1

 

装饰器的叠加:装饰器是可以叠加的,相当于是一层接着一层的封装。执行顺序是从下到上。

七、迭代器

 迭代:重复的过程是迭代,每次迭代的结果就是下一次迭代的初始值。

为什么要迭代:

1.节省内存

2.提供了一种不依赖下标,取出数据类型所有值的方法。比如集合,字典。

可迭代对象:可迭代对象就是可以迭代的对象,在python中,有__iter__方法的对象都叫做可迭代对象。

迭代器对象:迭代器对象就是可以直接取出来值的对象,在python中,所有的有__next__方法的对象都叫做迭代器对象。

iter,nextnext(it)效果等同于it.__next__()it = iter(s)效果等同于it = s.__iter__()

使用内置模块判断一个对象是否是可迭代对象/迭代器对象:

from collections import Iterable,Iterator

print(isinstance(‘abc’,Iterable))#判断是否是可迭代对象

print(isinstance([],Iterator))#判断是否是迭代器对象

迭代器的集中迭代方法:

for循环:

for循环就是把后面的对象变成迭代器对象,然后一直next直到出现stop标志。

注:迭代器对象也可以可迭代对象(包含__iter__方法)

②使用for循环和next方法。

   mid_value = [1,2,3,4,5,6,7,9]

   it = mid_value.__iter__()

while True:

 try:

  print(it.__next__)

       except Exception:

         print(“hehe”)

八、生成器

生成器本身就是迭代器的一种表现形式,他就是将函数变成了迭代器对象。

只要函数的内部有yield关键字的话,那么函数就是生成器函数。yield可以认为就是另一种形式的return。他会执行函数,执行到yield的时候就停下,返回后面的值。然后再调用这个生成器的next方法,就会继续执行。

下面这个例子就是实现每秒打印数字,递增。

import time

def num():

    count =0

    while True:

        count += 1

        yield count

 

num_iter = num()

# for n in num_iter:

#     print(n)

while True:

    time.sleep(1)

    print(num_iter.__next__())

九、内置函数

abs():绝对值

all():判断可迭代对象所有的值是否都是true。如果可迭代对象为空,返回True

any():只要有一个为true,那就返回True。如果可迭代对象为空返回false

bin():10进制转二进制

hex():10进制转化为16进制

oct():10进制转化为八进制

bool():判断传入数据类型的布尔值。

callable():判断对象是否是可调用对象。

chr():按照ascii码表把数据转化成字符。

crd():将字符转化成ascii码表的值。

complex:传入复数,打印实部,虚部。

 

 

dir:查看一个对象下面的属性。

help:查看一个对象的帮助信息

l =[]

print(help(l))

divmod:除法。返回商和余

eval提取字符串的命令然后再执行出来:也可以将字符串中的字典 列表都提取出来。比如eval('print "hello world"')

 

float():浮点数

frozenset():定义不可变集合

format:字符串格式化。

 

hash:将传进来的数据获得一串数字。

1.只要校验的内容一致,那么hash得到的结果永远一样

2.哈希不可逆

3.只要采用的哈希算法一样,得到的结果长度都是一样的。

 

id:打印出内存地址。

is是身份运算符,==是值运算符、

 

pow:将前两个值做平方操作 然后模第三个值。

 

reversed:从后往前迭代取值。

round:保留X位小数(四舍五入)。

slice:列表切片

 

 

vars:如果不加参数等于locals(),如果加了参数

zip

 

__import__:以字符串的形式导入一个模块。

 

m.sleep(30)

 

 

 

delattr

hasattr

getattr

setattr

 

工厂函数:

dict

int

str

set

list