How to convert a “custom class”-based singleton object programmatically into a python module?

六眼飞鱼酱① 提交于 2019-12-11 04:55:21

问题


I would like to convert a singleton-object programmatically into a Python module so that I can use the methods of this singleton-object directly by importing them via the module instead of accessing them as object attributes. By "programmatically" I mean that I do not want to have to copy-paste the class methods explicitly into a module file. I need some sort of a workaround that allows me to import the object methods into to global scope of another module.

I would really appreciate if someone could help me on this one.

Here is a basic example that should illustrate my problem:

mymodule.py

class MyClass:
"""This is my custom class"""
    def my_method(self):
        return "myValue"

singleton = MyClass()

main_as_is.py

from mymodule import MyClass

myobject = MyClass()
print(myobject.my_method())

main_to_be.py

from mymodule import my_method # or from mymodule.singleton import my_method

print(my_method())

回答1:


You can use the same strategy that the standard random module uses. All the functions in that module are actually methods of a "private" instance of the Random class. That's convenient for most common uses of the module, although sometimes it's useful to create your own instances of Random so that you can have multiple independent random streams.

I've adapted your code to illustrate that technique. I named the class and its instance with a single leading underscore, since that's the usual convention in Python to signify a private name, but bear in mind it's simply a convention, Python doesn't do anything to enforce this privacy.

mymodule.py

class _MyClass:
    """ This is my custom class """
    def my_method(self):
        return "myValue"

_myclass = _MyClass()
my_method = _myclass.my_method

main_to_be.py

from mymodule import my_method

print(my_method())       

output

myValue

BTW, the from mymodule import method1, method2 syntax is ok if you only import a small number of names, or it's clear from the name which module it's from (like math module functions and constants), and you don't import from many modules. Otherwise it's better to use this sort of syntax

import mymodule as mm
# Call a method from the module
mm.method1()

That way it's obvious which names are local, and which ones are imported and where they're imported from. Sure, it's a little more typing, but it makes the code a whole lot more readable. And it eliminates the possibility of name collisions.

FWIW, here's a way to automate adding all of the _myclass methods without explicitly listing them (but remember "explicit is better than implicit"). At the end of "mymodule.py", in place of my_method = _myclass.my_method, add this:

globals().update({k: getattr(_myclass, k) for k in _MyClass.__dict__ 
    if not k.startswith('__')})

I'm not comfortable with recommending this, since it directly injects items into the globals() dict. Note that that code will add all class attributes, not just methods.


In your question you talk about singleton objects. We don't normally use singletons in Python, and many programmers in various OOP languages consider them to be an anti-pattern. See https://stackoverflow.com/questions/12755539/why-is-singleton-considered-an-anti-pattern for details. For this application there is absolutely no need at all to use a singleton. If you only want a single instance of _MyClass then simply don't create another instance of it, just use the instance that mymodule creates for you. But if your boss insists that you must use a singleton, please see the example code here.



来源:https://stackoverflow.com/questions/50370744/how-to-convert-a-custom-class-based-singleton-object-programmatically-into-a-p

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!