[Python-checkins] cpython: Use __slots__ throughout instead of __dict__, to reduce the memory usage.

martin.v.loewis python-checkins at python.org
Sun Feb 19 20:25:35 CET 2012


http://hg.python.org/cpython/rev/3931f043b79a
changeset: 75041:3931f043b79a
user: Martin v. Löwis <martin at v.loewis.de>
date: Sun Feb 19 20:25:12 2012 +0100
summary:
 Use __slots__ throughout instead of __dict__, to reduce the memory usage.
files:
 Lib/xml/dom/expatbuilder.py | 39 +--
 Lib/xml/dom/minidom.py | 216 +++++++++++------------
 2 files changed, 114 insertions(+), 141 deletions(-)
diff --git a/Lib/xml/dom/expatbuilder.py b/Lib/xml/dom/expatbuilder.py
--- a/Lib/xml/dom/expatbuilder.py
+++ b/Lib/xml/dom/expatbuilder.py
@@ -283,27 +283,23 @@
 elif childNodes and childNodes[-1].nodeType == TEXT_NODE:
 node = childNodes[-1]
 value = node.data + data
- d = node.__dict__
- d['data'] = d['nodeValue'] = value
+ node.data = value
 return
 else:
 node = minidom.Text()
- d = node.__dict__
- d['data'] = d['nodeValue'] = data
- d['ownerDocument'] = self.document
+ node.data = data
+ node.ownerDocument = self.document
 _append_child(self.curNode, node)
 
 def character_data_handler(self, data):
 childNodes = self.curNode.childNodes
 if childNodes and childNodes[-1].nodeType == TEXT_NODE:
 node = childNodes[-1]
- d = node.__dict__
- d['data'] = d['nodeValue'] = node.data + data
+ node.data = node.data + data
 return
 node = minidom.Text()
- d = node.__dict__
- d['data'] = d['nodeValue'] = node.data + data
- d['ownerDocument'] = self.document
+ node.data = node.data + data
+ node.ownerDocument = self.document
 _append_child(self.curNode, node)
 
 def entity_decl_handler(self, entityName, is_parameter_entity, value,
@@ -363,11 +359,8 @@
 a = minidom.Attr(attributes[i], EMPTY_NAMESPACE,
 None, EMPTY_PREFIX)
 value = attributes[i+1]
- d = a.childNodes[0].__dict__
- d['data'] = d['nodeValue'] = value
- d = a.__dict__
- d['value'] = d['nodeValue'] = value
- d['ownerDocument'] = self.document
+ a.value = value
+ a.ownerDocument = self.document
 _set_attribute_node(node, a)
 
 if node is not self.document.documentElement:
@@ -761,11 +754,8 @@
 else:
 a = minidom.Attr("xmlns", XMLNS_NAMESPACE,
 "xmlns", EMPTY_PREFIX)
- d = a.childNodes[0].__dict__
- d['data'] = d['nodeValue'] = uri
- d = a.__dict__
- d['value'] = d['nodeValue'] = uri
- d['ownerDocument'] = self.document
+ a.value = uri
+ a.ownerDocuemnt = self.document
 _set_attribute_node(node, a)
 del self._ns_ordered_prefixes[:]
 
@@ -785,12 +775,9 @@
 aname, EMPTY_PREFIX)
 _attrs[aname] = a
 _attrsNS[(EMPTY_NAMESPACE, aname)] = a
- d = a.childNodes[0].__dict__
- d['data'] = d['nodeValue'] = value
- d = a.__dict__
- d['ownerDocument'] = self.document
- d['value'] = d['nodeValue'] = value
- d['ownerElement'] = node
+ a.ownerDocument = self.document
+ a.value = value
+ a.ownerElement = node
 
 if __debug__:
 # This only adds some asserts to the original
diff --git a/Lib/xml/dom/minidom.py b/Lib/xml/dom/minidom.py
--- a/Lib/xml/dom/minidom.py
+++ b/Lib/xml/dom/minidom.py
@@ -286,10 +286,10 @@
 childNodes = self.childNodes
 if childNodes:
 last = childNodes[-1]
- node.__dict__["previousSibling"] = last
- last.__dict__["nextSibling"] = node
+ node.previousSibling = last
+ last.nextSibling = node
 childNodes.append(node)
- node.__dict__["parentNode"] = self
+ node.parentNode = self
 
 def _in_document(node):
 # return True iff node is part of a document tree
@@ -342,9 +342,10 @@
 
 
 class Attr(Node):
+ __slots__=('_name', '_value', 'namespaceURI',
+ '_prefix', 'childNodes', '_localName', 'ownerDocument', 'ownerElement')
 nodeType = Node.ATTRIBUTE_NODE
 attributes = None
- ownerElement = None
 specified = False
 _is_id = False
 
@@ -352,12 +353,11 @@
 
 def __init__(self, qName, namespaceURI=EMPTY_NAMESPACE, localName=None,
 prefix=None):
- # skip setattr for performance
- d = self.__dict__
- d["nodeName"] = d["name"] = qName
- d["namespaceURI"] = namespaceURI
- d["prefix"] = prefix
- d['childNodes'] = NodeList()
+ self.ownerElement = None
+ self._name = qName
+ self.namespaceURI = namespaceURI
+ self._prefix = prefix
+ self.childNodes = NodeList()
 
 # Add the single child node that represents the value of the attr
 self.childNodes.append(Text())
@@ -365,9 +365,10 @@
 # nodeValue and value are set elsewhere
 
 def _get_localName(self):
- if 'localName' in self.__dict__:
- return self.__dict__['localName']
- return self.nodeName.split(":", 1)[-1]
+ try:
+ return self._localName
+ except AttributeError:
+ return self.nodeName.split(":", 1)[-1]
 
 def _get_name(self):
 return self.name
@@ -375,20 +376,30 @@
 def _get_specified(self):
 return self.specified
 
- def __setattr__(self, name, value):
- d = self.__dict__
- if name in ("value", "nodeValue"):
- d["value"] = d["nodeValue"] = value
- d2 = self.childNodes[0].__dict__
- d2["data"] = d2["nodeValue"] = value
- if self.ownerElement is not None:
- _clear_id_cache(self.ownerElement)
- elif name in ("name", "nodeName"):
- d["name"] = d["nodeName"] = value
- if self.ownerElement is not None:
- _clear_id_cache(self.ownerElement)
- else:
- d[name] = value
+ def _get_name(self):
+ return self._name
+
+ def _set_name(self, value):
+ self._name = value
+ if self.ownerElement is not None:
+ _clear_id_cache(self.ownerElement)
+
+ nodeName = name = property(_get_name, _set_name)
+
+ def _get_value(self):
+ return self._value
+
+ def _set_value(self, value):
+ self._value = value
+ self.childNodes[0].data = value
+ if self.ownerElement is not None:
+ _clear_id_cache(self.ownerElement)
+ self.childNodes[0].data = value
+
+ nodeValue = value = property(_get_value, _set_value)
+
+ def _get_prefix(self):
+ return self._prefix
 
 def _set_prefix(self, prefix):
 nsuri = self.namespaceURI
@@ -396,22 +407,16 @@
 if nsuri and nsuri != XMLNS_NAMESPACE:
 raise xml.dom.NamespaceErr(
 "illegal use of 'xmlns' prefix for the wrong namespace")
- d = self.__dict__
- d['prefix'] = prefix
+ self._prefix = prefix
 if prefix is None:
 newName = self.localName
 else:
 newName = "%s:%s" % (prefix, self.localName)
 if self.ownerElement:
 _clear_id_cache(self.ownerElement)
- d['nodeName'] = d['name'] = newName
+ self.name = newName
 
- def _set_value(self, value):
- d = self.__dict__
- d['value'] = d['nodeValue'] = value
- if self.ownerElement:
- _clear_id_cache(self.ownerElement)
- self.childNodes[0].data = value
+ prefix = property(_get_prefix, _set_prefix)
 
 def unlink(self):
 # This implementation does not call the base implementation
@@ -586,8 +591,8 @@
 _clear_id_cache(self._ownerElement)
 del self._attrs[n.nodeName]
 del self._attrsNS[(n.namespaceURI, n.localName)]
- if 'ownerElement' in n.__dict__:
- n.__dict__['ownerElement'] = None
+ if hasattr(n, 'ownerElement'):
+ n.ownerElement = None
 return n
 else:
 raise xml.dom.NotFoundErr()
@@ -598,8 +603,8 @@
 _clear_id_cache(self._ownerElement)
 del self._attrsNS[(n.namespaceURI, n.localName)]
 del self._attrs[n.nodeName]
- if 'ownerElement' in n.__dict__:
- n.__dict__['ownerElement'] = None
+ if hasattr(n, 'ownerElement'):
+ n.ownerElement = None
 return n
 else:
 raise xml.dom.NotFoundErr()
@@ -659,6 +664,9 @@
 _no_type = TypeInfo(None, None)
 
 class Element(Node):
+ __slots__=('ownerDocument', 'parentNode', 'tagName', 'nodeName', 'prefix',
+ 'namespaceURI', '_localName', 'childNodes', '_attrs', '_attrsNS',
+ 'nextSibling', 'previousSibling')
 nodeType = Node.ELEMENT_NODE
 nodeValue = None
 schemaType = _no_type
@@ -674,10 +682,12 @@
 
 def __init__(self, tagName, namespaceURI=EMPTY_NAMESPACE, prefix=None,
 localName=None):
+ self.parentNode = None
 self.tagName = self.nodeName = tagName
 self.prefix = prefix
 self.namespaceURI = namespaceURI
 self.childNodes = NodeList()
+ self.nextSibling = self.previousSibling = None
 
 self._attrs = {} # attributes are double-indexed:
 self._attrsNS = {} # tagName -> Attribute
@@ -688,9 +698,10 @@
 # namespaces.
 
 def _get_localName(self):
- if 'localName' in self.__dict__:
- return self.__dict__['localName']
- return self.tagName.split(":", 1)[-1]
+ try:
+ return self._localName
+ except AttributeError:
+ return self.tagName.split(":", 1)[-1]
 
 def _get_tagName(self):
 return self.tagName
@@ -718,14 +729,11 @@
 attr = self.getAttributeNode(attname)
 if attr is None:
 attr = Attr(attname)
- # for performance
- d = attr.__dict__
- d["value"] = d["nodeValue"] = value
- d["ownerDocument"] = self.ownerDocument
+ attr.value = value # also sets nodeValue
+ attr.ownerDocument = self.ownerDocument
 self.setAttributeNode(attr)
 elif value != attr.value:
- d = attr.__dict__
- d["value"] = d["nodeValue"] = value
+ attr.value = value
 if attr.isId:
 _clear_id_cache(self)
 
@@ -733,23 +741,18 @@
 prefix, localname = _nssplit(qualifiedName)
 attr = self.getAttributeNodeNS(namespaceURI, localname)
 if attr is None:
- # for performance
 attr = Attr(qualifiedName, namespaceURI, localname, prefix)
- d = attr.__dict__
- d["prefix"] = prefix
- d["nodeName"] = qualifiedName
- d["value"] = d["nodeValue"] = value
- d["ownerDocument"] = self.ownerDocument
+ attr.value = value
+ attr.ownerDocument = self.ownerDocument
 self.setAttributeNode(attr)
 else:
- d = attr.__dict__
 if value != attr.value:
- d["value"] = d["nodeValue"] = value
+ attr.value = value
 if attr.isId:
 _clear_id_cache(self)
 if attr.prefix != prefix:
- d["prefix"] = prefix
- d["nodeName"] = qualifiedName
+ attr.prefix = prefix
+ attr.nodeName = qualifiedName
 
 def getAttributeNode(self, attrname):
 return self._attrs.get(attrname)
@@ -874,7 +877,7 @@
 if _get_containing_entref(self) is not None:
 raise xml.dom.NoModificationAllowedErr()
 if not idAttr._is_id:
- idAttr.__dict__['_is_id'] = True
+ idAttr._is_id = True
 self._magic_id_nodes += 1
 self.ownerDocument._magic_id_count += 1
 _clear_id_cache(self)
@@ -893,8 +896,7 @@
 # This creates a circular reference, but Element.unlink()
 # breaks the cycle since the references to the attribute
 # dictionaries are tossed.
- attr.__dict__['ownerElement'] = element
-
+ attr.ownerElement = element
 
 class Childless:
 """Mixin that makes childless-ness easy to implement and avoids
@@ -938,54 +940,49 @@
 
 class ProcessingInstruction(Childless, Node):
 nodeType = Node.PROCESSING_INSTRUCTION_NODE
+ __slots__ = ('target', 'data')
 
 def __init__(self, target, data):
- self.target = self.nodeName = target
- self.data = self.nodeValue = data
+ self.target = target
+ self.data = data
 
- def _get_data(self):
+ # nodeValue is an alias for data
+ def _get_nodeValue(self):
 return self.data
- def _set_data(self, value):
- d = self.__dict__
- d['data'] = d['nodeValue'] = value
+ def _set_nodeValue(self, value):
+ self.data = data
+ nodeValue = property(_get_nodeValue, _set_nodeValue)
 
- def _get_target(self):
+ # nodeName is an alias for target
+ def _get_nodeName(self):
 return self.target
- def _set_target(self, value):
- d = self.__dict__
- d['target'] = d['nodeName'] = value
-
- def __setattr__(self, name, value):
- if name == "data" or name == "nodeValue":
- self.__dict__['data'] = self.__dict__['nodeValue'] = value
- elif name == "target" or name == "nodeName":
- self.__dict__['target'] = self.__dict__['nodeName'] = value
- else:
- self.__dict__[name] = value
+ def _set_nodeName(self, value):
+ self.target = value
+ nodeName = property(_get_nodeName, _set_nodeName)
 
 def writexml(self, writer, indent="", addindent="", newl=""):
 writer.write("%s<?%s %s?>%s" % (indent,self.target, self.data, newl))
 
 
 class CharacterData(Childless, Node):
+ __slots__=('_data', 'ownerDocument','parentNode', 'previousSibling', 'nextSibling')
+
+ def __init__(self):
+ self.ownerDocument = self.parentNode = None
+ self.previousSibling = self.nextSibling = None
+ self._data = ''
+ Node.__init__(self)
+
 def _get_length(self):
 return len(self.data)
 __len__ = _get_length
 
 def _get_data(self):
- return self.__dict__['data']
+ return self._data
 def _set_data(self, data):
- d = self.__dict__
- d['data'] = d['nodeValue'] = data
+ self._data = data
 
- _get_nodeValue = _get_data
- _set_nodeValue = _set_data
-
- def __setattr__(self, name, value):
- if name == "data" or name == "nodeValue":
- self.__dict__['data'] = self.__dict__['nodeValue'] = value
- else:
- self.__dict__[name] = value
+ data = nodeValue = property(_get_data, _set_data)
 
 def __repr__(self):
 data = self.data
@@ -1042,11 +1039,6 @@
 
 
 class Text(CharacterData):
- # Make sure we don't add an instance __dict__ if we don't already
- # have one, at least when that's possible:
- # XXX this does not work, CharacterData is an old-style class
- # __slots__ = ()
-
 nodeType = Node.TEXT_NODE
 nodeName = "#text"
 attributes = None
@@ -1112,9 +1104,7 @@
 else:
 break
 if content:
- d = self.__dict__
- d['data'] = content
- d['nodeValue'] = content
+ self.data = content
 return self
 else:
 return None
@@ -1160,7 +1150,8 @@
 nodeName = "#comment"
 
 def __init__(self, data):
- self.data = self.nodeValue = data
+ CharacterData.__init__(self)
+ self._data = data
 
 def writexml(self, writer, indent="", addindent="", newl=""):
 if "--" in self.data:
@@ -1169,11 +1160,6 @@
 
 
 class CDATASection(Text):
- # Make sure we don't add an instance __dict__ if we don't already
- # have one, at least when that's possible:
- # XXX this does not work, Text is an old-style class
- # __slots__ = ()
-
 nodeType = Node.CDATA_SECTION_NODE
 nodeName = "#cdata-section"
 
@@ -1504,18 +1490,19 @@
 node.ownerDocument._id_search_stack= None
 
 class Document(Node, DocumentLS):
+ __slots__ = ('_elem_info', 'doctype',
+ '_id_search_stack', 'childNodes', '_id_cache')
 _child_node_types = (Node.ELEMENT_NODE, Node.PROCESSING_INSTRUCTION_NODE,
 Node.COMMENT_NODE, Node.DOCUMENT_TYPE_NODE)
 
+ implementation = DOMImplementation()
 nodeType = Node.DOCUMENT_NODE
 nodeName = "#document"
 nodeValue = None
 attributes = None
- doctype = None
 parentNode = None
 previousSibling = nextSibling = None
 
- implementation = DOMImplementation()
 
 # Document attributes from Level 3 (WD 9 April 2002)
 
@@ -1530,6 +1517,7 @@
 _magic_id_count = 0
 
 def __init__(self):
+ self.doctype = None
 self.childNodes = NodeList()
 # mapping of (namespaceURI, localName) -> ElementInfo
 # and tagName -> ElementInfo
@@ -1815,17 +1803,15 @@
 element.removeAttributeNode(n)
 else:
 element = None
- # avoid __setattr__
- d = n.__dict__
- d['prefix'] = prefix
- d['localName'] = localName
- d['namespaceURI'] = namespaceURI
- d['nodeName'] = name
+ n.prefix = prefix
+ n._localName = localName
+ n.namespaceURI = namespaceURI
+ n.nodeName = name
 if n.nodeType == Node.ELEMENT_NODE:
- d['tagName'] = name
+ n.tagName = name
 else:
 # attribute node
- d['name'] = name
+ n.name = name
 if element is not None:
 element.setAttributeNode(n)
 if is_id:
-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list

AltStyle によって変換されたページ (->オリジナル) /