NoPayn
NoPayn

Reputation: 49

Dynamically adding attributes to __init__ method in python

Is there any way you can define a function that can add,at some later point in the program, new attributes to an already existing __init__ method? For example, below I created a Class for a Family Tree. Each instance would create a root.

class FamilyTree:
    def __init__(self,rootObj):
        self.key = rootObj

I want each new root instance to have the ability to have a specific number of children attributes: For example:

self.child1 = 'B'
self.child2 = 'C'
self.child3 = 'D'

Since every new root instance can have various number of children, how can I variably add new attributes to the __init__ method?

Upvotes: 2

Views: 3452

Answers (4)

Dhia
Dhia

Reputation: 10609

A possible way to automate this is as follow:

class FamilyTree:
    def __init__(self,rootObj, child_names=None):
        self.key = rootObj
        if child_names is not None:
            # child_names is a list of child attributes values
            for i, child in enumerate(child_names):
                setattr(self, 'child{0}'.format(i), child)
            setattr(self, 'child_nbr', len(child_names))

    def add_child(self, *child_names)
        for name in child_names:
            self.child_nbr += 1
            setattr(self, 'child{0}'.format(self.child_nbr), name)

usage:

>>> f=FamilyTree('Family1', ['B', 'C', 'D'])
>>> print(f.child1, f.child2, f.child3)
>>> i = 0
>>> while i < f.child_nbr:
>>>     print getattr(f, 'child{0}'.format(i+1))
>>> f.add_child('E')
>>> print(f.child4)
>>> f.add_child('F', 'G')
>>> print(f.child5, f.child6) 

Upvotes: 2

Byte Commander
Byte Commander

Reputation: 6736

I guess what you really (should) want is a list of children:

class FamilyTree:

    def __init__(self, rootObj):
        self.key = rootObj
        self.children = []

    def add_children(*new_children)
        self.children.extend(new_children)

Now you can use the add_children method to add any number of children to the list at once, or you could simply directly access the children instance member list as well:

tree = FamilyTree("whatever a rootObj is...")

tree.add_children("Alice", "Bob", "Claudia", "Dave")
tree.children.append("Eva")
tree.children += ["Fred", "Gina", "Herbert"]

print(tree.children)
# Output: ["Alice", "Bob", "Claudia", "Dave", "Eva", "Fred", "Gina", "Herbert"]

Upvotes: 3

Matthias Schreiber
Matthias Schreiber

Reputation: 2517

Maybe I understand this wrong, but you don't add attributes to the 'init' method, you add attributes to the instance of the class. 'self' refers to the instance of the class. To add attributes during runtime to a class, look at Abhra's example. To add attributes to a specific instance of a class, look here (sorry Abhra, stole your example):

class FamilyTree:
    def __init__(self,rootObj):
        self.key = rootObj



child1='B'
child2='C'
child3='D'

objold=FamilyTree('keyold')

objold.child1=child1
objold.child2=child2
objold.child3=child3


objnew=FamilyTree('keynew')

print objnew.key, objnew.child1, objnew.child2, objnew.child3
print objold.key, objold.child1, objold.child2, objold.child3
'''
keynew AttributeError: 'FamilyTree' object has no attribute 'child1' (same error for the others)
keyold B C D
'''

Upvotes: 0

Abhra
Abhra

Reputation: 61

class FamilyTree:
    def __init__(self,rootObj):
        self.key = rootObj



child1='B'
child2='C'
child3='D'

objold=FamilyTree('keyold')

FamilyTree.child1=child1
FamilyTree.child2=child2
FamilyTree.child3=child3


objnew=FamilyTree('keynew')

print objnew.key,objnew.child1,objnew.child2,objnew.child3
print objold.key,objold.child1,objold.child2,objold.child3
'''
keynew B C D
keyold B C D
'''

Upvotes: 0

Related Questions