There are two places where memory will expand in your code:
1) making a copy of graph1 (perhaps you need to keep a copy though)
2) using graph2.edges() makes a list of all edges in memory, graph2.edges_iter() iterates over the edges without creating a new list
You can probably make it faster by handling the edge data differently too. You can get the data object while iterating over the edges and not have to perform as may dictionary lookups:
def combined_graphs_edges(G, H, weight = 1.0):
for u,v,hdata in H.edges_iter(data=True):
# multply attributes of H by weight
attr = dict( (key, value*weight) for key,value in hdata.items())
# get data from G or use empty dict if no edge in G
gdata = G[u].get(v,{})
# add data from g
# sum shared items
shared = set(gdata) & set(hdata)
attr.update(dict((key, attr[key] + gdata[key]) for key in shared))
# non shared items
non_shared = set(gdata) - set(hdata)
attr.update(dict((key, gdata[key]) for key in non_shared))
yield u,v,attr
return
if __name__ == '__main__':
import networkx as nx
G = nx.Graph([('a','b', {'a': 1, 'b':2})])
H = nx.Graph([('a','b', {'a': 3, 'c':4})])
print list(combined_graphs_edges(G,H,weight=0.5))
# or to make a new graph
graph = G.copy()
graph.add_edges_from(combined_graphs_edges(G,H,weight=0.5))