python 通过bisect模块实现列表排序,在调用是每增加一个元素就调用一次sort进行排序
有序插入示例代码如下:
#!/usr/bin/env python
import bisect
import random
# use a connstant seed to ensure that
# the same pseudo-random numbers
# are used each time the loop is run
random.seed(1)
print 'New Pos Contents'
print '--- --- --------'
# generate random numbers and
# insert them intoed a list in sort
# order.
l = []
for i in range(1, 40):
r = random.randint(1, 100) #产生一个随机数
position = bisect.bisect(l, r) #计算出该数在列表中的排序位置
#print '--==', position
bisect.insort(l, r) #将r操作数插入序列
print '%3d %3d' % (r, position), l 输出操作数,列表位置及列表内容
处理重复
bisect 模块提供了2种处理重复值的方法,新值可以插入到现有值的左边或者右边,insort()函数实际上是insort_rigth()的别名这个函数会在现有值之后插入新值。相应的函数insort_left()实现现有值之前插入新值。
使用bixect_left()和insort_left()处理同样的数据时,结果会得到相同的有序列表不过重复插入的位置有所不同,示例代码如下:
#!/usr/bin/env python
import bisect
import random
random.seed(1)
l = []
print 'New Pos Contents'
print '--- --- --------'
for i in range(1,20):
r = random.randint(1,100)
opt = bisect.bisect_left(l, r)
bisect.insort_left(l, r)
print '%3d %3d' % (r, opt), l
queue——线程安全的FIFO实现
queu模块提供了一个适应与多线程编程的先进先出(first-in,first-out,FIFO)数据结构,可用来在生产者和消费者线程之间安全的传递消息或其他数据。他会为调用者处理锁定,使多个线程可以安全的处理同一个queue实例。queue的大小会受到限制,以限制内存使用。
queue类实现了一个基本的先进先出容器。使用put()将元素增加到序列一端,使用get从另一端删除。示例代码如下:
#!/usr/bin/env python
import Queue
#sheng ming dui lie shili
q = Queue.Queue()
for i in range(5):
q.put(i)
while not q.empty():
print q.get(),
print
LIFO队列
queue是标准的FIFO队列,而LifoQueue使用了后进先出的顺序。
示例代码如下:
#!/usr/bin/env python
import Queue #导入Queue模块
q = Queue.LifoQueue() #声明Queue.LifoQueue实例
for i in range(10):
q.put(i) #将数压入栈
while not q.empty():
print q.get(), #取出栈中数据
print
优先队列
有些情况下元素的处理顺序需要根据这些元素的特性来决定,而不只是在队列中,创建或插入的顺序。如财务部的打印作业可能要优于一个开发人员打印的代码清单,使用priorityQueue使用队列内容的有序顺序来决定获取哪一个元素。
示例代码如下:
#!/usr/bin/env python
import Queue
import threading
class Job(object):
def __init__(self, priority, description):
self.priority = priority
self.description = description
print 'New job:', description
return
def __cmp__(self, other):
return cmp(self.priority, other.priority)
q = Queue.PriorityQueue()
q.put(Job(3, 'Mid-level job'))
q.put(Job(10, 'low-level job'))
q.put(Job(1, 'Important job'))
def process_job(q):
while True:
next_job=q.get()
print 'procesiing job:', next_job.description
q.task_done()
workers = [threading.Thread(target=process_job, args=(q,)),
threading.Thread(target=process_job, args=(q,)),
]
for w in workers:
w.setDaemon(True)
w.start()
q.join()
struct 二进制数据结构
struct模块包括一些在字节窜与内置python数据类型之间转行的函数。
struct提供了 一组处理结构值的模块级函数,另外还有一个struct类,格式指示符由字符串格式转换为一种编译表示,这于处理正则表达式的方式类似。这个转换会耗费资源。所以当创建一个struct实例并在这个实例上调用方法时完成一次转换会变得比较高效。
struct支持使用格式指示符将数据打包(packing)为字符串,以及从字符串解包unpacking数据。
下面的例子中指示符要求一个整数或long值、一个包含两个字符串,以及一个浮点数,格式指示符中包含的空格用来分割类型指示符,在编译格式时会忽略。
#!/usr/bin/env python
import struct
import binascii
values = (1, 'ab', 2.7)
s = struct.Struct('i 2s f')
packed_data = s.pack(*values)
print 'Original values:', values
print 'Format string :', s.format
print 'use :', s.size, 'bytes'
print 'packed value :', binascii.hexlify(packed_data)
实例将大巴的值转换为一个16进制序列,以便利用binascii.hexlify()进行打印,因为有些字符是null。
unpack可以实现解包,基本得到相同的值,但是浮点型数据不同。
如下:
packed_data1 = binascii.unhexlify('0100000061620000cdcc2c40')
print '--->', packed_data1
s = struct.Struct('i 2s f')
unpacked_data = s.unpack(packed_data1)
print 'unpacked values:', unpacked_data
字节序
python默认使用c库的字节序进 行编码,只需要在格式串中提供一个显示的字节序指令,就可以很容易覆盖这个默认选择。
示例代码如下:
#!/usr/bin/env python
import struct
import binascii
values = (1, 'ab', 2.7)
print 'Original value:', values
endianness = [
('@', 'native, native'),
('=', 'native, standard'),
('<', 'little-endian'),
('>', 'big-endian'),
('!', 'network'),
]
for code, name in endianness:
s = struct.Struct(code + 'I 2s f')
packed_data = s.pack(*values)
print
print 'Format string :', s.format, 'for', name
print 'Uses :', s.size, 'bytes'
print 'packed value :', binascii.hexlify(packed_data)
print 'Unpacked value :', s.unpack(packed_data)
struct的字节序概述如下:
指示符 | 含义 |
---|---|
@ | 内置顺序 |
= | 内置标准 |
< | 小端 |
> | 大端 |
! | 网络顺序 |
缓冲区
通常在重视性能的情况下或者享扩展模块传入或传出数据时才会处理二进制打包,通过避免为每个打包结构分配一个新缓冲区所带来的开销,可以优化这些情况使用pack_info()和unpack_from()方法支持直接写入预分配的缓冲区。
示例代码如下:
#!/usr/bin/env python
import struct
import binascii
s = struct.Struct('I 2s f')
values = (1, 'ab', 2.7)
print 'Original:', values
print
print 'ctypes string buffer'
import ctypes
b = ctypes.create_string_buffer(s.size)
print 'Beffore :', binascii.hexlify(b.raw)
s.pack_into(b, 0, *values)
print 'After :', binascii.hexlify(b.raw)
print 'Unpacked:', s.unpack_from(b, 0)
print
print 'array'
import array
a = array.array('c', '\0'*s.size)
print 'Before :', binascii.hexlify(a)
s.pack_into(a, 0, *values)
print 'After :', binascii.hexlify(a)
print 'Unpacked:', s.unpack_from(a,0)
weakref 对象的非永久引用
weakerf模块支持对象的弱引用,正常的引用会增加对象的引用计数器,避免被垃圾回收,但并不总希望如此,比如有时可能会出现一个循环引用,或构造一个对象缓存,需要内存时则删除这个缓存。弱引用是避免对象被自动清理的一个句柄。
对象引用通过ref类管理,要获取原对象,可以调用引用对象。
示例代码:
#!/usr/bin/env python
import weakref
class Expensiveobject(object):
def __del__(self):
print '(Deleting %s)' % self
obj = Expensiveobject()
r = weakref.ref(obj)
print 'obj:', obj
print 'ref:', r
print 'r():', r()
print 'deleting obj'
del obj
print 'r():', r()
print '='*50
str = 'this is a test'
str1 = str
print r()
del str
print r()
引用回调
ref构造函数接受一个可选的回调函数,删除索引的对象时会调用这个函数。
代码示例:
#!/usr/bin/env python
import weakref
class Expensiveobject(object):
def __del__(self):
print '(Deleting %s)' % self
def callback(reference):
"""Invoked when referenced object is deleted"""
print 'callback(',reference, ')'
obj = Expensiveobject()
r = weakref.ref(obj, callback)
print 'obj:', obj
print 'ref:', r
print 'r():', r()
print 'deleting obj'
del obj
print 'r():', r()
代理
有时使用代理比使用弱引用更方便。使用代理时可以象使用源对象一样,而且不要求访问对象之前先调用代理。这说明,可以将代理传递到一个库,而这个库并不知道它接受的是一个引用而把bushi真正的对象。
示例代码如下:
#!/usr/bin/env python
import weakref
class Expensiveobject(object):
def __init__(self, name):
self.name = name
def __del__(self):
print '(Deleting %s)' % self
obj = Expensiveobject('my object')
r = weakref.ref(obj)
p = weakref.proxy(obj)
print 'via obj:', obj.name
print 'via ref:', r().name
print 'via proxy:', p.name
del obj
print 'via proxy:', p.name
copy-复制对象
copy模块包含两个函数copy()和deepcopy()用于复制现有的对象。
copy()创建浅副本,是一个新容器,其中填充原对象内容的引用,建立list对象的一个浅副本时,会构造一个新的list,并将原对象的元素追加到这个list
示例代码如下:
#!/usr/bin/env python
import copy
class MyClass:
def __init__(self, name):
self.name = name
def __cmp__(self, other):
return cmp(self.name, other.name)
a = MyClass('a')
my_list = [a]
dup = copy.copy(my_list)
print ' my_list', my_list
print ' dup', dup
print ' dup is my_list', (dup is my_list)
print ' dup == my_list', (dup == my_list)
print 'dup[0] is my_list[0]', (dup[0] is my_list[0])
print 'dup[0] == my_list[0]', (dup[0] == my_list[0])
deepcopy()创建的深副本是一个新容器,其中填充原对象内容的副本要建立一个list的深副本会构造一个新的list,复制原列表的元素,然后用这些副本追加到新列表中。
dup = copy.deepcopy(my_list)
示例代码如下:
#!/usr/bin/env python
import copy
class MyClass:
def __init__(self, name):
self.name = name
def __cmp__(self, other):
return cmp(self.name, other.name)
a = MyClass('a')
my_list = [a]
dup = copy.deepcopy(my_list)
print ' my_list', my_list
print ' dup', dup
print ' dup is my_list', (dup is my_list)
print ' dup == my_list', (dup == my_list)
print 'dup[0] is my_list[0]', (dup[0] is my_list[0])
print 'dup[0] == my_list[0]', (dup[0] == my_list[0])
pprint美观打印数据结构
pprint包含一个美观打印机用于生成数据结构的一个美观视图。格式化工具会生成数据结构的一些表示,不仅可以由解释器正确地解析,而且便于人类阅读输出仅能你放在一行上,分解为多行时则需要缩进。
示例代码如下:
data数据文件代码
data =[ (1, {'a':'A','b':'B','c':'C','d':'D'}),
(2, {'edata =[ (1, {'a':'A','b':'B','c':'C','d':'D'}),
(2, {'e':'E','f':'F','g':'G','h':'H',
'i':'I','j':'J','k':'K','l':'L'})
]':'E','f':'F','g':'G','h':'H',
'i':'I','j':'J','k':'K','l':'L'})
]
#!/usr/bin/env python
from pprint import pprint
from pprint_data import data
print 'print:'
print data
print
print 'pprint:'
pprint(data)
pprint()格式化一个对象,并把它写至一个数据流,这个数据流作为参数传入。
格式化
要格式化一个数据结构而不把它直接写至一个流可以 使用pformat()来构造一个字符串表示。
示例代码:
#!/usr/bin/env python
import logging
from pprint import pformat
from pprint_data import data
logging.basicConfig(level=logging.DEBUG,
format='%(levelname)-8s %(message)s',
)
logging.debug('Logging pformatted data')
formatted = pformat(data)
for line in formatted.splitlines():
logging.debug(line.rstrip())