8

I have a class A that can be generated from two different ways.

  • a = A(path_to_xml_file)
  • a = A(listA, listB)

The first method has file path as an input to parse from XML file to get listA, and listB. The second method is given two lists.

I can think of two ways to implement multiple constructor. What do you think? What method normally Python guys use for this case?

Check the type

class A():
    def __init__(self, arg1, arg2 = None):
        if isinstance(arg1, str): 
            ...
        elif isinstance(arg1, list):
            ...

a = A("abc")
b = A([1,2,3],[4,5,6])

Make different builders

class A2():
    def __init__(self):
        pass
    def genFromPath(self, path):
        ...
    def genFromList(self, list1, list2):
        ...
a = A2()
a.genFromPath("abc")
b = A2()
b.genFromList([1,2,3],[4,5,6])

5 Answers 5

7

Make the constructor take the two lists. Write a factory classmethod that parses the XML and returns the object.

Sign up to request clarification or add additional context in comments.

4 Comments

Any reason why a classmethod over a staticmethod?
@Peter: So that if the class is derived from, the method will pick the proper class to instantiate regardless.
Why the asymmetry? That is, why not two factory classmethods, one for XML and one for a pair of lists? Or is it because you assume the "pair of list" is a "natural" way to build this object, so that factory method could rely on the "pair of list" constructor?
@max: list is a native Python type. XML is not.
3

Use classmethod for second one

class A(object):
    @classmethod
    def from_string(cls, string):
        # ...

    @classmethod
    def from_lists(cls, list1, list2):
        # ...

Use module's functions

def from_string(string):
    # ...

def from_lists(list1, list2):
    # ...

class A(object):
    pass

Comments

3

Since the number of arguments passed to the initializer is different in each case, you can avoid type-checking by using the extended call syntax:

class A(object):
    def __init__(self, *args):
        if len(args) == 1:
            path = args[0]
            ...
        elif len(args) == 2:
            list1 = args[0]
            list2 = args[1]
            ...
        else:
            raise SomeException()

1 Comment

Note that this is not really a good method since it goes against Python's usually self-documenting nature.
2

Looking at the problem more closely, I'd suggest having the class take two lists, and include a helper function in the module:

class A(object):
    def __init__(self, list1, list2):
        # Init from lists here
        pass

def create_A_from_path(path):
    list1, list2 = parse_xml_into_lists(path)
    return A(list1, list2)

Comments

2
class A(object):
    @staticmethod
    def from_string(str):
        obj =A()
        obj.str = str
        return obj

    @staticmethod
    def from_list(lis):
        obj = A()
        obj.lis = lis
        return obj

>>>
(obj1, obj2) = A.from_string('hello'), A.from_list(['one', 'two'])

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.