Reputation: 933
I am using python 2.7 and I want to create some kind of data structure, using classes
Question A:
Let's say that I create this class:
class my_data():
def __init__(self,data1,data2,data3):
self.data1 = data1
self.data2 = data2
self.data3 = data3
and after that I create some instances of the class, e.g.
d1 = my_data(1,2,None)
d2 = my_data(4,5,d1)
d3 = my_data(7,8,d2)
As you see, data3 may be None or an instance. So far so good.
Now, let's once more try to create some other instances (the hard way):
d2 = my_data(4,5,d1)
d1 = my_data(1,2,None)
d3 = my_data(7,8,d2)
In this case NameError Exception will occur, because obviously in line d2 = my_data(4,5,d1), d1 has not been defined.
So, here is the question: I want to create instances in which data3 should be None or an instance. If data3 is None or an existed instance, no problem. But if data3 refers to an unexisted instance, I want that instance to be created.
For example: d2 = my_data(4,5,d1)
if d1 does not exist, I want to be initiated as a dummy instance d1 = my_data(None,None,None), and after that, d2 to be initiated as well
I tried this but doesn't seem to do the trick:
class my_data():
def __init__(self,data1,data2,data3):
self.data1 = data1
self.data2 = data2
try:
self.data3 = data3
except:
data3 = my_data(None,None,None)
self.data3 = data3
Question B:
Let's say that somehow we have created some instances (d1,d2,d3,...) of the class. How can I store the instances in a list inside the class, so every instance which has been created in this class to be included in the list?
something like my_data.my_list() which will produce [d1, d2, d3, ...]
Any ideas will be appreciated
Upvotes: 2
Views: 423
Reputation: 371
Have you ever think about redesign your data structure and object? create a instance of object A inside object A is not a good approach. Maybe you should divide the my_data into two objects. one holds the two values, the other holds the relatioinships and the list.
PS: I strongly suspect you are representing graphs using my_data, if so try Networkx, a good packages for graph stuffs.
Upvotes: 0
Reputation: 1121266
You cannot materialize an object from a non-existing reference. Python names have to exist for them to work.
Instead, give the data3
keyword a default, then when the keyword is not specified, create the instance:
_sentinel = object()
class my_data():
def __init__(self, data1, data2, data3=_sentinel):
if data3 is _sentinel:
data3 = my_data(None, None, None)
self.data1 = data1
self.data2 = data2
self.data3 = data3
Now you can create instances of my_data()
with a default new instance for data3
:
>>> d2 = my_data('a', 'b')
>>> d1 = d2.data3
>>> d1
<__main__.my_data instance at 0x10e994cf8>
>>> vars(d2), vars(d1)
({'data1': 'a', 'data3': <__main__.my_data instance at 0x10e994cf8>, 'data2': 'b'}, {'data1': None, 'data3': None, 'data2': None})
Because we used a sentinel default value, you can still set data3
to None
as well:
>>> d3 = my_data('a', 'b', None)
>>> d3.data3 is None
True
A mutable list on the class can hold all instances; just set the list as a class attribute and append new instances to that:
_sentinel = object()
class my_data():
instances = []
def __init__(self, data1, data2, data3=_sentinel):
if data3 is _sentinel:
data3 = my_data(None, None, None)
self.data1 = data1
self.data2 = data2
self.data3 = data3
my_data.instances.append(self)
and you can list all instances with my_data.instances
.
Do note that this creates circular references, keeping instances alive even when you no longer use them anywhere else. Use the weakref
module if you want to prevent this.
Upvotes: 10