Reputation: 113
I have created chained methods across a set of classes, but when I set values for the last link in the chain, it is overwriting value in what I thought were separate instances within the class chain.
For example:
sub0.one.some.a.time_t.raw = 1
sub0.one.some.b.time_t.raw = 2
But:
print sub0.one.some.a.time_t.raw
returns 2
(not 1
, as set above)
print sub0.one.some.b.time_t.raw
returns 2
Code is below. Sub0
is the top level in the chain, Sub4
is the lowest. I add instances of classes as methods within the class by using the type()
method.
Why isn't sub0.one.some.a.time_t.raw
returning 1
, as I've set it? Isn't it a separate instance of all classes in the chain?
class Sub4(object):
pass
class Sub3(object):
pass
class Sub2(object):
pass
class Sub1(object):
def __init__(self, config):
self.config_field = config['flag']
class Sub0(object):
def __init__(self, config):
self.config = config
sub4_methods = ['raw']
Sub4 = type("Sub4", (Sub4, ), { sub4:None for sub4 in sub4_methods})
sub3_methods = ['time_t']
Sub3 = type("Sub3", (Sub3, ), { sub3:Sub4() for sub3 in sub3_methods})
sub2_methods = ['a', 'b']
Sub2 = type("Sub2", (Sub2, ), { sub2:Sub3() for sub2 in sub2_methods})
sub1_methods = ['all', 'some']
Sub1 = type("Sub1", (Sub1,), { sub1:Sub2() for sub1 in sub1_methods})
configs = {
"one": { "flag": True },
"two": { "flag": False },
}
Sub0 = type("Sub0", (Sub0,), { k:Sub1(v) for (k,v) in zip(configs.keys(), configs.values())})
#create class instance
sub0 = Sub0(configs)
#set values
sub0.one.some.a.time_t.raw = 1
sub0.one.some.b.time_t.raw = 2
#both of these return 1, even though they are set to 1 & 2 respectively
print sub0.one.some.a.time_t.raw
#returns 1
print sub0.one.some.b.time_t.raw
#returns 1
Thanks!
Upvotes: 0
Views: 60
Reputation: 281011
I add instances of classes as methods within the class by using the
type()
method.
That is not what type
does. type
makes an entirely new class. Even if you're aware of that (you don't seem to be), it's a bizarre and unsuitable choice for what you're trying to do.
Isn't it a separate instance of all classes in the chain?
No. All objects in this attribute chain are shared.
If you want Sub0
instances to have Sub1
objects as attributes and Sub1
objects to have Sub2
objects as attributes, etc., do it the normal way, with __init__
:
class Sub0(object):
def __init__(self):
self.one = Sub1({"flag": True})
self.two = Sub1({"flag": False})
class Sub1(object):
def __init__(self):
self.all = Sub2()
self.some = Sub2()
...
If you want to define your attribute names with lists, you can do that using setattr
in __init__
:
class Sub1(object):
def __init__(self):
for name in ['all', 'some']:
setattr(self, name, Sub2())
Upvotes: 2