python study day04

1、装饰器:本质是函数,功能:就是为了其他函数添加附加功能

原则:不能修改被装饰的函数的源代码
不能修改被装饰的函数的调用方式
实现装饰器知识储备:
1)、函数即“变量”,即可以像变量一样赋值

2)、高阶函数
a:把一个函数名当做实参传递给另外一个函数(在不修改被装饰函数源代码的情况下为其添加功能)
b:返回值中包含函数名(不修改函数的调用方式)

3)、嵌套函数
就是在一个函数里面定义一个函数
高阶函数+嵌套函数 =》装饰器
def bar()
pass
print(bar) 返回的是函数体的物理地址,即函数名是函数体的门牌号
bar() 表示函数运行
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
带参数的装饰器
在这里插入图片描述
4)、高级装饰器

2、列表生成式

在这里插入图片描述

3、迭代器和生成器

生成器:有一个方法:next()
(1)只有在调用时才会生成相应的数据
(2)只记录当前位置
通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的,而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那么后面绝大多数元素占用的空间都白白浪费了。
所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间,在python中,这种一边循环一边计算的机制,称为生成器:genetator。

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

所以,我们创建了一个generator后,基本上永远不会调用next(),而是通过for循环来迭代它,并且不需要关心stopIteration的错误,generator非常强大,如果推算的算法比较复杂,用类似列表生成式的for循环无法实现的时候,还可以用函数来实现。

在这里插入图片描述
这不是一个函数,而是一个生成器,return的作用是当出现异常时,抛出return 后面的语句,函数里面有yield 语句,则说明不是一个函数。
函数和generator仅一步之遥,只需要把print(b)改成yield b 就可以了

最难理解的就是generator和函数的执行流程不一样,函数是顺序执行,遇到return语句或者最后一行函数语句就返回。而generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句后继续执行。

3.1、可以通过yield实现在单线程的情况下实现并发运算的效果
Next只是唤醒yield
Send可以唤醒yield的同时,给yield赋值
在这里插入图片描述
C=consumer(“chenronghua”)这一步只是把函数变成了生成器,并没有执行这个生成器,当遇到c.next()后才开始执行函数生成器,并遇到yield返回,并停止。
在这里插入图片描述
3.2迭代器
我们已经知道,可以直接作用于for循环的数据类型有以下几种:
一类是集合数据类型, 如list、tuple、dict、set、str等;
一类是generator,包括生成器和带yield的generator function
这些可以直接作用于for循环的对象统称为课迭代对象:iterable.
可以使用isinstance()判断一个对象是否是iterable对象。
Isinstance([ ],Iterable)
返回True
而生成器不但可以作用于for循环,还可以被__next__()函数不断调用并返回下一个值,直到最后抛出StopIteration错误表示无法继续返回下一个值了。

可以被_next__()函数调用并不断返回下一个值的对象称为迭代器:Iterator
可以使用isinstance()判断一个对象是否是Iterator对象。

生成器都是迭代器(Iterator),但是list、dict、str虽然是iterable,却不是Iterator。
把list、dict、str等iterable变成Iterator可以使用iter()函数
a=[1,2,3]
Iter(a)则就是一个迭代器,把它赋给b,则可以用__next__()依次访问

你可能会问,为什么list、dict、str等数据类型不是Iterator?

这是因为python的iterator对象表示的是一个数据流,iterator对象可以被next()函数调用并不断返回下一个数据,直到没有数据时抛出stopiteration错误。可以把这个数据流看做是一个有序序列,但我们却不能提前知道序列的长度,只能不断通过next()函数实现按需计算下一个数据,所以iterator的计算是惰性的,只有在需要返回下一个数据时它才会计算。
Iterator甚至可以表示一个无限大的数据流,例如全体自然数,而使用list是永远不可能存储全体自然数的。
小结:
凡是可作用于for循环的对象都是iterable类型;
凡是可作用于next()函数的对象都是iterator类型,它们表示一个惰性计算的序列;
集合数据类型如list、dict、str等是iterable但不是iterator,不过可以通过iter()函数获得一个iterator对象

Python的for循环本质上就是通过不断用next()函数实现的。
在这里插入图片描述
字符串和二进制不能修改,只能生成新的覆盖原来的

4、内置方法

1、all() 当可迭代对象的所有元素都为True,则返回True,否则返回False。

2、any() 当可迭代对象的任意一个元素为True,则返回True,否则返回False。

3、ascii()

4、bin() 把十进制转为二进制

5、bytearray() 把二进制变成数组的二进制

6、callable() 判断是否可被调用,即是否可以加(),函数和类是可以调用的

7、chr() 返回数字所对应的ASCII对应返回

8、ord() 返回ASCII码对应的数字

9、filter() 和匿名函数lambda结合使用,过滤出想要的数据
在这里插入图片描述
10、map() 和匿名函数lamdba结合,
在这里插入图片描述
在这里插入图片描述
map() 会根据提供的函数对指定序列做映射。
第一个参数 function 以参数序列中的每一个元素调用 function 函数,返回包含每次 function 函数返回值的新列表。
``map(function, iterable, …)

def square(x) : # 计算平方数 ... return x ** 2 

map(square, [1,2,3,4,5]) # 计算列表各个元素的平方 [1, 4, 9, 16, 25] 

map(lambda x: x ** 2, [1, 2, 3, 4, 5]) # 使用 lambda 匿名函数 [1, 4, 9, 16, 25] # 提供了两个列表,对相同位置的列表数据进行相加 

map(lambda x, y: x + y, [1, 3, 5, 7, 9], [2, 4, 6, 8, 10]) [3, 7, 11, 15, 19] 

11、frozenset()可以把列表转为不可更改的列表

12、hex()把数字转为16进制

13、id()返回id

14、oct() 装为八进制

15、sorted()
在这里插入图片描述
第一个是按key排序,第二个是按value排序
16、zip()
在这里插入图片描述
把两个数据组合起来

17、import() 函数用于动态加载类和函数:
import指令做了两件事:1)搜索module,2)绑定到局部变量
内置函数__import__()只做了一件事:搜索module
 import指令执行过程中是调用__import__()来完成Module检索的。
我们知道模块的名字 可以这样导入
在这里插入图片描述
以上是所有的内置方法、

5、Json & pickle数据序列化

5.1、Json序列化
Json.dumps() 将python对象编码成JSON字符串
Json.loads() 将已编码的JSON字符串解码为python对象
Dump把数据类型转换成字符串并存储在文件中dump(data,f),load把文件打开从字符串转换成数据类型load(f)。
在这里插入图片描述
Json只支持简单的字符串、字典等函数等不支持
dumps一次和loads一次
5.2、pickle 可以支持所有的数据类型 ,用法和Json一样,但是其转化为二进制。

6、shelve模块

Shelve 模块是一个简单的k,v将内存数据通过文件持久化的模块,可以持久化任何pickle可支持的python数据格式。
Shelve 写文件

import shelve
	import datetime

d = shelve.open('shelve_txt')

	info = {'age':23,'job':'sd'}
	name = "safad"
	d['info'] = info
	d['name'] = name
	d['datetime'] = datetime.datetime.now()
	d.close

shelve 读文件
在这里插入图片描述

7、软件目录结构规范

我们设计一个层次清晰的目录结构,就是为了达到以下两点:
1、可读性高:不熟悉这个项目的代码的人,一眼就能看懂目录结构,知道程序启动脚本是哪个,测试目录在哪等等,从而非常快速的了解这个项目
2、可维护想高:定义好组织规则后,维护者就能很明确地知道,新增的那个文件和代码应该放在什么目录下,这样好处是,随着时间的推移,代码/配置的规模增加,项目结构不会混乱,仍能组织良好。

7.1、目录组织方式
在这里插入图片描述

简单解释一下:假设项目的名称为foo
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)、常见问题说明

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也是未尝不可。

Requirement.txt
这个文件存在的目的是:
1)、方便开发者维护软件的包依赖。将开发过程中新增的包添加进去这个列表中,避免在setup.py安装依赖是漏掉软件包。
2)、方便读者明确项目使用了哪些python包。
这个文件的格式是每一行包含一个包依赖的说明,通常是flask>=0.10这种格式,要求是这个格式能被pip识别,这样就可以简单的通过pip install –r requirements.txt来把所有python包依赖都安装好了。

7.2在python文件中添加环境变量
1)、获取当前文件的相对路径
print(file)
2)、获取当前文件的绝对路径
import os
print(os.path.abspath(file))
3)、获取上一级文件的绝对路径
os.path.dirname(os.path.abspath(file))
4)、添加环境变量

	import sys
	import os
	BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
	sys.path.append(BASE_DIR)

sys.path.append(BASE_DIR)是把BASE_DIR添加到sys.path列表后面,可以用inster()添加到前面

8、匿名函数

一般一下情况多考虑使用匿名函数:
1)程序一次性使用、不需要定义函数名时,用匿名函数可以节省内存中变量定义空间。
2)如果想让程序更加简洁,使用匿名函数就可以做到。
当然,匿名函数有3个规则要记住:
1)一般有一行表达式,必须有返回值。
2)不能有return。
3)可以没有参数,也可以有一个或多个参数。

作业:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值