Python 迭代器&生成器

1.内置参数

  Built-in Functions  
abs()dict()help()min()setattr()
all()dir()hex()next()slice()
any()divmod()id()object()sorted()
ascii()enumerate()input()oct()staticmethod()
bin()eval()int()open()str()
bool()exec()isinstance()ord()sum()
bytrarray()filter()issubclass()pow()super()
bytes()float()iter()print()tuple()
callable()format()len()property()type()
chr()frozenset()list()range()vars()
classmethod()getattr()locals()repr()zip()
compile()globals()map()reversed()__import__()
complex()hasattr()max()round() 
delattr()hash()memoryview()set() 

内置参数详解 https://docs.python.org/3/library/functions.html?highlight=built#ascii 

 

2.迭代器&生成器

列表生成式,是Python内置的一种极其强大的生成list的表达式。

如果要生成一个list [1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9] 可以用 range(1 , 10):

1
2
#print(list(range(1,10)))
[ 1 2 3 4 5 6 7 8 9 ]

如果要生成[1x1, 2x2, 3x3, ..., 10x10]怎么做?

1
2
3
4
5
6
=  []
for  in  range ( 1 , 10 ):
     l.append(i * i)
print (l)
####打印输出####
#[1, 4, 9, 16, 25, 36, 49, 64, 81]

而列表生成式则可以用一行语句代替循环生成上面的list:

1
2
>>>  print ([x * for  in  range ( 1 , 10 )])
[ 1 4 9 16 25 36 49 64 81 ]

for循环后面还可以加上if判断,这样我们就可以筛选出仅偶数的平方:

1
2
>>>  print ([x * for  in  range ( 1 , 10 if  % 2  = = 0 ])
[ 4 16 36 64 ]

 

>>>[ i*2 for i in range(10)]
[0,1,4,6,8,10,12,14,16,18]
等于
>>>a=[]
>>>for i in range(10):
.  .  .    a.append(i*2)
>>>a
[0,1,4,6,8,10,12,14,16,18]

 小程序

 

str1 = ""
for i in iter(input,""):    # 循环接收 input输入的内容
    str1 += i

print(str1)

 

 

 

生成器

通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。

所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器:generator。

要创建一个generator,有很多种方法。第一种方法很简单,只要把一个列表生成式的[]改成(),就创建了一个generator:

>>>l = [x*x for x in range(10)]
>>>l
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
>>>g = (x*x for x in range(10))
>>>g
<generator object <genexpr> at 0x1022ef630>
View Code

创建Lg的区别仅在于最外层的[]()L是一个list,而g是一个generator。

我们可以直接打印出list的每一个元素,但我们怎么打印出generator的每一个元素呢?

如果要一个一个打印出来,可以通过next()函数获得generator的下一个返回值:

>>> next(g)
0
>>> next(g)
1
>>> next(g)
4
>>> next(g)
9
>>> next(g)
16
>>> next(g)
25
>>> next(g)
36
>>> next(g)
49
>>> next(g)
64
>>> next(g)
81
>>> next(g)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

所以,我们创建了一个generator后,基本上永远不会调用next(),而是通过for循环来迭代它,并且不需要关心StopIteration的错误。

generator非常强大。如果推算的算法比较复杂,用类似列表生成式的for循环无法实现的时候,还可以用函数来实现。

比如,著名的斐波拉契数列(Fibonacci),除第一个和第二个数外,任意一个数都可由前两个数相加得到:

1, 1, 2, 3, 5, 8, 13, 21, 34, ...

  

def fib(max):
   n,a,b=0,0,1
   while n < max:
      print(b)
      a,b=b,a+b
      n = n+1
   return 'done'

上面的函数可以输出斐波那契数列的前N个数:

>>>fib(10)
1
1
2
3
5
8
13
21
34
55
done

生成器的特点:

1)生成器只有在调用时才会生成相应的数据;

2)只记录当前位置;

3)只有一个__next__()方法;

还可通过yield实现在单线程的情况下实现并发运算的效果:

import time
def consumer(name):
    print("%s 准备吃包子!" %name)
    while True:
        baozi = yield
        print("包子[%s]来了,被[%s]吃了!" %(baozi,name))
c = consumer("ChenRonghua")
c.__next__()

def produceer(name):
    c = consumer("a")
    c2 = consumer("b")
    c.__next__()
    c2.__next__()
    print("老子开始准备做包子啦!")
    for i in range(10):
        time.sleep(1)
        print("做了1个包子,分两半!")
        c.send(i)
        c2.send(i)
produceer("alex")

  迭代器

我们已经知道,可以直接作用于for循环的数据类型有以下几种:

一类是集合数据类型,如listtupledictsetstr等;

一类是generator,包括生成器和带yield的generator function。

这些可以直接作用于for循环的对象统称为可迭代对象:Iterable

可以使用isinstance()判断一个对象是否是Iterable对象:

>>>from collections import Iterable
>>>isinstance([],Iterable)
True
>>>isinstance({},Iterable)
True
>>>isinstance('abc',Iterable)
True
>>> isinstance((x for x in range(10)), Iterable)
True
>>> isinstance(100, Iterable)
False

  

凡是可作用于for循环的对象都是Iterable类型;

凡是可作用于next()函数的对象都是Iterator类型,它们表示一个惰性计算的序列;

集合数据类型如listdictstr等是Iterable但不是Iterator,不过可以通过iter()函数获得一个Iterator对象。

Python的for循环本质上就是通过不断调用next()函数实现的,例如:

 

for x in [1,2,3,4,5]:
pass

 

实际上完全等价于:

# 首先获得Iterator对象:
it = iter([1, 2, 3, 4, 5])
# 循环:
while True:
    try:
        # 获得下一个值:
        x = next(it)
    except StopIteration:
        # 遇到StopIteration就退出循环
        break

  

3.Json&pickle数据序列化

用于序列化的两个模块

  • json,用于字符串 和 python数据类型间进行转换
  • pickle,用于python特有的类型 和 python的数据类型间进行转换

Json模块提供了四个功能:dumps、dump、loads、load

pickle模块提供了四个功能:dumps、dump、loads、load

info = {
    "name":"alex",
    "age":22
}
f = open("test.txt","w")
f.write(info)
f.close()
json序列化
1 f = open("test.txt","r")
2 
3 data = eval(f.read())
4 f.close()
5 print(data['age'])
json反序列化

json能处理简单的数据类型,字典,列表,字符串。

json是所有语言通用的,json的作用是不同语言之间进行数据交互。

 1 #json序列化
 2 import json
 3 info = {
 4     "name":"alex",
 5     "age":22
 6 }
 7 f = open("test.txt","w")
 8 #print(json.dumps(info))
 9 f.write(json.dumps(info))
10 f.close()
11 #json反序列化
12 import json
13 f = open("test.txt","r")
14 
15 data = json.loads(f.read())
16 f.close()
17 print(data['age'])
json序列化,反序列化
 1 import pickle
 2 def sayhi(name):
 3     print("hello,",name)
 4 info = {
 5     "name":"alex",
 6     "age":22,
 7     "func":sayhi
 8 }
 9 f = open("test.txt","wb")
10 
11 f.write(pickle.dumps(info))
12 f.close()
pickle序列化
import pickle
def sayhi(name):
    print("hello,",name)
f = open("test.txt","rb")
data = pickle.loads(f.read())

print(data['func']("Alex"))
pickle反序列化

 

 

4.装饰器

 

定义:

 

本质上是个函数,功能是装饰其他函数—就是为其他函数添加附加功能 

 

装饰器原则:

 

1)  不能修改被装饰函数的源代码;

 

2)  不能修改被装饰函数的调用方式;

 

实现装饰器知识储备:

 

函数即“变量”

 

定义一个函数相当于把函数体赋值给了函数名

 

 

1.函数调用顺序:其他高级语言类似,python不允许在函数未声明之前,对其进行引用或者调用

错误示范:

 1 def foo():
 2     print('in the foo')
 3     bar()
 4 foo()
 5 
 6 报错:
 7 in the foo
 8 Traceback (most recent call last):
 9   File "<pyshell#13>", line 1, in <module>
10     foo()
11   File "<pyshell#12>", line 3, in foo
12     bar()
13 NameError: global name 'bar' is not defined
14 
15 def foo():
16     print('foo')
17     bar()
18 foo()
19 def bar()
20     print('bar')
21 报错:NameError: global name 'bar' is not defined
View Code

正确示范:(注意,python为解释执行,函数foo在调用前已经声明了bar和foo,所以bar和foo无顺序之分)

def foo()
    print('in the foo')
    bar()
def bar():
    print('in the bar')
foo()

def bar():
    print('in the bar')
def foo():
    print('in the foo')
    bar()
foo()
View Code

2.高阶函数

满足下列条件之一就可成函数为高阶函数

  1.某一函数当做参数传入另一个函数中

  2.函数的返回值包含n个函数,n>0

高阶函数示范:

def bar():
    print('in the bar')
def foo(func):
    res=func()
    return res
foo(bar)
View Code

 高阶函数的牛逼之处:

def foo(func):
    return func
print('function body is %s' %(foo(bar)))
print('function name is %s' %(foo(bar).func_name))
foo(bar)()
#foo(bar)() 等同于bar=foo(bar)然后bar()
bar = foo(bar)
bar()
View Code

3.内嵌函数和变量作用域

定义:在一个函数体内创建另一个函数,这种函数就叫内嵌函数

嵌套函数:

def foo():
    def bar():
        print('in the bar')
    bar()
foo()

局部作用域和全局做用域的访问顺序

x = 0
def grandpa():
    def dad():
        x = 2
        def son():
            x=3
            print(x)
        son()
    dad()
grandpa()
View Code

4.高阶函数+内嵌函数=》装饰器

函数参数固定

def decorartor(func):
    def wrapper(n):
        print('starting')
        func(n)
        print('stopping')
    return wrapper

def test(n):
    print('in the test arg is %s' %n)
decorartor(test)('alex')
View Code

函数参数不固定

def decorartor(func):
    def wrapper(*args,**kwargs):
        print('starting')
        func(*args,**kwargs)
        print('stopping')
    return wrapper

def test(n,x=1):
    print('in the test arg is %s' %n)
decorartor(test)('alex',x=2222)
View Code

1.无参装饰器

import time
def decorator(func):
    def wrapper(*args,**kwargs):
        start_time=time.time()
        func(*args,**kwargs)
        stop_time=time.time()
        print("%s" %(stop_time-start_time))
    return wrapper

@decorator
def test(list_test):
    for i in list_test:
        time.sleep(0.1)
        print('-'*20,i)

#decorator(test)(range(10))
test(range(10))
View Code

2.有参装饰器

import time
def timer(timeout=0):
    def decorator(func):
        def wrapper(*args,**kwargs):
            start=time.time()
            func(*args,**kwargs)
            stop=time.time()
            print('run time is %s ' %(stop-start))
            print(timeout)
        return wrapper
    return decorator
@timer(2)
def test(list_test):
    for i in list_test:
        time.sleep(0.1)
        print ('-'*20,i)
  
#timer(timeout=10)(test)(range(10))
test(range(10))
View Code

3.终极装饰器

user,passwd = 'alex','abc123'
def auth(auth_type):
    print('auth func:',auth_type)
    def outer_wrapper(func):
        def wrapper(*args,**kwargs):
            print("wrapper func args:",*args,**kwargs)
            if auth_type=="local":
                username = input("Username:").strip()
                password = input("Password:").strip()
                if user == username and passwd == password:
                    res = func(*args,**kwargs)
                    print("---after authentication")
                    return res
                else:
                    exit("\033[31;1mInvalid username or password\033[0m")
            elif auth_type == "ldap":
                print('搞毛线ldap,不会......')

        return wrapper
    return outer_wrapper

def index():
    print("welcome to index page")
@auth(auth_type="local")    #home = wrapper()
def home():
    print("welcome to home page")
    return "from home"
@auth(auth_type="ldap")
def bbs():
    print("welcome to bbs page")

index()
print(home())#wrapper()
bbs()
View Code

 

转载于:https://www.cnblogs.com/smile1/p/5769488.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值