python高阶编程(一)
虚拟环境及编码规范
环境管理
一、虚拟环境介绍
二、virtualenv的安装和应用
安装步骤(mac)
-
pip安装virtualenv:
pip3 install virtualenv -
pip安装虚拟环境管理包virtualenvwrapper:
pip3 install virtualenvwrapper -
创建一个存放虚拟环境的目录(建议 命名为.env或者.virtualenv):
mkdir ~/.virtualenv -
配置环境变量
进入环境变量配置文件:
vim ~/.bash_profile添加如下配置:
# 配置python虚拟环境 export WORKON_HOME=~/.virtualenv # 路径使用命令 which python3 获取 export VIRTUALENVWRAPPER_PYTHON=/usr/local/bin/python3 # 路径使用命令 which virtualenvwrapper.sh 获取 source /usr/local/bin/virtualenvwrapper.sh执行
source ~/.bash_profile使配置生效
virtualenv常用命令
电脑上同时装有python2和python3时:
在python2中,创建虚拟环境:mkvirtualenv -p python2 虚拟环境名称
在python3中,创建虚拟环境:mkvirtualenv -p python3 虚拟环境名称
pip list 已安装的包,非虚拟环境中,展示本地的安装包,进入虚拟环境输入该命令,展示该虚拟环境的包。
在虚拟环境中,使用pip install也仅在虚拟环境中安装包。
三、pipenv的安装与使用
pipenv是对pip命令和virtualenv的封装,不需要配置环境变量
如果我们没有存放虚拟环境的路径,他会自动生成一个,由于我们之前装virtualenv时创建了存放虚拟环境的路径,使用pipenv时不会生成新的存放路径。
项目目录下,输入pipenv install 安装虚拟环境。 (后面不带包名)
虚拟环境安装成功后,会生成一个Pipfile和Pipfile.lock文件,记录相关依赖包的。
Pipfile.lock文件,原则上是不能进行修改。
Pipfile文件中,url表示源地址,默认是国外源,可以换成国内源。
可换成清华源:pypi.tuna.tsinghua.edu.cn/simple
pipenv install 包名 包安装在默认环境[packages]下
pipenv install 包名 --dev 包安装在开发环境[dev-packages]下
使用pipenv graph查看包的依赖,比如安装了requests包,这个包依赖了下面四个包:
复制Pipfile和Pipfile.lock文件到另一个工程下,使用pipenv install 安装虚拟环境时,会自动安装上Pipfile文件下[packages]下的包
若想安装[dev-packages]下的包,使用命令pipenv install --dev
pipenv命令,只在当前路径下运行,所以,下面命令需进入到对应目录下运行:
四、requirements.txt文件
使用virtualenv管理虚拟环境,使用下述命令导出requirments.txt文件和恢复虚拟环境:
pipenv除了可以通过Pipfile和Pipfile.lock文件进行恢复虚拟环境,也可以使用requirments.txt文件方式恢复虚拟环境:
在pipenv中使用pipenv lock -r>requirments.txt 生成requirments.txt,恢复dev的包,命令为pipenv lock -r --dev>requirments.txt
使用pipenv install -r requirments.txt安装环境
编码规范
一、python代码规范
-
PEP 8(python代码样式规范)
官方: www.python.org/dev/peps/pe…
中文翻译版: blog.csdn.net/ratsniper/a…
主要:
标准库,不用pip安装的。相关的第三方库,需要pip进行安装的。
mac下调整代码格式快捷键:
command+option+L格式化代码(L大写小写都可以) -
PEP 257(python文档说明的书写语义和约定)
官方: www.python.org/dev/peps/pe…
中文翻译版: blog.csdn.net/xtydtc/arti…
-
PEP 20(python的禅宗)
官方: www.python.org/dev/peps/pe…
项目结构
一、工程结构化
根据项目不同会有所不同,大致如是,开源项目广泛用。
数据类型&函数进阶
数据类型
python数据类型:
数值:
序列:字符串、元组、列表
散列(特征:内部元素是无序):字典、集合
一、元组和列表
-
元组和列表的性能分析
ipython是一个python的交互式shell,比默认的python shell好用得多。
安装ipython
sudo pipenv install ipython(mac不加sudo不能安装)安装好后输入
ipython进入shell:配合timeit模块,这分别是计算初始化一个列表和元组1000000次的时间:
元组比列表的性能快很多。
列表是可变的,在内存中,开辟一块空间,当检测到列表元素快占满那块空间时,会自动给列表扩容。
元组是不可变,内存分配了固定空间,所以更快。
拓展:timeit模块,可以用于计算代码性能,如自己编写的函数等。
import timeit # 初始化列表,如无参数,默认次数为100w次 list_speed = timeit.timeit('[1,2,3,4,5,6]') # 初始化元组,如无参数,默认次数为100w次 tuple_speed = timeit.timeit('(1,2,3,4,5,6)') print(list_speed) print(tuple_speed) def func_speed(): for i in range(10): print(i) # 调用func_speed方法,100次所需要的时间 res = timeit.Timer(func_speed).timeit(1000) print(res) -
命名元组
使用
collections.namedtuple函数,来构造一个带字段名的元组:from collections import namedtuple # 创建一个具名元组,需要两个参数,一个是类名,另一个是类的各个字段名 stu_info = namedtuple("stu_info",['name','age','gender']) # 创建一个stu_info对象 student_info = stu_info("susan",19,"男") print(student_info) # 类型 print(type(student_info)) # <class '__main__.stu_info'> ,即在namedtuple中定义的类名。 # 类似与对象的取值方式 print(student_info.name,student_info.age,student_info.gender)
二、字典和集合的原理和应用
集合和字典的常用使用方法
# 空集合
set_blank = set()
# 空字典
dict_blank = {}
# 利用集合对列表进行去重
list1 = [1,1,1,2,3,3,2,5]
list2 = list(set(list1))
print(list2)
-
散列类型的存储过程
集合和字典都是无序的,称之为散列类型。
一个知识点更新:python3.7之前,字典是无序的,3.7之后新特性,字典会按你添加的顺序保存,实际有顺序了。
-
字典查找值的过程
三、推导式
-
列表推导式
-
字典推导式
使用字典推导式把字符串改成字典类型数据
str = 'name=susan,gender=女,school=上海某大学' dict1 = {i.split("=")[0]:i.split("=")[1] for i in str.split(",")} print(dict1)
迭代器和生成器
-
生成器
使用生成器,可用于节约内存。什么时候用,什么时候取,用哪个,取哪个。
使用
next()就计算出下一个元素的值。直到计算到最后一个元素,没有更多的元素时,抛出StopIteration的错误。# 通过yield自定义生成器 def gen_func(): yield 100 print("hello yield") yield 110 yield 119 res = gen_func() # 返回生成器对象 print(res) print(next(res)) # 输出第一个yield后的值 print(next(res)) # 输出第二个yield后的值 print(next(res)) # 输出第三个yield后的值 -
迭代协议
-
迭代器
可迭代对象:可以for循环遍历的都是可迭代对象。内部只实现了__iter__方法。
迭代器:可以通过next()取值的。内部只实现了__iter__之外,还实现了__next__方法。
如,列表是一个可迭代对象,但不是一个迭代器。可以通过iter(),把一个可迭代对象转为迭代器。
list1 = [1,2,3,4,4,5] li = iter(list1) # 通过iter() ,触发list类里的__iter__方法 print(next(li)) # 触发了li这个对象中的__next__方法 print(next(li))生成器是迭代器的一种。生成器和迭代器的区别:
高阶函数
-
递归函数
# 递归函数实现斐波那契数列 def fib(n): if n <= 1: return 1 else: return fib(n-1)+fib(n-2) -
纯函数
常用内置函数
内置函数官网: docs.python.org/zh-cn/3.7/l…
filter():一个参数是过滤的方法、第二个参数为序列,序列的每一个参数带入到过滤方法中,为True的返回,为False的过滤掉。一般使用匿名函数进行定义,此处只是为了更明白filter()的过程。
map():会根据提供的函数对指定序列做映射。第一个参数 function 以参数序列中的每一个元素调用 function 函数,返回包含每次 function 函数返回值的新列表。
# 内置函数filter()、map()
li = [1, 2, 5, 10, 2, 22]
def filter_li(n):
return n >= 5
print("filter函数的结果:{}".format(list(filter(filter_li, li))))
print("map函数的结果:{}".format(list(map(filter_li, li))))
zip():函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表。如果各个迭代器的元素个数不一致,则返回列表长度与最短的对象相同,利用 * 号操作符,可以将元组解压为列表。
# 内置函数zip()
zip1 = zip([1,2,3],[11,22,33],[111,222,333])
zip2 = zip([1,2,3,4],[11,22,33,44],[111,222,333,444,555])
zipped = zip([1,2,3],[4,5,6])
# 将对象中对应的元素打包成一个个元组
print(list(zip1))
# 如果各个迭代器的元素个数不一致,则返回列表长度与最短的对象相同
print(list(zip2))
# 使用*解压
print(list(zip(*zipped)))
-
匿名函数
节约内存,即用即释放,所以不推荐把方法赋值给变量,推荐直接调用。
与filter()函数结合使用,省内存,阅读更舒适:
li = [1, 2, 5, 10, 2, 22] print("filter函数的结果:{}".format(list(filter(lambda n:n>=5,li))))
闭包、偏函数、数据锁定
-
偏函数
-
闭包
对外层函数非全局的变量会储存在自身的
__closure__中,实现数据锁定,提高稳定性。 -
装饰器
先有index()功能,现在需要在网站首页前增加账号和密码验证。不改变调用方法,使用装饰器进行新增功能。
# 装饰器 def login(func): def verity(): username = input("请输入username:") password = input("请输入password:") if username == 'leitx' and password=='123': func() else: print("账号或密码错误") return verity @login # 语法糖:相当于index = login(index),所以调用index(),实际相当于调用verity函数 def index(): print("展示首页") index()参数传递示意:
通用装饰器
def outer(func): def check(*args,**kwargs): print("在原index()方法前面操作的代码") func(*args,**kwargs) print("在原index()方法后面操作的代码") return check @outer def index(*args,**kwargs): print("原本的功能实现") index()装饰类的装饰器
多个装饰器装饰同一个函数
从下往上装饰,先装饰wrapper,再装饰login_check,结果导致代码从上往下运行:先运行login_check中的代码,再运行wrapper中的代码,再运行func中的代码。
python中类里面三个内置的装饰器
-
@classmethod 类方法
装饰了classmethod的方法,不需要self参数,此时的self指向了类。而没有装饰classmethod的方法,self是实例本身:
装饰了classmethod的方法,参数应该是cls,cls代表了类本身:
类方法可以直接使用类调用
MyTest.add()和实例调用MyTest().add()。 -
@staticmethod 静态方法
不用传self参数
-
@property
这个装饰器装饰的方法,可以像属性一样被调用。一般用于设置只读属性。
通过调用
MyTest().read_attr调用,不可对MyTest().read_attr进行修改,所以一般用于设置只读属性。
用类实现装饰器(魔法方法时讲)
-