Let us open a small idf file and look at the underlying data structure.
We know that constructions us just syntactic sugar around the underlying data structure. Let us call the underlying data structure real_constructions
So any changes made in constructions should reflected in constructions. Let us test this out.
Even though we made the change only in constructions, we can see the changes in both constructions and real_constructions. Ep_Bunch takes care of this for us.
since constructions is a list, we can do all the list operations on it. Let us try some of them:
That makes sense. We poped the first item in the list and now we have only two items.
Is this change reflected in real_constructions ?
Dammit !! Why not ?
We still have 3 items in real_constructions and 2 items in constructions
constructions and real_constructions are lists. constructions[0].Name = "New C1" we see changes to an item within constructions is reflected within real_constructionsEpBunch takes care of that connectionconstructions will not be reflected in real_constructions This is how it works in eppy version 0.5
We need to fix this. Now we describe how this problem was fixed.
constructions should be a list-like wrapper around real_constructions. Python has an excellent data structure called collections.MutableSequence that works perfectly for this. Alex Martelli has a great discussion of this in this stackoverflow thread Overriding append method after inheriting from a Python List
eppy.idf_msequence.Idf_MSequence that inherits form collections.MutableSequenceconstructions is now an instance of eppy.idf_msequence.Idf_MSequenceeppy.idf_msequence.Idf_MSequence should show you how it workseppy.idf_msequence.Idf_MSequenceLet us take a look at how it works (in all versions of eppy newer than 0.5):
In [4]:
# using eppy version greater than 0.5
import sys
# pathnameto_eppy = 'c:/eppy'
pathnameto_eppy = '../../../'
sys.path.append(pathnameto_eppy)
from eppy import modeleditor
from eppy.modeleditor import IDF
iddfile = "../../../eppy/resources/iddfiles/Energy+V7_2_0.idd"
fname1 = "../../../eppy/resources/idffiles/V_7_2/smallfile.idf"
IDF.setiddname(iddfile)
idf = IDF(fname1)
idf.newidfobject('construction'.upper(), Name='C1')
idf.newidfobject('construction'.upper(), Name='C2')
idf.newidfobject('construction'.upper(), Name='C3')
constructions = idf.idfobjects['construction'.upper()]
In [5]:
print constructions
In [8]:
real_constructions = idf.model.dt['construction'.upper()]
print real_constructions
Shall we test pop(0) here ?
In [9]:
constructions.pop(0)
Out[9]:
In [10]:
print constructions
In [11]:
print real_constructions
Awesome !!! both constructions and real_constructions have the same number of items
In [12]:
print type(constructions)
print type(real_constructions)
what kind of sorcery is this. How did that work. How does Idf.Msequence do this magic ? Let us look at that link in stackoverflow. The question raised in stackovverflow is:
I want to create a list that can only accept certain types. As such, I'm trying to inherit from a list in Python, and overriding the append() method like so: and there is a sample code after this.
Alex Martelli responds:
Not the best approach! Python lists have so many mutating methods that you'd have to be overriding a bunch (and would probably forget some).
Rather, wrap a list, inherit from collections.MutableSequence, and add your checks at the very few "choke point" methods on which MutableSequence relies to implement all others. Alex's code follows after this point. In eppy.idf_msequence I have included Alex's code.
Stop here and read through the stackoverflow link
Well ... you don't really have to. It does go off on some tangents unrelated to what we do in eppy.
The strategy in eppy.idf_msequence.Idf_MSequence is to have two lists, list1 and list2. To play with this I made a simple class TwoLists. Here TwoLists acts just like a list. Any operation list operation on TwoLists will result in a similar operation on both list1 and list2. TwoLists is not used in eppy, I simply use it to flesh out how MutableSequence can be used. I am going to play with TwoLists here to show you how cool it is :-)
In [16]:
from eppy.idf_msequence import TwoLists
twolists = TwoLists()
print twolists
In [18]:
twolists.append(5)
print twolists
In [19]:
twolists.append(dict(a=15))
print twolists
In [20]:
twolists.insert(1, 42)
print twolists
In [21]:
twolists.pop(-1)
Out[21]:
In [22]:
print twolists
Isn't that neat !! Idf_MSequence works in a similar way. Out of sheer laziness I am going to let you figure it out on your own. (ignore Idf_MSequence_old, since that went in the wrong direction)
In [ ]: