Python的平凡之路(4)

1、迭代器&生成器
生成器定义:
经过列表生成式,咱们能够直接建立一个列表。可是,受到内存限制,列表容量确定是有限的。并且,建立一个包含100万个元素的列表,不只占用很大的存储空间,若是咱们仅仅须要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。因此,若是列表元素能够按照某种算法推算出来,那咱们是否能够在循环的过程当中不断推算出后续的元素呢?这样就没必要建立完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制称为生成器。
特色:
1 生成器只有在调用时才能生成相应的数据。
2 只有一个__next__()方法
生成器表达式的语法和列表解析同样,只不过生成器表达式是被()括起来的,而不是[]
4 生成器是一种特殊的迭代器,内部支持了生成器协议,不须要明肯定义__iter__()和next()方法
5 生成器经过生成器函数产生,生成器函数能够经过常规的def语句来定义,可是不用return返回,而是用yield一次返回一个结果。
 
列表生成式
譬如:
( i*2 for i in range(10))
等同于
a = [ ]
for i in range(10):
     a.append(i*2)
     print(i)
 
迭代器定义:
咱们已经知道,能够直接做用于 for循环的数据类型有如下几种:
一类是集合数据类型,如 listtupledictsetstr等;
一类是 generator,包括生成器和带 yield的generator function。
这些能够直接做用于 for循环的对象统称为可迭代对象: Iterable
可使用 isinstance()判断一个对象是不是 Utterable对象。
*能够被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator
特色:
1生成器都是 Iterator对象,但 listdictstr虽然是 Iterable,却不是 Iterator
listdictstrIterable变成 Iterator可使用 iter()函数:
2 是可做用于 for循环的对象都是 Iterable类型; 凡是可做用于 next()函数的对象都是 Iterator类型,它们表示一个惰性计算的序列;
集合数据类型如 listdictstr等是 Iterable但不是 Iterator,不过能够经过 iter()函数得到一个 Iterator对象。
Python的 for循环本质上就是经过不断调用 next()函数实现的
3 举例:
Python的 for循环本质上就是经过不断调用 next()函数实现的, 对于可迭代对象,for语句能够经过iter()方法获取迭代器,而且经过next()方法得到容器的下一个元素。例如:
for  in  [ 1 2 3 4 5 ]:
     pass

实际上彻底等价于:python

# 首先得到Iterator对象:
it = iter([1, 2, 3, 4, 5])
# 循环:
while True:
    try:
        # 得到下一个值:
        x = next(it)
    except StopIteration:
        # 遇到StopIteration就退出循环
        break
 
生成器.py
#!/usr/bin/env python
#Author is wspikh
# -*- coding: encoding -*-
#这1亿个数并无真正生成,调用的时候才生成。
b = (i*2 for i in range(100))
#b.__next__()) 的含义

for i in b:
    print(i)

def fib(max):
    n, a, b = 0, 0, 1
    while n < max:
        #print(b)
        yield b #返回了函数的中断状态
        a, b = b, a + b
        n = n + 1
    return 'done'
print(fib(100))
f = fib(100)
print(f.__next__())
print("===========")
print(f.__next__())
print(f.__next__())
print(f.__next__())
print(f.__next__())
print(f.__next__())


g = fib(6)
while True:
    try:
        x = next(g)
        print('g:', x)
    except StopIteration as e:
        print('Generator return value:', e.value)
        break
 
迭代器.py
#!/usr/bin/env python
#Author is wspikh
# -*- coding: encoding -*-
from collections import Iterable
#判断是否是可迭代对象
print(isinstance('abc',Iterable))
print(isinstance('[1,2,3]',Iterable))
print(isinstance('{"server":"192.168.1.10"}',Iterable))
print(isinstance((x for x in range(10)), Iterable))
print(isinstance(100,Iterable))
print("")
print("")
from collections import Iterator
#判断是否是迭代器对象
print(isinstance('abc',Iterator))
print(isinstance('[1,2,3]',Iterator))
print(isinstance('{"server":"192.168.1.10"}',Iterator))
#生成器确定是迭代器
print(isinstance((x for x in range(10)), Iterator))
print(isinstance(100,Iterator))
 
 
2、装饰器
定义:
装饰器本质是函数,用来装饰其余函数,为其余函数添加函数功能
原则:
1 不能修改被装饰的函数的源代码
2 不能修改被装饰的函数的调用方式
实现装饰器知识储备:
1 函数即“变量"
2 高阶函数
 a 把一个函数当作实参传给另一个函数(不修改源代码状况下添加功能)
 b 返回值中包含函数名(不修改函数的调用方式)
3 嵌套函数
举例:
qt.py
#!/usr/bin/env python
#Author is wspikh
# -*- coding: encoding -*-
def foo():
    print("in the foo")
    def bar():
     print("in the bar")
    bar()
foo()
4 高阶函数+嵌套函数=》装饰器
gj.py
#!/usr/bin/env python
#Author is wspikh
# -*- coding: encoding -*-
import time
def bar():
    time.sleep(4)
    print('in the bar')
def test1(func):
    #print(func)
    start_time = time.time()
    func() #run bar
    stop_time = time.time()
    print("the fund run time is %s" %(start_time-stop_time))
#不能写成test1(bar()),由于bar()表明函数返回值
test1(bar)
 
装饰器.py
#!/usr/bin/env python
#Author is wspikh
# -*- coding: encoding -*-
import time
#嵌套函数和高阶函数的融合
def timer(func):
    def deco():
        start_time=time.time()
        #return func()
        func()
        stop_time=time.time()
        print("the func run time is %s" %(start_time-stop_time))
    return deco #返回值中包含函数名(不修改函数的调用方式)//?

@timer #语法堂 test1=timer(test1)之因此仍是用test1作变量是由于装饰器不改变被装饰函数的调用方式,
def test1():
    time.sleep(3)
    print("in the test1")

@timer #语法堂 test2=timer(test2)
def test2():
    time.sleep(3)
    print("in the test2")

test1()
test2()
 
 
3、Json & pickle 数据序列化
定义:
咱们把变量从内存中变成可存储或传输的过程称之为序列化。反过来,把变量内容从序列化的对象从新读到内存里称之为反序列化,即unpickling。
特色:
1 序列化以后,就能够把序列化后的内容写入磁盘,或者经过网络传输到别的机器上,在python中提供了两个模块可进行序列化。分别是pickle和json。
2 pickle是python中独有的序列化模块,所谓独有,就是指不能和其余编程语言的序列化进行交互,由于pickle将数据对象转化为bytes。pickle模块提供了四个功能:dumps、dump、loads、load。dumps和dump都是进行序列化,而loads和load则是反序列化。
3 若是咱们要在不一样的编程语言之间传递对象,就必须把对象序列化为标准格式,好比XML,但更好的方法是序列化为JSON,由于JSON表示出来就是一个字符串,能够被全部语言读取,也能够方便地存储到磁盘或者经过网络传输。JSON不只是标准格式,而且比XML更快,并且能够直接在Web页面中读取,很是方便。
4 json中的方法和pickle中差很少,也是dumps,dump,loads,load。使用上也没有什么区别,区别在于,json中的序列化后格式为字符。
5 dumps将所传入的变量的值序列化为一个bytes,而后,就能够将这个bytes写入磁盘或者进行传输。dump则更加一步到位,在dump中能够传入两个参数,一个为须要序列化的变量,另外一个为须要写入的文件。loads当咱们要把对象从磁盘读到内存时,能够先把内容读到一个bytes,而后用loads方法反序列化出对象,也能够直接用load方法直接反序列化一个文件。
举例:
序列化和反序列化.py
#!/usr/bin/env python
#Author is wspikh
# -*- coding: encoding -*-
#import json
import pickle

def sayhi(name):
    print("hello",name)

sayhi("alex")

info = {
'age':22,
'name':'alex',
'func':sayhi
}
f = open("json.txt","wb")
#f.write(str(info))
f.write(pickle.dumps(info))
f.close()
#反序列化
f = open("json.txt","rb")
data = pickle.loads(f.read())
print(data)
f.close()
 
 
4、软件目录结构规范
目的:
软件目录层次清晰,可读性强。
举例:
假设你的项目名为foo, 目录结构建议以下:
Foo/
|-- bin/ | |-- foo | |-- foo/ | |-- tests/ | | |-- __init__.py | | |-- test_main.py | | | |-- __init__.py | |-- main.py | |-- docs/ | |-- conf.py | |-- abc.rst | |-- setup.py |-- requirements.txt |-- README

简要解释:算法

  1. bin/: 存放项目的一些可执行文件,固然你能够起名script/之类的也行。
  2. foo/: 存放项目的全部源代码。(1) 源代码中的全部模块、包都应该放在此目录。不要置于顶层目录。(2) 其子目录tests/存放单元测试代码; (3) 程序的入口最好命名为main.py
  3. docs/: 存放一些文档。
  4. setup.py: 安装、部署、打包的脚本。
  5. requirements.txt: 存放软件依赖的外部Python包列表。
  6. README: 项目说明文件。
相关文章
相关标签/搜索