4

I am working on a factory in Python and would like to make all the imports "private".

So something like this:

from my_classes import MyClass1, MyClass2

class MyFactory(object):
    def __init__(self, class_name):
        if class_name == "my_class_1":
            return MyClass1()
        elif class_name == "my_class_2":
            return MyClass2()

In this case I would like to have the caller be able to use MyFactory, and not see MyClass1 and MyClass2.

I know there is no such thing as private in Python. What I tried is from my_classes import MyClass1 as _my_class_1 but then I get a message Constant variable imported as non-constant

For now I have solved it like this:

class MyFactory(object):
    def __init__(self):
        do my init stuff here

    def create_myclass_1(self):
        from my_classes import MyClass1
        return MyClass1()

    def create_myclass_2(self):
        from my_classes import MyClass2
        return MyClass2()

This does not look very Pythonic to me, but I might be wrong.

Could someone tell me if there is a better way to do this?

Johan Vergeer
  • 5,208
  • 10
  • 48
  • 105
  • The better question would be if your solution has unwanted side effects. If this is not the case why not just use it... – Matthias Nov 09 '16 at 08:08
  • 4
    The whole notion of making classes private is not Pythonic, to be honest. Just give your classes names that start with a single underscore: `_`. – Martijn Pieters Nov 09 '16 at 08:14
  • 1
    The message states that you should use: `from my_classes import MyClass1 as _MyClass1` – Dan D. Nov 09 '16 at 08:38
  • voted to reopen. the "duplicate" is about private modules. this question is about private imports of public functionality. It _can_ be solved by the answer in the duplicate but only in special cases – joel Jul 24 '20 at 15:21

2 Answers2

-1

There is no pythonic and nice way to do this.

you can use __all__

and when you import the module (module you use __all__ in it) in the including module,

you are gonna get everything mentioned in __all__.

more info? see

https://codereview.stackexchange.com/questions/214329/importing-modules-for-private-use-in-python

-3

You could just create an actual factory function

def my_factory(class_name):
    if class_name == "my_class_1":
        return MyClass1()
    elif class_name == "my_class_2":
        return MyClass2()

Alternatively, if you want a little more magic and want it to be treated more like a class, you can override the __new__ method.

class FakeClass(object):
    def __new__(cls, class_name):
        if class_name == "my_class_1":
            cls = MyClass1
        elif class_name == "my_class_2":
            cls = MyClass2
        return object.__new__(cls)
Brendan Abel
  • 35,343
  • 14
  • 88
  • 118