笔者QQ 360212316

迭代器&生成器

生成器:

一个函数调用返回一个迭代器,那这个函数叫做生成器,如果函数中包含yield语法,那么这个函数就会变成生成器

生成器的特点:

1、生成器必须从前往后一次访问,不能跳着取

2、生成器只记录访问的数据,其他数据释放

3、生成器的作用就是预想可能用到那么多的数据

生成器的两种方式:

方式一:

data = (x * 2 for x in range(5))
# 获取结果的两种方式
print(data.__next__())
print(next(data))

方式二:

def fib(num):
count = 0
a, b = 0, 1
while count < num:
tmp = a
a = b
b = a + tmp
yield a # 有yield代表这个函数其实是个生成器,类似return,但是不结束
# a 返回给了__next__()调用当前函数的人 f = fib(10000) # 生成一个生成器对象,就是代表生成式准备好了生成公式
print(f.__next__())
print(f.__next__())

此处yield的作用:

这个yield的主要效果就是可以中断函数,并保存中断状态,中断后,代码可以继续往下执行,过一段时间含还可以重新调用这个函数,从上次的yield的下一行开始执行

另外,还可以通过yield实现单线程的情况下实现并发运算的效果

import time   # 导入时间模块
def xf(name):
print("%s 吃包子了" % name)
while True:
baozi = yield
print("包子 %s 来了,被 %s吃 了" % (baozi, name))
def chushi(name):
c = xf('A') # 调用生成式
c2 = xf('B') # 调用生成式
c.__next__()
c2.__next__()
print("开始做包子")
for i in range(10):
time.sleep(1) # 睡眠一秒
print("做了俩个包子")
c.send(i) # 将i发送给yield
c2.send(i) # 将i发送给yield
chushi("xiaofeng")

列表生成式

需求,列表[0,1,2,3,4,5],要求把每个值都加1,实现方法:

方法1:

data = [0, 1, 2, 3, 4, 5]
data = map(lambda x: x+1, data)
for i in data:
print(i)
# 结果:
1
2
3
4
5
6

迭代器:

迭代器是访问集合元素的一种方式。迭代器对象从集合的第一个元素开始访问,直到所有的元素都被访问结束。迭代器只能往前不能往后退,迭代器的有点就是不用事先准备好整个过程中的手游元素,迭代器仅仅在跌带到某个元素时才开始计算该元素,而在之前或之后,元素可以不存在或销毁,这个特点使他特别适合用于遍历一些巨大无限的集合,比如几个G的文件

特点:

1、访问者不需要关心迭代器内部的结构,仅需要通过next()方法不断去取下一个内容

2、不能随机访问集合中的某个值,只能从头到尾依次访问

3、访问到一半时不能回退

4、便于循环比较大的数据集合,节省内存

迭代小结:

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

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

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

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

装饰器:

装饰器的功能就是给函数添加功能,同时又不改变源代码,也不改变元程序的调用方式

第一步:最简单的函数

def home():
print("--首页---") def america():
print("---欧美---") def japan():
print("---日韩---") def henan():
print("---河南---") # 调用方法
home()
america()
japan()
henan()

第二步:使用装饰器函数在函数执行前添加额外认证功能

user_status = False
def loggin(func):
def inner():
_username = "xiao"
_password = "abc123"
global user_status
if user_status == False:
username = input("username:")
password = input("password:")
if username == _username and password == _password:
print("welcome loging")
user_status = True
# func()
else:
print("wrong username or password")
if user_status == True:
func()
return inner
def home():
print("--首页---") def america():
print("---欧美---") home()
america= loggin(america)
america()

第三步:使用语法糖来装饰函数

user_status = False
def loggin(func):
def inner():
_username = "xiao"
_password = "abc123"
global user_status
if user_status == False:
username = input("username:")
password = input("password:")
if username == _username and password == _password:
print("welcome loging")
user_status = True
# func()
else:
print("wrong username or password")
if user_status == True:
func()
return inner
def home():
print("--首页---") @loggin # 语法糖@来装饰函数
def america():
print("---欧美---")
home()
america()

第四步:对带参数的函数进行装饰

user_status = False
def loggin(func):
def inner(x,y):
_username = "xiao"
_password = "abc123"
global user_status
if user_status == False:
username = input("username:")
password = input("password:")
if username == _username and password == _password:
print("welcome loging")
user_status = True
# func(x,y)
else:
print("wrong username or password")
if user_status == True:
func()
return inner
def home():
print("--首页---") @loggin # 语法糖@来装饰函数
def america(x,y):
print("---欧美---")
print(x,y)
home()
america(1,2)

第5步:对参数不确定装饰

user_status = False
def loggin(func):
def inner(*args,**kwargs):
_username = "xiao"
_password = "abc123"
global user_status
if user_status == False:
username = input("username:")
password = input("password:")
if username == _username and password == _password:
print("welcome loging")
user_status = True
func(args,kwargs)
else:
print("wrong username or password")
if user_status == True:
func()
return inner
def home():
print("--首页---") @loggin # 语法糖@来装饰函数
def america(x,y):
print("---欧美---")
print(x,y)
home()
america(1,2)

模块

什么是模块:

模块,用一对代码实现某个功能的集合。

类似于函数式变成和面向过程,函数式变成则完成一个功能,其他的代码用来调用即可,提供了代码的重用性和代码间的耦合。而对于一个复杂的功能来,可能需要多个函数才能完成(函数又可以在不同的.py文件中),n个,.py文件组成的代码集合就称为模块。

见到点说就是一个功能一个py文件

模块的分类:

1、内置标准模块(又称标准库)

2、自定义模块

3、第三方模块

os模块

常用模块方法 含义
os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径
os.chdir("dirname") 改变当前脚本工作目录;相当于shell下cd
os.curdir 返回当前目录: ('.')
os.pardir 获取当前目录的父目录字符串名:('..')
os.makedirs('dirname1/dirname2' 可生成多层递归目录
os.removedirs('dirname1') 若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推
os.mkdir('dirname') 生成单级目录;相当于shell中mkdir dirname
os.rmdir('dirname') 删除单级空目录,若目录不为空则无法删除,报错;相当于shell中rmdir dirname
os.listdir('dirname') 列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印
os.remove() 删除一个文件
os.rename("oldname","newname") 重命名文件/目录
os.stat('path/filename') 获取文件/目录信息
os.sep 输出操作系统特定的路径分隔符,win下为"\\",Linux下为"/"
os.linesep 输出当前平台使用的行终止符,win下为"\t\n",Linux下为"\n"
os.pathsep 输出用于分割文件路径的字符串
os.name 输出字符串指示当前使用平台。win->'nt'; Linux->'posix'
os.system("bash command") 运行shell命令,直接显示
os.environ 获取系统环境变量
os.path.abspath(path) 返回path规范化的绝对路径
os.path.split(path) 将path分割成目录和文件名二元组返回
os.path.dirname(path) 返回path的目录。其实就是os.path.split(path)的第一个元素
os.path.basename(path) 返回path最后的文件名。如何path以/或\结尾,那么就会返回空值。即os.path.split(path)的第二个元素
os.path.exists(path) 如果path存在,返回True;如果path不存在,返回False
os.path.isabs(path) 如果path是绝对路径,返回True
os.path.isfile(path) 如果path是一个存在的文件,返回True。否则返回False
os.path.isdir(path) 如果path是一个存在的目录,则返回True。否则返回False
os.path.join(path1[, path2[, ...]]) 将多个路径组合后返回,第一个绝对路径之前的参数将被忽略
os.path.getatime(path) 返回path所指向的文件或者目录的最后存取时间
os.path.getmtime(path) 返回path所指向的文件或者目录的最后修改时间

sys模块

常用方法 含义
sys.argv 命令行参数List,第一个元素是程序本身路径
sys.exit(n) 退出程序,正常退出时exit(0)
sys.version 获取Python解释程序的版本信息
sys.maxint 最大的Int
sys.path 返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值
sys.platform 返回操作系统平台名称

sys.stdout.write('please:')

 

val = sys.stdin.readline()[:-1]

 

json和pickle模块

json和pickle模块用于序列化的模块

json,用于字符串和python数据类型间进行转换

pickle,用于python特有的类型和python的数据类型间进行转换

json模块提供了四个功能,dumps、dump、load、loads

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

json示例:

import json

data = {
"name": "panfeng",
"age": 22
}
with open("data", 'w', encoding='utf-8') as f:
json.dump(data, f) # 字典序列化写入到文件 with open("data", 'r', encoding='utf-8') as f:
a = json.load(f) # 字符串以序列化读取
print(a['age']) 结果:
22
pickle序列化示例
import pickle   # 导入pickle模块才能pickle方法
data = {
"name": "panfeng",
"age": 22
}
with open("data", 'wb') as f:
pickle.dump(data, f) # 字典序列化写入到文件 with open("data", 'rb') as f:
a = pickle.load(f) # 字符串以序列化读取
print(a['age'])
# 结果:
22

软件目录结构规范

为什么要要设计好目录结构?

设计项目目录结构,就和代码的风格一样,属于个人风格问题,对于这种风格的规范,一直存在两种态度:

1、一类人任务,这种个人风格问题无关紧要,理由就是能让程序work更好,风格问题根本不是问题

2、另一类人认为,规范化能更高的控制程序结构,让程序具有更高的可读性。

项目目录结构其实是属于可读性和可维护性的范畴,我们设计一个清晰的目录机构就是为了达到一下两点:

1、可读性高,不熟悉这个项目代码的人,一眼就能看懂不了机构,知道程序的启动脚本是哪个,测试目录在哪里,配置文件在哪里等等。从而非常快速的了解这个项目

2、可维护性高:定义好组织规则后,维护者就能明确的知道,新增的哪个文件和代码应该放在什么目录之下。这个好处就是,随着时间的推移,代码/配置的规则增加,项目结构不会混乱,仍然都能够组织良好。

所哟保持一个层次清晰的目录结构是有必要的。更何况组织一个良好的工程目录,其实是一件简单的事。

目录的组织方式

关于如何组织一个较好的Python工程目录结构,已经有一些得到了共识的目录结构。在Stackoverflow的这个问题上,能看到大家对Python目录结构的讨论。

这里面说的已经很好了,我也不打算重新造轮子列举各种不同的方式,这里面我说一下我的理解和体会。

假设你的项目名为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: 项目说明文件。

除此之外,有一些方案给出了更加多的内容。比如LICENSE.txt,ChangeLog.txt文件等,我没有列在这里,因为这些东西主要是项目开源的时候需要用到。如果你想写一个开源软件,目录该如何组织,可以参考这篇文章

关于README的内容

这个我觉得是每个项目都应该有的一个文件,目的是能简要描述该项目的信息,让读者快速了解这个项目。

它需要说明以下几个事项:

  1. 软件定位,软件的基本功能。
  2. 运行代码的方法: 安装环境、启动命令等。
  3. 简要的使用说明。
  4. 代码目录结构说明,更详细点可以说明软件的基本原理。
  5. 常见问题说明。

我觉得有以上几点是比较好的一个README。在软件开发初期,由于开发过程中以上内容可能不明确或者发生变化,并不是一定要在一开始就将所有信息都补全。但是在项目完结的时候,是需要撰写这样的一个文档的。

可以参考Redis源码中Readme的写法,这里面简洁但是清晰的描述了Redis功能和源码结构。

关于requirements.txt和setup.py

setup.py

一般来说,用setup.py来管理代码的打包、安装、部署问题。业界标准的写法是用Python流行的打包工具setuptools来管理这些事情。这种方式普遍应用于开源项目中。不过这里的核心思想不是用标准化的工具来解决这些问题,而是说,一个项目一定要有一个安装部署工具,能快速便捷的在一台新机器上将环境装好、代码部署好和将程序运行起来。

这个我是踩过坑的。

我刚开始接触Python写项目的时候,安装环境、部署代码、运行程序这个过程全是手动完成,遇到过以下问题:

  1. 安装环境时经常忘了最近又添加了一个新的Python包,结果一到线上运行,程序就出错了。
  2. Python包的版本依赖问题,有时候我们程序中使用的是一个版本的Python包,但是官方的已经是最新的包了,通过手动安装就可能装错了。
  3. 如果依赖的包很多的话,一个一个安装这些依赖是很费时的事情。
  4. 新同学开始写项目的时候,将程序跑起来非常麻烦,因为可能经常忘了要怎么安装各种依赖。

setup.py可以将这些事情自动化起来,提高效率、减少出错的概率。"复杂的东西自动化,能自动化的东西一定要自动化。"是一个非常好的习惯。

setuptools的文档比较庞大,刚接触的话,可能不太好找到切入点。学习技术的方式就是看他人是怎么用的,可以参考一下Python的一个Web框架,flask是如何写的: setup.py

当然,简单点自己写个安装脚本(deploy.sh)替代setup.py也未尝不可。

requirements.txt

这个文件存在的目的是:

  1. 方便开发者维护软件的包依赖。将开发过程中新增的包添加进这个列表中,避免在setup.py安装依赖时漏掉软件包。
  2. 方便读者明确项目使用了哪些Python包。

这个文件的格式是每一行包含一个包依赖的说明,通常是flask>=0.10这种格式,要求是这个格式能被pip识别,这样就可以简单的通过 pip install -r requirements.txt来把所有Python包依赖都装好了。具体格式说明: 点这里

关于配置文件的使用方法
注意,在上面的目录结构中,没有将conf.py放在源码目录下,而是放在docs/目录下。

很多项目对配置文件的使用做法是:

  1. 配置文件写在一个或多个python文件中,比如此处的conf.py。
  2. 项目中哪个模块用到这个配置文件就直接通过import conf这种形式来在代码中使用配置。

所以,我认为配置的使用,更好的方式是,

  1. 模块的配置都是可以灵活配置的,不受外部配置文件的影响。
  2. 程序的配置也是可以灵活控制的。

能够佐证这个思想的是,用过nginx和mysql的同学都知道,nginx、mysql这些程序都可以自由的指定用户配置。

所以,不应当在代码中直接import conf来使用配置文件。上面目录结构中的conf.py,是给出的一个配置样例,不是在写死在程序中直接引用的配置文件。可以通过给main.py启动参数指定配置路径的方式来让程序读取配置内容。当然,这里的conf.py你可以换个类似的名字,比如settings.py。或者你也可以使用其他格式的内容来编写配置文件,比如settings.yaml之类的。

python3.5-day5_迭代器_生成器_装饰器_模块的更多相关文章

  1. Python3基础教程(十六)—— 迭代器、生成器、装饰器

    在这个实验里我们学习迭代器.生成器.装饰器有关知识. 这几个概念是 Python 中不容易理解透彻的概念,务必把所有的实验代码都完整的输入并理解清楚其中每一行的意思. 迭代器 Python 迭代器(I ...

  2. python is、==区别;with;gil;python中tuple和list的区别;Python 中的迭代器、生成器、装饰器

    1. is 比较的是两个实例对象是不是完全相同,它们是不是同一个对象,占用的内存地址是否相同 == 比较的是两个对象的内容是否相等 2. with语句时用于对try except finally 的优 ...

  3. python的迭代器、生成器、装饰器

    迭代器.生成器.装饰器 在这个实验里我们学习迭代器.生成器.装饰器有关知识. 知识点 迭代器 生成器 生成器表达式 闭包 装饰器 实验步骤 1. 迭代器 Python 迭代器(Iterators)对象 ...

  4. Python 闭包、迭代器、生成器、装饰器

    Python 闭包.迭代器.生成器.装饰器 一.闭包 闭包:闭包就是内层函数对外层函数局部变量的引用. def func(): a = "哈哈" def func2(): prin ...

  5. python基础之迭代器、生成器、装饰器

    一.列表生成式 a = [0,1,2,3,4,5,6,7,8,9] b = [] for i in a: b.append(i+1) print(b) a = b print(a) --------- ...

  6. 7th,Python基础4——迭代器、生成器、装饰器、Json&pickle数据序列化、软件目录结构规范

    1.列表生成式,迭代器&生成器 要求把列表[0,1,2,3,4,5,6,7,8,9]里面的每个值都加1,如何实现? 匿名函数实现: a = map(lambda x:x+1, a) for i ...

  7. Python开发——7.迭代器、生成器和装饰器

    一.迭代器 1.迭代器协议 (1)迭代器协议是指:对象必须提供一个next方法,执行该方法要么返回迭代中的下一项,要么引起一个StopIteration移除异常以中止迭代. (2)可迭代对象:实现了迭 ...

  8. Python基础4 迭代器,生成器,装饰器,Json和pickle 数据序列化

    本节内容 迭代器&生成器 装饰器 Json & pickle 数据序列化 软件目录结构规范 作业:ATM项目开发 1.列表生成式,迭代器&生成器 列表生成式 孩子,我现在有个需 ...

  9. 详解python三大器——迭代器、生成器、装饰器

    迭代器 聊迭代器前我们要先清楚迭代的概念:通常来讲从一个对象中依次取出数据,这个过程叫做遍历,这个手段称为迭代(重复执行某一段代码块,并将每一次迭代得到的结果作为下一次迭代的初始值). 可迭代对象(i ...

  10. python开发学习-day04(迭代器、生成器、装饰器、二分查找、正则)

    s12-20160123-day04 *:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: ...

随机推荐

  1. 移动端 isScroll自定义实现

    var scroll_flag=null;var goodNum = 11;var i_c = 0;function loadInsuranceList(){ //这里写滚动出来 加载的数据$.aja ...

  2. 安装ntp

    #yum -y install ntp#service ntpd restart#vi /etc/ntp.confserver 0.aisa.pool.ntp.org iburstserver 1.a ...

  3. APP常见崩溃原因和测试方法整理

    测试过APP的人都应该发现,app崩溃是一类非常常见的问题,很多时候还是致命性的,这就要求我们测试人员要尽最大可能去找出软件当中的缺陷,减少app崩溃出现的概率,这里我将收集到的关于针对APP崩溃测试 ...

  4. codeforces 645 E. Intellectual Inquiry

    一个字符串,由前k个字母组成,长度为m + n,其中前m个字符已经确定,后面n个由你自由选择, 使得这个串的不同的子序列的个数最多,空串也算一个子序列. 1 <= m <= 10^6,0 ...

  5. mint安装相关数据库lib

    sudo apt-get install libmysqlclient-dev sudo apt-get install sqlite3 libsqlite3-dev

  6. [Linux编程] module_param()函数学习笔记

    在读TCP cubic源码中,遇到了module_param(),网上查到的资料如下: 在用户态下编程可以通过main()来传递命令行参数,而编写一个内核模块则可通过module_param()来传递 ...

  7. mysql数据库的一些基本操作

    下面列出一些做项目时常用到的一些mysql操作. 1.对数据库的操作 查看所有的数据库:show databases; 新建一个数据库:create database database_name; 此 ...

  8. CentOS 7安装Sublime text3

    最近使用centos7,发现桌面有了大的改善,完全能够使用桌面进行开发.现在进行sublime text3的安装. 官网下载只有windows,ios,ubuntu这几个类型,我们选择ubuntu64 ...

  9. (Array)169. Majority Element

    Given an array of size n, find the majority element. The majority element is the element that appear ...

  10. cocos2dx day 3 - Chapter5 Scene

    写在前面 越来越懒了,才3天,主要是cocos2dx官网的文章写的还是不是太完美,发现一段代码有个笔误,还有好几处写得不是很清楚的,所以有点泄气,不想继续读下去,不过为了我的第一款手游,一切困难都要先 ...