此内容为之前学习python时做的知识笔记

python必背100源代码(python基础知识笔记)(1)

人生苦短,我用python

以守护进程运行python脚本,python test1.py &

1.基础知识1.0 包package

python package需要有一个名为init.py的文件,不然就是普通的package,则无法import package下的模块。可以在init.py文件里写入要被使用的模块,这样import package时,系统会直接去init.py里面寻找模块或者函数。

1.1 变量命名规则

python变量名只能包含以下字符:大小写字母、数字、下划线(_),名称不允许以数字开头。并且以下划线开头的名字有特殊含义。

1.2 可变对象与不可变对象1.3python容器

创建列表:a=[],a=list() 赋值:a=[],b=a 此时,a,b共享同一个对象。 复制(新表):a=[],b=a.copy(),c=list(a),d=a[:] 此时b,c,d是新的对象,不共享,和a没有任何关系。属于浅复制;浅复制只复制一层(外层)

创建元组:a=(),a=tuple() a=(1,)等价于a=1, 元组元素不可更改

创建字典:a={},a=dict() 复制:copy() 赋值:=

创建集合:a=set(),a={1} 集合运算:交集(&),并集(|),差集(-)

1.4 格式化

Python有两种格式化方式,习惯称为旧式和新式;这两种方式在python2和python3中都适用。

旧式格式化的形式为:string % data,其中string包含的是待插值序列。

>>> '%s'%4.12 '4.12' >>> '%f'%4.12 '4.120000' >>> "my name is %s,age is %d "%('ss',14) 'my name is ss,age is 14 ' >>> "d f s"%(12,11,'dad') #设置最小域宽度为10格字符,左侧用空格补充 ' 12 11.000000 dad' >>> "%-10d %-10f %-10s"%(12,11,'dad') #左对齐 '12 11.000000 dad ' >>> '%.4f %.3d'%(12.13131,11) #数据截断,设置最大字符宽度 '12.1313 011'

>>> '{}{}'.format(12,13) '1213' >>> '{1}{0}'.format(12,13) #指定插入的顺序,参数从0开始。 '1312' >>> '{m}{n}'.format(n=12,m=13) #命名变量参数 '1312' >>> '{1:d} {0:f}'.format(12,13) #使用:实现格式化类型 '13 12.000000' >>> '{1:<4d} {0:<5f}'.format(12,13) #左对齐<,右对齐>,居中^ '13 12.000000' >>> '{1:^4d} {0:<5.3f}'.format(12,13) #精度和旧式一样,但也有不同 ' 13 12.000' >>> '{:^4.3}'.format(12) #新格式中无法对整数设定精度 Traceback (most recent call last): File "<stdin>", line 1, in <module>

1.5 代码注释

#单行注释1 print(123)#单行注释2 #多行注释1 #ddd #ddd #ddd ''' 多行注释2 ddd '''

1.6 python2 VS python31.6.1 print

在python3中,print是函数,使用 print('helloworld') 不换行输出,print("hello",end="") print("world") 输出:helloworld 在python2中,print是关键字,print "helloworld" 不换行输出,pring "hello", print "world" 输出:hello world (以空格分割)

1.6.2 input

--------python2 >>> a=input() #会做计算处理 12 >>> print a,type(a) 12 <type 'int'> >>> a=raw_input() #对输入都以字符串处理 12 >>> print a,type(a) 12 <type 'str'> >>> --------python3 >>> a=input() 12 >>> print(a) 12 >>> print(type(a)) #所有输入都作为字符串处理 <class 'str'> >>>

1.6.3 整除

-----------python2 >>> print 5/2 #向下取整 2 -----------python3 >>> print (5/2) #默认进行浮点数除法 2.5 >>> print (5//2) #取模 2

1.6.4 range

-------------python2 >>> print range(4) #返回列表 [0, 1, 2, 3] ------------python3 >>> print(range(4)) #返回range对象 range(0, 4) #循环访问py2和py3基本一样

1.6.5 字符串

python3表示字符串的两种类型:bytes和str,前者的实例包含原始的8位值(一个字节),后者实例包含Unicode字符。 python2表示字符串的两种类型:unicode和str,前者包含Unicode字符,后者包含原始的8位值。 二进制转化为Unicode字符,使用decode;Unicode字符转二进制,使用encode。

1.6.6 列表推导产生的变量泄漏问题

>>> x = 'my precious' >>> dummy = [x for x in 'ABC'] >>> x 'C' >>> dummy ['A', 'B', 'C']

>>> x = 'my precious' >>> dummy = [x for x in 'ABC'] >>> x 'my precious' >>> dummy ['A', 'B', 'C']

python2中,在列表推导中同名变量的赋值可能会影响上下文环境;而在python3中,都有自己的局部作用域。使用生成器则不会出现这种变量泄漏的问题。

1.6.7 import

python2默认是按照相对路径导入模块和包,python3默认则是按照绝对路径导入。python2引入一个module时会先在当前目录搜索,然后再去搜索路径(sys.path)搜索;而python3直接在搜索路径搜索,为了导入,使用显式路径导入。

Python2.x 缺省为相对路径导入,Python3.x 缺省为绝对路径导入。绝对导入可以避免导入子包覆盖掉标准库模块(由于名字相同,发生冲突)。如果在 Python2.x 中要默认使用绝对导入,可以在文件开头加入如下语句:

from __future__ import absolute_import

这句 import 并不是指将所有的导入视为绝对导入,而是指禁用 implicit relative import(隐式相对导入), 但并不会禁掉 explicit relative import(显示相对导入)。

from .foo import Foo #python2、3都适用 from .bar import Bar #python2、3都适用 #from mdl.foo import Foo #python2、3都适用 #from mdl.bar import Bar #python2、3都适用 #from foo import Foo #python3不适用 #from bar import Bar #python3不适用

1.6.8 Exception

py2 : except exc, varpy3 : except exc as var,使用 as 作为关键词

1.6.9 不等运算符

Python 2.x中不等于有两种写法 != 和 <>Python 3.x中去掉了<>, 只有!=一种写法

1.6.10 dict方法

py2中dict的keys()、items()、values() 是列表,iteritems()返回迭代器py3中dict的keys()、items()、values() 是类或迭代器,非基础数据类型,执行json的加解密时,需要注意py3中iteritems() 和 viewitems() 这两个方法都已经废除了,而items()得到的结果是和py2里面viewitems()一致的。在py3里用items()替换iteritems() ,可以用于for来循环遍历

1.6.11 数据类型

在Python2中long是比int取值范围更大的整数,Python3中取消了long类型,int的取值范围扩大到之前的long类型范围。python3版本中增加了bytes类型

1.6.12 重载

当我们想对python中原有的模块进行覆盖,又不希望退出当前的程序,就需要用到重载的概念

# python2 内置函数 reload(module) # python3 from importlib import reload reload(module)

1.7 项目依赖库安装1.8 用venv 配置不同的开发环境

python3内置了用于创建虚拟环境的venv,可直接使用python3 -m venv .venv(Linux下)

py -3 -m venv .venv

virtualenv --python=/usr/local/bin/python3 env3 #创建指定python版本的虚拟环境 --python 指定python解释器

1.9.代码风格1.10.新式类和旧式类

python2中既有新式类又有旧式类,并且默认为经典类,只有显示继承object才是新式类。

class a(Object):pass #新式类写法 class a():pass #经典类(旧式类)写法 class a:pass #经典类写法 类.mro() #查看解析顺序列表,只有新式类有该属性。 ---------------------------------------------------------------------- class a(): pass c=a() print dir(c) ---------------------------------out ['__doc__', '__module__'] class a(object): pass c=a() print dir(c) ---------------------------- ---out ['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__'] *:在编写python类时,尽量使用新式类,其包含更多属性。

python3中只有新式类,默认式新式类,不必显式继承object。新式类增加了slots内置属性, 可以把实例属性的种类锁定到slots规定的范围之中。

如果类是经典类,在多继承的情况下,会按照深度优先方式查找;如果类是新式类,在多继承的情况下,会按照广度优先方式查找;

1.11.python序列化

什么叫序列化——将原本的字典、列表等内容转换成一个字符串的过程就叫做序列化。json是可以在不同语言之间交换数据的,而pickle只在python之间使用。json只能序列化最基本的数据类型,而pickle可以序列化所有的数据类型,包括类,函数都可以序列化。

序列化的目的:

1.11.1 Json序列化

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

Python

JSON

dict

object

list, tuple

array

str, unicode

string

int, long, float

number

True

true

False

false

None

null

JSON

Python

object

dict

array

list

string

unicode

number (int)

int, long

number (real)

float

true

True

false

False

null

None

-----------------------------loads和dumps--------------------------- import json dic = {'k1':'v1','k2':'v2','k3':'v3'} str_dic = json.dumps(dic) #序列化:将一个字典转换成一个字符串 print(type(str_dic),str_dic) #<class 'str'> {"k3": "v3", "k1": "v1", "k2": "v2"} #注意,json转换完的字符串类型的字典中的字符串是由""表示的 dic2 = json.loads(str_dic) #反序列化:将一个字符串格式的字典转换成一个字典 #注意,要用json的loads功能处理的字符串类型的字典中的字符串必须由""表示 print(type(dic2),dic2) #<class 'dict'> {'k1': 'v1', 'k2': 'v2', 'k3': 'v3'} list_dic = [1,['a','b','c'],3,{'k1':'v1','k2':'v2'}] str_dic = json.dumps(list_dic) #也可以处理嵌套的数据类型 print(type(str_dic),str_dic) #<class 'str'> [1, ["a", "b", "c"], 3, {"k1": "v1", "k2": "v2"}] list_dic2 = json.loads(str_dic) print(type(list_dic2),list_dic2) #<class 'list'> [1, ['a', 'b', 'c'], 3, {'k1': 'v1', 'k2': 'v2'}] -------------------------load和dump---------------------------- import json f = open('json_file','w') dic = {'k1':'v1','k2':'v2','k3':'v3'} json.dump(dic,f) #dump方法接收一个文件句柄,直接将字典转换成json字符串写入文件 f.close() f = open('json_file') dic2 = json.load(f) #load方法接收一个文件句柄,直接将文件中的json字符串转换成数据结构返回 f.close() print(type(dic2),dic2

1.11.2 pickle序列化

用于python特有的类型 和 python的数据类型间进行转换。pickle操作文件时,需要以二进制的方式操作。

import pickle dic = {'k1':'v1','k2':'v2','k3':'v3'} str_dic = pickle.dumps(dic) print(str_dic) #一串二进制内容 dic2 = pickle.loads(str_dic) print(dic2) #字典 import time struct_time = time.localtime(1000000000) print(struct_time) f = open('pickle_file','wb') pickle.dump(struct_time,f) #f.write(pickle.dumps(struct_time)) f.close() f = open('pickle_file','rb') struct_time2 = pickle.load(f) #struct_time2=pickle.loads(f.read()) print(struct_time2.tm_year)

1.11.3 json序列化非基本数据类型

如果目标对象是基本数据类型,则不会执行转换方法

import json class Info(object): def __init__(self,name,age): # super().__init__() self.name=name self.age=age info=Info("selfeasy",12) #由于json不支持将对象转为为序列化对象,所以需要做转换处理,实现default方法 '''两种转换方式 1. 实现default参数所指定的方法 2. 继承JSONEncoder,并实现default方法 ''' # 1. 实现default方法, 当反序列化时,为了保持原来的目标对象,需要实现object_hook所指向的函数方法 def makeJson(obj): return dict(name=obj.name,age=obj.age) def load_Json(obj): return Info(obj['name'], obj['age']) a=json.dumps(info, default=makeJson) print(a) print(json.loads(a,object_hook=load_Json)) # 2.继承JSONEncoder,实现default方法 class JsonMake(json.JSONEncoder): def default(self, o): if isinstance(o,Info): return dict(name=o.name,age=o.age) return super().default(o) a=json.dumps(info, cls=JsonMake) print(a) print(json.loads(a,object_hook=load_Json))

1.12.猴子补丁(Monkey patch)

在动态语言中,不去改变源码而对功能进行追加和变更,是在程序运行的过程中去修改。1.追加功能 2.功能变更 3.修正程序错误4.增加钩子,在执行某个方法的同时执行一些其他的处理,如打印日志,实现AOP等。

class XiaoMing(object): def favorite(self): print "apple" class God(object): @classmethod def new_xiaoming_favorite(cls): print "banana" @classmethod def monkey_patch(cls): XiaoMing.favorite = cls.new_xiaoming_favorite God.monkey_patch() xiaoming = XiaoMing() xiaoming.favorite() >> banana

1.13.上下文管理器

上下文管理器是一个对象,为操作提供了额外的上下文消息,以一种优雅的方式将额外的处理封装起来。如果一个类实现了__enter__和__exit__方法则表明该类的实例是一个上下文管理器。上下文管理器通常和with搭配使用。实现上下文管理器的两种方式:类和装饰器

class context(object): def __init__(self): print ('上下文管理器初始化') def __enter__(self): print("上下文管理器开始执行") return self def __exit__(self,exec_type, exec_value, exec_traceback): print ("上下文执行结束") def operator(self): print (1/2) with context() as obj: obj.operator() --------------------------------out 上下文管理器初始化 上下文管理器开始执行 0.5 上下文执行结束

备注 :当operator改为1/0时,程序执行后抛出异常;但是当在exit方法中返回True时(默认为False),程序不会报错,因为结果返回true就表示告诉python解释器,异常已捕获并解决,不需要往外抛了。

from contextlib import contextmanager from traceback import format_exc @contextmanager def context(a,b): print ("上下文管理器开始运行") #enter方法 f=a/b try: yield f except Exception: print ("处理异常") finally: print("finally") with context(1,2) as f: print (123) print(f) ----------------------------------out 上下文管理器开始运行 123 0.5 finally

备注:try之前的代码会在装饰器的__enter__方法中执行;当执行到yield时,它的产出值会作为__enter__的返回值,赋值给as后的变量。当with块的代码执行完成后,上下文管理器会在yield处恢复,继续执行yield后的代码,后面的代码在装饰器的__exit__方法中被调用。当程序发生异常时,后面的代码不会执行(包括finally代码)

上下文管理器类与@contextmanager中最大的区别在于对异常的处理。以类的方式实现的上下文管理器,在引发异常时,exit方法内的代码仍会正常执行;而以生成器函数实现的上下文管理器,在引发异常时,exit方法会将异常传递给生成器,如果生成器无法正确处理异常,则yield之后的代码不会执行。

1.14. 可散列的数据类型

如果一个对象是可散列的,那么在这个对象的生命周期中,它的散列值是不变的,而且这个对象需要实现 __hash__() 方法。另外可散列对象还要有 __eq__() 方法,这样才能跟其他键做比较。如果两个可散列对象是相等的,那么它们的散列值一定是一样的。原子不可变数据类型(str、bytes 和数值类型)都是可散列类型。

1.15. Python 运行时

python -m xxx #相当于import,当作模块运行,当前脚本路径不会加入到sys.path中。 python xxx.py #直接运行,当前脚本路径会加入到sys.path中。 python -m site #显示sys.path的值内容,即python搜索模块的目录

1.16. 原地操作

许多运算符都有原地操作,如add方法对应的原地操作是iadd。python中的运算符和operator模块中的函数是对应的

对于不可变的目标如字符串、数字、元组等,当调用一个原地方法是,分两步执行,运算和赋值。当调用原地函数时,只执行运算嘛,不执行赋值操作。如下:

>>> import operator >>> a="hello" >>> operator.iadd(a, ' world')#若要更新变量,则需要执行赋值操作,即a=operator.iadd(a, ' world') 'hello world' >>> a 'hello'

>>> import operator >>> s = ['h', 'e', 'l', 'l', 'o'] >>> iadd(s, [' ', 'w', 'o', 'r', 'l', 'd']) ['h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd'] >>> s ['h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd']

1.17 python -c 和-m区别

0. python xxx.py 直接运行 1. python -m xxx.py当作模块执行,相当于import 2. python -c 当作命令,脚本执行

1.18 查看包搜索路径的几种方法

import sys from pprint import pprint pprint(sys.path)

python -c "import sys;print sys.path"

python -m site

1.19 快速构建HTML帮助文档

python -m pydoc -p 8180 #开启本地http服务

1.20 字符串转义

正则表达式re中就用到了转义

当字符串中使用到特殊字符时,有时候我们不想让其发生转义,而想原样式输出,我们可以使用r字符来定义原始字符串。如下:

str = 'Python\nJava' print(str) # out Python Java str = r'Python\nJava' print(str) # out Python\nJava

2.错误解决方法2.1 ImportError错误
  1. 普通的package和python packae

错误分析</strong>:from package import xxx 时,package无法被识别为python package 解决办法:在package下新建__init__.py即可,此时package被视为python package

  1. 循环导入

from a inport b # module a from b import a # module b

解决办法:

  1. 在模块的最后使用import语句。
  2. 在函数内导入模块(即使用到该模块内容的函数内部)
,