Python开发【【金沙官网线上】模块】:Weakref

Weak references

前言:

  • weakref模块允许python开发者创建弱引用对象。
  • 再接下来中,术语referent代表被弱引用所引用的对象。
  • 一个弱引用对于对象是不能够保持对象存活的:当仅剩下referent的引用都是弱引用时,垃圾回收机制是可以自由销毁referent然后重新使用内存的。然而,直到对象被真正销毁之前,弱引用可能返回一个对象,即使它没有强引用。
  • 弱引用的主要用处是实现缓存和映射保持大型对象,期望大型对象不能仅仅因为出现在缓存或映射中而保持存活。
  • 举个栗子,如果你有一些大型二进制image对象,你可能希望用name与每个image关联起来。如果你用python中的字典去映射names对images,或者images对names。image对象将仍然存活仅仅因为它作为key值或value值存放在字典中。 weakref中的WeakKeyDictionaryWeakValueDictionary是另一种选择,使用弱引用会构造映射,映射不会仅因为对象出现在映射中而保持存活。再举个栗子,一个image对象作为value存放于WeakValueDictionary中,当image对象最后的引用时弱映射中的弱引用时,垃圾回收机制会回收对象,在弱映射中对应的条目也会被删除。
  • WeakKeyDictionaryWeakValueDictionary使用弱引用实现,设置回调方法,当弱字典的key或value被垃圾回收机制回收时会通知弱字典。WeakSet实现了set接口,但是对它的元素却保持了弱引用,就像WeakKeyDictionary一样。
  • finalize提供了一个直接的方式注册清理函数,当对象被垃圾回收是调用,这比在原始的弱引用上设置回调函数更简单,因为该模块自动确保终结器在对象被收集之前仍然存活。大多是程序发现使用弱类型或finalize是所需要的,低级别机器由weakref模块公开,以获得高级应用的好处。但是并不是所有的对象都可以被弱引用的;可以引用的包括类实例、Python中的方法(不在C中)、实例方法、集合、frozensets、一些文件对象、生成器、类型对象、sockets、arrays、dequeues、正则、代码对象。
  • 更改再version 3.2: 添加支持thread.lock, threading.Lock, and code objects。
  • 一些内置类型,如list和dict不直接支持弱引用,但是可以通过子类添加支持。

    class Dict(dict):

    pass
    

    obj = Dict(red=1, green=2, blue=3) # this object is weak referenceable

  •  其他内置类型,如tuple和int,即使在子类化时也不支持弱引用(这是一个实现细节,可能在不同的Python实现中是不同的)。扩展类型可以很容易地支持弱引用。

 

使用:

 1、weakref.``ref(object[, callback])

 

  1.1 Counter()

  如果你想统计一个单词在给定的序列中一共出现了多少次,诸如此类的操作就可以用到Counter。来看看如何统计一个list中出现的item次数:

1 2 3 4 5 from collections import Counter   li = ["Dog", "Cat", "Mouse", 42, "Dog", 42, "Cat", "Dog"] a = Counter(li) print a # Counter({'Dog': 3, 42: 2, 'Cat': 2, 'Mouse': 1})

  若要统计一个list中不同单词的数目,可以这么用:

1 2 3 4 5 6 7 from collections import Counter   li = ["Dog", "Cat", "Mouse", 42, "Dog", 42, "Cat", "Dog"] a = Counter(li) print a # Counter({'Dog': 3, 42: 2, 'Cat': 2, 'Mouse': 1})   print len(set(li)) # 4

  如果需要对结果进行分组,可以这么做:

1 2 3 4 5 6 7 8 9 10 from collections import Counter   li = ["Dog", "Cat", "Mouse","Dog","Cat", "Dog"] a = Counter(li)   print a # Counter({'Dog': 3, 'Cat': 2, 'Mouse': 1})   print "{0} : {1}".format(a.values(),a.keys())  # [1, 3, 2] : ['Mouse', 'Dog', 'Cat']   print(a.most_common(3)) # [('Dog', 3), ('Cat', 2), ('Mouse', 1)]

  以下的代码片段找出一个字符串中出现频率最高的单词,并打印其出现次数。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 import re from collections import Counter   string = """   Lorem ipsum dolor sit amet, consectetur     adipiscing elit. Nunc ut elit id mi ultricies     adipiscing. Nulla facilisi. Praesent pulvinar,     sapien vel feugiat vestibulum, nulla dui pretium orci,     non ultricies elit lacus quis ante. Lorem ipsum dolor     sit amet, consectetur adipiscing elit. Aliquam     pretium ullamcorper urna quis iaculis. Etiam ac massa     sed turpis tempor luctus. Curabitur sed nibh eu elit     mollis congue. Praesent ipsum diam, consectetur vitae     ornare a, aliquam a nunc. In id magna pellentesque     tellus posuere adipiscing. Sed non mi metus, at lacinia     augue. Sed magna nisi, ornare in mollis in, mollis     sed nunc. Etiam at justo in leo congue mollis.     Nullam in neque eget metus hendrerit scelerisque     eu non enim. Ut malesuada lacus eu nulla bibendum     id euismod urna sodales.  """   words = re.findall(r'w+', string) #This finds words in the document   lower_words = [word.lower() for word in words] #lower all the words   word_counts = Counter(lower_words) #counts the number each time a word appears print word_counts   # Counter({'elit': 5, 'sed': 5, 'in': 5, 'adipiscing': 4, 'mollis': 4, 'eu': 3, # 'id': 3, 'nunc': 3, 'consectetur': 3, 'non': 3, 'ipsum': 3, 'nulla': 3, 'pretium': # 2, 'lacus': 2, 'ornare': 2, 'at': 2, 'praesent': 2, 'quis': 2, 'sit': 2, 'congue': 2, 'amet': 2, # 'etiam': 2, 'urna': 2, 'a': 2, 'magna': 2, 'lorem': 2, 'aliquam': 2, 'ut': 2, 'ultricies': 2, 'mi': 2, # 'dolor': 2, 'metus': 2, 'ac': 1, 'bibendum': 1, 'posuere': 1, 'enim': 1, 'ante': 1, 'sodales': 1, 'tellus': 1, # 'vitae': 1, 'dui': 1, 'diam': 1, 'pellentesque': 1, 'massa': 1, 'vel': 1, 'nullam': 1, 'feugiat': 1, 'luctus': 1, # 'pulvinar': 1, 'iaculis': 1, 'hendrerit': 1, 'orci': 1, 'turpis': 1, 'nibh': 1, 'scelerisque': 1, 'ullamcorper': 1, # 'eget': 1, 'neque': 1, 'euismod': 1, 'curabitur': 1, 'leo': 1, 'sapien': 1, 'facilisi': 1, 'vestibulum': 1, 'nisi': 1, # 'justo': 1, 'augue': 1, 'tempor': 1, 'lacinia': 1, 'malesuada': 1})

  额外的知识

  一些基本的数据结构

  完整的例子:

  引用计数器是由Python的垃圾回收器使用的,当一个对象的应用计数器变为0,则其将会被垃圾回收器回收。

  最好将weak reference用于开销较大的对象,或避免循环引用(虽然垃圾回收器经常干这种事情)。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import weakref import gc   class MyObject(object):     def my_method(self):         print 'my_method was called!'   obj = MyObject() r = weakref.ref(obj)   gc.collect() assert r() is obj #r() allows you to access the object referenced: it's there.   obj = 1 #Let's change what obj references to gc.collect() assert r() is None #There is no object left: it was gc'ed.

  提示:只有library模块中定义的class instances、functions、methods、sets、frozen sets、files、generators、type objects和certain object types(例如sockets、arrays和regular expression patterns)支持weakref。内建函数以及大部分内建类型如lists、dictionaries、strings和numbers则不支持。

Python 数据结构

s[i:j:k] slice of s from i to j with step k
参考资料:docs.python.org/...xrange  

python有什用

python适合快速开发,代码不仅优美,而且简洁。当然这是从美观上来说的。它本身是解释性语言,因此不需要编译即可运行。而且内置许多的高级数据结构,如常见的链表(python叫list),Hash表(python叫dict)等都是内置的。而且它没有静态类型声明,这样自然就是一种泛型编程。也不需要接口,但通过自省或约定可以轻松实现接口的功能。它的动态性还表现在可以在运行时改变一个实例,改变类(因为python中一切皆为对象,类也是一个对象)。还支持高级但更复杂的metaclass编程,即生成类的类。特别是它自带许多的标准库,功能都不错。python还提供一个交互环境可以进行测试。python有象java一样的包的概念,可以轻松管理你的模块。同时还有强大的自省功能,即在运行时检查对象的属性。支持自动垃圾回收。  

http://www.bkjia.com/Pythonjc/904699.htmlwww.bkjia.comtruehttp://www.bkjia.com/Pythonjc/904699.htmlTechArticlePython中的高级数据结构,python数据结构 数据结构 数据结构的概念很好理解,就是用来将数据组织在一起的结构。换句话说,数据结构是用...

  复杂的例子:

  假定我有两个类,名为Manager和Graph,每个Graph包含了一个指向其manager的引用,而每个Manager有一个指向其管理的Graph的集合,现在我们有两个任务需要完成:

  1) 复制一个graph实例,使用deepcopy,但其manager指向为原graph的manager。

  2) 复制一个manager,完全创建新manager,但拷贝原有的所有graph。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 import weakref, copy   class Graph(object):     def __init__(self, manager=None):         self.manager = None if manager is None else weakref.ref(manager)     def __deepcopy__(self, memodict):         manager = self.manager()         return Graph(memodict.get(id(manager), manager))   class Manager(object):     def __init__(self, graphs=[]):         self.graphs = graphs         for g in self.graphs:             g.manager = weakref.ref(self)   a = Manager([Graph(), Graph()]) b = copy.deepcopy(a)   if [g.manager() is b for g in b.graphs]:     print True # True   if copy.deepcopy(a.graphs[0]).manager() is a:     print True # True

  7. Pprint()

  Pprint模块能够提供比较优雅的数据结构打印方式,如果你需要打印一个结构较为复杂,层次较深的字典或是JSON对象时,使用Pprint能够提供较好的打印结果。

  假定你需要打印一个矩阵,当使用普通的print时,你只能打印出普通的列表,不过如果使用pprint,你就能打出漂亮的矩阵结构

  如果

1 2 3 4 5 6 7 8 9 import pprint   matrix = [ [1,2,3], [4,5,6], [7,8,9] ] a = pprint.PrettyPrinter(width=20) a.pprint(matrix)   # [[1, 2, 3], #  [4, 5, 6], #  [7, 8, 9]]

  5. Weakref

  weakref模块能够帮助我们创建Python引用,却不会阻止对象的销毁操作。这一节包含了weak reference的基本用法,并且引入一个代理类。

  在开始之前,我们需要明白什么是strong reference。strong reference是一个对对象的引用次数、生命周期以及销毁时机产生影响的指针。strong reference如你所见,就是当你将一个对象赋值给一个变量的时候产生的:

1 2 >>> a = [1,2,3] >>> b = a

  在这种情况下,这个列表有两个strong reference,分别是a和b。在这两个引用都被释放之前,这个list不会被销毁。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 class Foo(object):     def __init__(self):         self.obj = None         print 'created'       def __del__(self):         print 'destroyed'       def show(self):         print self.obj       def store(self, obj):         self.obj = obj   a = Foo() # created b = a del a del b # destroyed

  Weak reference则是对对象的引用计数器不会产生影响。当一个对象存在weak reference时,并不会影响对象的撤销。这就说,如果一个对象仅剩下weak reference,那么它将会被销毁。

  你可以使用weakref.ref函数来创建对象的weak reference。这个函数调用需要将一个strong reference作为第一个参数传给函数,并且返回一个weak reference。

1 2 3 4 5 >>> import weakref >>> a = Foo() created >>> b = weakref.ref(a) >>> b

  一个临时的strong reference可以从weak reference中创建,即是下例中的b():

1 2 3 4 >>> a == b() True >>> b().show() None

  请注意当我们删除strong reference的时候,对象将立即被销毁。

1 2 >>> del a destroyed

  如果试图在对象被摧毁之后通过weak reference使用对象,则会返回None:

1 2 >>> b() is None True

  若是使用weakref.proxy,就能提供相对于weakref.ref更透明的可选操作。同样是使用一个strong reference作为第一个参数并且返回一个weak reference,proxy更像是一个strong reference,但当对象不存在时会抛出异常。

1 2 3 4 5 6 7 8 9 10 11 12 >>> a = Foo() created >>> b = weakref.proxy(a) >>> b.store('fish') >>> b.show() fish >>> del a destroyed >>> b.show() Traceback (most recent call last):   File "", line 1, in ? ReferenceError: weakly-referenced object no longer exists

  4. Bisect

  bisect模块能够提供保持list元素序列的支持。它使用了二分法完成大部分的工作。它在向一个list插入元素的同时维持list是有序的。在某些情况下,这比重复的对一个list进行排序更为高效,并且对于一个较大的list来说,对每步操作维持其有序也比对其排序要高效。

  假设你有一个range集合:

1 a = [(0, 100), (150, 220), (500, 1000)]

金沙官网线上,  如果我想添加一个range (250, 400),我可能会这么做:

1 2 3 4 5 6 7 import bisect   a = [(0, 100), (150, 220), (500, 1000)]   bisect.insort_right(a, (250,400))   print a # [(0, 100), (150, 220), (250, 400), (500, 1000)]

  我们可以使用bisect()函数来寻找插入点:

1 2 3 4 5 6 7 8 9 import bisect   a = [(0, 100), (150, 220), (500, 1000)]   bisect.insort_right(a, (250,400)) bisect.insort_right(a, (399, 450)) print a # [(0, 100), (150, 220), (250, 400), (500, 1000)]   print bisect.bisect(a, (550, 1200)) # 5

  bisect(sequence, item) => index 返回元素应该的插入点,但序列并不被修改。

1 2 3 4 5 6 7 8 9 10 11 import bisect   a = [(0, 100), (150, 220), (500, 1000)]   bisect.insort_right(a, (250,400)) bisect.insort_right(a, (399, 450)) print a # [(0, 100), (150, 220), (250, 400), (500, 1000)]   print bisect.bisect(a, (550, 1200)) # 5 bisect.insort_right(a, (550, 1200)) print a # [(0, 100), (150, 220), (250, 400), (399, 450), (500, 1000), (550, 1200)]

  新元素被插入到第5的位置。

  1. 单链链表

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 class Node:     def __init__(self):         self.data = None         self.nextNode = None       def set_and_return_Next(self):         self.nextNode = Node()         return self.nextNode       def getNext(self):         return self.nextNode       def getData(self):         return self.data       def setData(self, d):         self.data = d   class LinkedList:     def buildList(self, array):         self.head = Node()         self.head.setData(array[0])         self.temp = self.head         for i in array[1:]:             self.temp = self.temp.set_and_return_Next()             self.temp.setData(i)             self.tail = self.temp         return self.head     def printList(self):         tempNode = self.head         while(tempNode!=self.tail):             print(tempNode.getData())             tempNode = tempNode.getNext()         print(self.tail.getData()) myArray = [3, 5, 4, 6, 2, 6, 7, 8, 9, 10, 21]   myList = LinkedList() myList.buildList(myArray) myList.printList()

  2. 用Python实现的普林姆算法

  译者注:普林姆算法(Prims Algorithm)是图论中,在加权连通图中搜索最小生成树的算法。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 from collections import defaultdict from heapq import heapify, heappop, heappush   def prim( nodes, edges ):     conn = defaultdict( list )     for n1,n2,c in edges:         conn[ n1 ].append( (c, n1, n2) )         conn[ n2 ].append( (c, n2, n1) )       mst = []     used = set( nodes[ 0 ] )     usable_edges = conn[ nodes[0] ][:]     heapify( usable_edges )       while usable_edges:         cost, n1, n2 = heappop( usable_edges )         if n2 not in used:             used.add( n2 )             mst.append( ( n1, n2, cost ) )               for e in conn[ n2 ]:                 if e[ 2 ] not in used:                     heappush( usable_edges, e )     return mst   #test nodes = list("ABCDEFG") edges = [ ("A", "B", 7), ("A", "D", 5),           ("B", "C", 8), ("B", "D", 9), ("B", "E", 7),       ("C", "E", 5),       ("D", "E", 15), ("D", "F", 6),       ("E", "F", 8), ("E", "G", 9),       ("F", "G", 11)]   print "prim:", prim( nodes, edges )

本文由金沙官网线上发布于编程,转载请注明出处:Python开发【【金沙官网线上】模块】:Weakref

您可能还会对下面的文章感兴趣: