0

The goal:

  • B in inherits from A.
  • A and B have a factory method create, which harmonizes different input types before initializing the actual class.
  • create calls different create methods create_general_1, create_general_2, create_specific_b_1 via their name, supplied as a string.

This is my current approach:

import sys

class A:
    def __init__(self, text):
        self.text = text
        print("I got initialized: {}".format(text))

    def create(create_method_str):
        # This is where it breaks:
        create_method = getattr(sys.modules[__name__], create_method_str)
        return create_method()

    def create_general_style_3():
        return A("a, #3")

class B(A):
    def create_b_style_1():
        return B("b, #1")

if __name__ == "__main__":
    B.create("create_b_style_1")

It fails with the following error:

Traceback (most recent call last): File "test.py", line 22, in B.create("create_b_style_1") File "test.py", line 10, in create create_method = getattr(sys.modules[__name__], create_method_str) AttributeError: 'module' object has no attribute 'create_b_style_1'

So in a way, I'm trying to combine three things: factory methods, inheritance, and function calling by name. It would be great if someone had a smarter approach, or knew how to get this approach to work.

Thanks a great lot!

Two-Bit Alchemist
  • 17,966
  • 6
  • 47
  • 82
elke
  • 1,220
  • 2
  • 12
  • 24
  • 1
    You've got some problems in the code you have now. You're not defining methods correctly, for one. Each must have `self` or `cls` as the first argument, depending on whether they're [instance or class methods](http://stackoverflow.com/q/17134653/2588818). You probably want `create` to be a [static method](http://stackoverflow.com/q/735975/2588818). You probably also want to let `create` call the subfunctions without passing their names in as strings. That just seems fragile, if only because you might want to rename the functions later without retraining your users. – Two-Bit Alchemist Oct 29 '15 at 21:48
  • Very fast reply, great! I've proposed an Answer with your help. Concerning fragility: At some point, user input will need to be mapped to internal methods. This is always gonna be fragile, no matter where the mapping takes places. Exception handling can easily be integrated in the current solution. If you know a better solution though, I'm very happy to hear! – elke Oct 29 '15 at 22:17

1 Answers1

1

Thanks to Two-Bit Alchemist's comment, I've created this solution, which seems to work fine. Any improvements / other proposals are more than welcome :)

All is well explained here.

import sys

class A:
    def __init__(self, text):
        self.text = text
        print("I got initialized: {}".format(text))

    @classmethod
    def create(cls, create_method_str):
        create_method = getattr(cls, create_method_str)
        return create_method()

    @classmethod
    def create_general_style_3(cls):
        return cls("a, #3")

class B(A):
    @classmethod
    def create_b_style_1(cls):
        return cls("b, #1")

if __name__ == "__main__":
    B.create("create_b_style_1")
Community
  • 1
  • 1
elke
  • 1,220
  • 2
  • 12
  • 24