记录python中的一些小知识,备忘
##一个小错误
程序一直运行不成功,总是报错说xx模块下没有xx, 我就郁闷了半天,最后发现工作目录下有一个与导入模块重名的文件,真是毙了狗了
##了解过的几个module random,os,math,requests,re,sys,urllib,smtplib,argparse,bs4,queue,threading,StringIO,collections,tornado pickle,zipfile,socketserver,xmlrpc,image..
##a,b=b,a+b 这玩意相当于先计算b,a+b再赋值
#yield send方法 对于 value = (yield n) 一开始执行的时候返回n的值 并将n的值给value 后挂起 如果收到send方法的值则不改变n依旧返回n的值 使得value = send的值
##2**3 直接计算次方,也可以使用pow(2,3)
##round() 对某一位进行四舍五入
##print不换行 printf(“233”,end=’’)
##字符编码问题 ord()可以获得一个字符的十进制表示 chr()可以将十进制变为字符 可以使用sys.getdefaultencoding()来获得默认编码 我这里的 python 3.4默认使用的是utf-8编码 可以在开头加一行# -- coding: utf-8 --
##关于bytes 要复制的内容中有\x的这种明显bytes类型的应该直接使用b’‘,否则如果当成字符串赋值给s的话,会因为\而乱七八糟引起错误的
###Python3中内置类型bytes和str用法及byte和string之间各种编码转换 Python 3最重要的新特性大概要算是对文本和二进制数据作了更为清晰的区分。文本总是Unicode,由str类型表示,二进制数据则由bytes类型表示。Python 3不会以任意隐式的方式混用str和bytes,正是这使得两者的区分特别清晰。你不能拼接字符串和字节包,也无法在字节包里搜索字符串(反之亦然),也不能将字符串传入参数为字节包的函数(反之亦然).
####python3.0中怎么创建bytes型数据 bytes([1,2,3,4,5,6,7,8,9]) bytes(“python”, ‘ascii’) # 字符串,编码
>>>website = 'http://www.169it.com/os'
>>>type(website)
<class 'str'>
>>>website
'http://www.169it.com/os'
>>>website_bytes_utf8 = website.encode(encoding="utf-8")
>>>type(website_bytes_utf8)
<class 'bytes'>
>>>website_bytes_utf8
b'http://www.169it.com/os'
>>>website_bytes_gb2312 = website.encode(encoding="gb2312")
>>>type(website_bytes_gb2312)
<class 'bytes'>
>>> website_bytes_gb2312
b'http://www.169it.com/os'
>>>website_string = website_bytes_utf8.decode()
>>>type(website_string)
<class 'str'>
>>>website_string
'http://www.169it.com/os'
>>>website_string_gb2312 = website_bytes_gb2312.decode("gb2312")
>>>type(website_string_gb2312)
<class 'str'>
>>>website_string_gb2312
'http://www.169it.com/os'
print ("=-=",max)
print (r'''
QAQ
''')
##list,tuple,dict
list中添加,删除元素的有append,pop,delete,insert 字符串的join()方法可以把一个 list 拼接成一个字符串。 事实上join()很好用,’‘.join(x for x in y if x in string.ascii_letters)就可以方便的筛选出y中的字母 zip()函数可以把两个 list 变成一个 list 一个小例子,用来生成字典解密:cypher = dict(zip(string.ascii_lowercase,string.ascii_lowercase[2:]+string.ascii_lowercase[:2])) print ““.join(cypher.get(c,c) for c in codedmessage) enumerate() 函数把: [‘Adam’, ‘Lisa’, ‘Bart’, ‘Paul’] 变成了类似: [(0, ‘Adam’), (1, ‘Lisa’), (2, ‘Bart’), (3, ‘Paul’)] 因此,迭代的每一个元素实际上是一个tuple:
tuple元素”不可变”,但是如果元素中有List,那么这个list中的元素还是可以变动的
dict添加元素很简单d[“key”] = value 删除元素del d[“key”] 保存添加顺序的字典dict = collections.OrderedDict() ##set集合
set 持有一系列元素,这一点和 list 很像,但是set的元素没有重复,而且是无序的,这点和 dict 的 key很像。 创建 set 的方式是调用 set() 并传入一个 list,list的元素将作为set的元素 set添加的元素必须是不可变对象,添加add,删除remove 我们可以利用这一点去掉list中的重复的数据
set([1,1,2,3,2,4])
##切片操作
字符串 ‘xxx’和 Unicode字符串 u’xxx’也可以看成是一种list,每个元素就是一个字符。因此,字符串也可以用切片操作,只是操作结果仍是字符串:
‘ABCDEFG’[:3] ‘ABC’ ‘ABCDEFG’[-3:] ‘EFG’ ‘ABCDEFG’[::2] ‘ACEG’ 在很多编程语言中,针对字符串提供了很多各种截取函数,其实目的就是对字符串切片。Python没有针对字符串的截取函数,只需要切片一个操作就可以完成,非常简单。
##迭代
在Python中,如果给定一个list或tuple,我们可以通过for循环来遍历这个list或tuple,这种遍历我们成为迭代(Iteration)。 在Python中,迭代是通过 for … in 来完成的,而很多语言比如C或者Java,迭代list是通过下标完成的,比如Java代码:
for (i=0; i < list.length; i++){
n = list[i];
}
可以看出,Python的for循环抽象程度要高于Java的for循环。 因为 Python 的 for循环不仅可以用在list或tuple上,还可以作用在其他任何可迭代对象上。 因此,迭代操作就是对于一个集合,无论该集合是有序还是无序,我们用 for 循环总是可以依次取出集合的每一个元素。
注意: 集合是指包含一组元素的数据结构,我们已经介绍的包括:
##cmp()函数在python3中莫有了 这几个函数就是用来替换之前的cmp的.
lt(a, b) 相当于 a < b
le(a,b) 相当于 a <= b
eq(a,b) 相当于 a == b
ne(a,b) 相当于 a != b
gt(a,b) 相当于 a > b
ge(a, b)相当于 a>= b
函数的返回值还是跟cmp一样,返回的是数值。
##列表生成式
要生成list [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],我们可以用range(1, 11):
range(1, 11) [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 但如果要生成[1x1, 2x2, 3x3, …, 10x10]怎么做?方法一是循环: L = [] for x in range(1, 11): … L.append(x * x) … L [1, 4, 9, 16, 25, 36, 49, 64, 81, 100] 但是循环太繁琐,而列表生成式则可以用一行语句代替循环生成上面的list: [x * x for x in range(1, 11)] [1, 4, 9, 16, 25, 36, 49, 64, 81, 100] 这种写法就是Python特有的列表生成式。利用列表生成式,可以以非常简洁的代码生成 list。 列表生成式的 for 循环后面还可以加上 if 判断。例如: [x * x for x in range(1, 11)] [1, 4, 9, 16, 25, 36, 49, 64, 81, 100] 如果我们只想要偶数的平方,不改动 range()的情况下,可以加上 if 来筛选: [x * x for x in range(1, 11) if x % 2 == 0] [4, 16, 36, 64, 100] 有了 if 条件,只有 if 判断为 True 的时候,才把循环的当前元素添加到列表中。
dict 对象有一个 values() 方法,这个方法把dict转换成一个包含所有value的list,这样,我们迭代的就是 dict的每一个 value: d = { ‘Adam’: 95, ‘Lisa’: 85, ‘Bart’: 59 } print d.values()
for v in d.values(): print v # 85 # 95 # 59 如果仔细阅读Python的文档,还可以发现,dict除了values()方法外,还有一个 itervalues() 方法,用 itervalues() 方法替代 values() 方法,迭代效果完全一样:
##高阶函数map() map()是 Python 内置的高阶函数,它接收一个函数 f 和一个 list,并通过把函数 f 依次作用在 list 的每个元素上,得到一个新的 list 并返回。 例如,对于list [1, 2, 3, 4, 5, 6, 7, 8, 9] 如果希望把list的每个元素都作平方,就可以用map()函数:
def f(x):
return x*x
print map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9])
##高阶函数reduce() reduce()函数接收的参数和 map()类似,一个函数 f,一个list,但行为和 map()不同,reduce()传入的函数 f 必须接收两个参数,reduce()对list的每个元素反复调用函数f,并返回最终结果值。 reduce()还可以接收第3个可选参数,作为计算的初始值。
##高阶函数filter() filter()函数是 Python 内置的另一个有用的高阶函数,filter()函数接收一个函数 f 和一个list,这个函数 f 的作用是对每个元素进行判断,返回 True或 False,filter()根据判断结果自动过滤掉不符合条件的元素,返回由符合条件元素组成的新list。 利用filter(),可以完成很多有用的功能,例如,删除 None 或者空字符串: 3.x中返回的是一个filter对象 需要用list()一下返回的对象
def is_not_empty(s):
return s and len(s.strip()) > 0
filter(is_not_empty, ['test', None, '', 'str', ' ', 'END'])
注:s.strip(rm) 删除 s 字符串中开头、结尾处的 rm 序列的字符。 当rm为空时,默认删除空白符(包括’\n’, ‘\r’, ‘\t’, ‘ ‘).
##sorted() sorted()也是一个高阶函数,它可以接收一个比较函数来实现自定义排序,比较函数的定义是,传入两个待比较的元素 x, y,如果 x 应该排在 y 的前面,返回 -1,如果 x 应该排在 y 的后面,返回 1。如果 x 和 y 相等,返回 0。
#匿名函数 关键字lambda 表示匿名函数,冒号前面的 x 表示函数参数。 匿名函数有个限制,就是只能有一个表达式,不写return,返回值就是该表达式的结果。 使用匿名函数,可以不必定义函数名,直接创建一个函数对象,很多时候可以简化代码. sorted([1, 3, 9, 5, 0], lambda x,y: -cmp(x,y)) [9, 5, 3, 1, 0]
##装饰器 装饰器可以极大的简化代码,避免每个函数编写重复性代码 打印日志:@log 检测性能:@performance 数据库事务:@transaction URL路由:@post(’/register’)
@decorator可以动态实现函数功能的增加,但是,经过@decorator“改造”后的函数,和原函数相比,这对于那些依赖函数名的代码就会失效。decorator还改变了函数的__doc__等其它属性。如果要让调用者看不出一个函数经过了@decorator的“改造”,就需要把原函数的一些属性复制到新函数中,这样写decorator很不方便,因为我们也很难把原函数的所有必要属性都一个一个复制到新函数上,所以Python内置的functools可以用来自动化完成这个“复制”的任务.
##偏函数 functools.partial可以把一个参数多的函数变成一个参数少的新函数,少的参数需要在创建时指定默认值,这样,新函数调用的难度就降低了。
##获取对象信息
获取对象信息
拿到一个变量,除了用 isinstance() 判断它是否是某种类型的实例外
首先可以用 type() 函数获取变量的类型,它返回一个 Type 对象:
其次,可以用 dir() 函数获取变量的所有属性:
对于实例变量,dir()返回所有实例属性,包括__class__
这类有特殊意义的属性。注意到方法whoAmI
也是 s 的一个属性。
如何去掉__xxx__
这类的特殊属性,只保留我们自己定义的属性?回顾一下filter()函数的用法。
dir()返回的属性是字符串列表,如果已知一个属性名称,要获取或者设置对象的属性,就需要用 getattr() 和 setattr( )函数了
由于Python是动态语言,任何实例在运行期都可以动态地添加属性。 如果要限制添加的属性,例如,Student类只允许添加 name、gender和score 这3个属性, 就可以利用Python的一个特殊的__slots__来实现。
在Python中,函数其实是一个对象:所有的函数都是可调用对象。 一个类实例也可以变成一个可调用对象,只需要实现一个特殊方法__call__()。
我们把 Person 类变成一个可调用对象:
class Person(object):
def __init__(self, name, gender):
self.name = name
self.gender = gender
def __call__(self, friend):
print 'My name is %s...' % self.name
print 'My friend is %s...' % friend
现在可以对 Person 实例直接调用:
>>> p = Person('Bob', 'male')
>>> p('Tim')
My name is Bob...
My friend is Tim...
##filter过滤字符串 filter(fuction,list) 例子result = filter(str.isalpha,list) print (list(result))
##translate
from string import *
a=ascii_lowercase
"map".translate(maketrans(a,a[2:]+a[:2]))
import string
table = string.maketrans(
... string.ascii_lowercase,
... string.ascii_lowercase[2:]+string.ascii_lowercase[:2])
Now we apply the translation table on the string:
string.translate(text,table)
text.translate(table)
#zipfile file = zipfile.ZipFile(“test.zip”) print(file.read(“xxx”).decode()) file.getinfo(“xxx”).comment
#pickle dumps() dump() load() loads()
d = dict(name=’Bob’, age=20, score=88) 可以随时修改变量,比如把name改成’Bill’,但是一旦程序结束,变量所占用的内存就被操作系统全部回收。如果没有把修改后的’Bill’存储到磁盘上,下次重新运行程序,变量又被初始化为’Bob’。
我们把变量从内存中变成可存储或传输的过程称之为序列化,在Python中叫pickling,在其他语言中也被称之为serialization,marshalling,flattening等等,都是一个意思。
序列化之后,就可以把序列化后的内容写入磁盘,或者通过网络传输到别的机器上。
反过来,把变量内容从序列化的对象重新读到内存里称之为反序列化,即unpickling。
Python提供两个模块来实现序列化:cPickle和pickle。这两个模块功能是一样的,区别在于cPickle是C语言写的,速度快,pickle是纯Python写的,速度慢,跟cStringIO和StringIO一个道理。用的时候,先尝试导入cPickle,如果失败,再导入pickle:
try: import cPickle as pickle except ImportError: import pickle 首先,我们尝试把一个对象序列化并写入文件: d = dict(name=’Bob’, age=20, score=88) pickle.dumps(d) “(dp0\nS’age’\np1\nI20\nsS’score’\np2\nI88\nsS’name’\np3\nS’Bob’\np4\ns.” pickle.dumps()方法把任意对象序列化成一个str,然后,就可以把这个str写入文件。或者用另一个方法pickle.dump()直接把对象序列化后写入一个file-like Object: f = open(‘dump.txt’, ‘wb’) pickle.dump(d, f) f.close() 看看写入的dump.txt文件,一堆乱七八糟的内容,这些都是Python保存的对象内部信息。
当我们要把对象从磁盘读到内存时,可以先把内容读到一个str,然后用pickle.loads()方法反序列化出对象,也可以直接用pickle.load()方法从一个file-like Object中直接反序列化出对象。我们打开另一个Python命令行来反序列化刚才保存的对象:
f = open(‘dump.txt’, ‘rb’) d = pickle.load(f) f.close() d {‘age’: 20, ‘score’: 88, ‘name’: ‘Bob’} 变量的内容又回来了!
当然,这个变量和原来的变量是完全不相干的对象,它们只是内容相同而已。
Pickle的问题和所有其他编程语言特有的序列化问题一样,就是它只能用于Python,并且可能不同版本的Python彼此都不兼容,因此,只能用Pickle保存那些不重要的数据,不能成功地反序列化也没关系。
#JSON
Python内置的json模块提供了非常完善的Python对象到JSON格式的转换。我们先看看如何把Python对象变成一个JSON: import json d = dict(name=’Bob’, age=20, score=88) json.dumps(d) ‘{“age”: 20, “score”: 88, “name”: “Bob”}’ dumps()方法返回一个str,内容就是标准的JSON。类似的,dump()方法可以直接把JSON写入一个file-like Object。 要把JSON反序列化为Python对象,用loads()或者对应的load()方法,前者把JSON的字符串反序列化,后者从file-like Object中读取字符串并反序列化:
json_str = ‘{“age”: 20, “score”: 88, “name”: “Bob”}’ json.loads(json_str) {u’age’: 20, u’score’: 88, u’name’: u’Bob’} 有一点需要注意,就是反序列化得到的所有字符串对象默认都是unicode而不是str。由于JSON标准规定JSON编码是UTF-8,所以我们总是能正确地在Python的str或unicode与JSON的字符串之间转换。
JSON进阶
Python的dict对象可以直接序列化为JSON的{},不过,很多时候,我们更喜欢用class表示对象,比如定义Student类,然后序列化:
import json
class Student(object): def init(self, name, age, score): self.name = name self.age = age self.score = score
s = Student(‘Bob’, 20, 88) print(json.dumps(s)) 运行代码,毫不留情地得到一个TypeError:
Traceback (most recent call last): … TypeError: <main.Student object at 0x10aabef50> is not JSON serializable 错误的原因是Student对象不是一个可序列化为JSON的对象。
如果连class的实例对象都无法序列化为JSON,这肯定不合理!
别急,我们仔细看看dumps()方法的参数列表,可以发现,除了第一个必须的obj参数外,dumps()方法还提供了一大堆的可选参数:
https://docs.python.org/2/library/json.html#json.dumps
这些可选参数就是让我们来定制JSON序列化。前面的代码之所以无法把Student类实例序列化为JSON,是因为默认情况下,dumps()方法不知道如何将Student实例变为一个JSON的{}对象。
可选参数default就是把任意一个对象变成一个可序列为JSON的对象,我们只需要为Student专门写一个转换函数,再把函数传进去即可:
def student2dict(std): return { ‘name’: std.name, ‘age’: std.age, ‘score’: std.score }
print(json.dumps(s, default=student2dict)) 这样,Student实例首先被student2dict()函数转换成dict,然后再被顺利序列化为JSON。
不过,下次如果遇到一个Teacher类的实例,照样无法序列化为JSON。我们可以偷个懒,把任意class的实例变为dict:
print(json.dumps(s, default=lambda obj: obj.dict)) 因为通常class的实例都有一个__dict__属性,它就是一个dict,用来存储实例变量。也有少数例外,比如定义了__slots__的class。
同样的道理,如果我们要把JSON反序列化为一个Student对象实例,loads()方法首先转换出一个dict对象,然后,我们传入的object_hook函数负责把dict转换为Student实例:
def dict2student(d): return Student(d[‘name’], d[‘age’], d[‘score’])
json_str = ‘{“age”: 20, “score”: 88, “name”: “Bob”}’ print(json.loads(json_str, object_hook=dict2student)) 运行结果如下:
<main.Student object at 0x10cd3c190> 打印出的是反序列化的Student实例对象。