Use module as class instance in Python
Question: ## TL; DR

Basically the question is about hiding from the user the fact that my modules
have class implementations so that the user can use the module as if it has
direct function definitions like `my_module.func()`

## Details

Suppose I have a module `my_module` and a class `MyThing` that lives in it.
For example:

    
    
    # my_module.py
    
    class MyThing(object):
        def say():
            print("Hello!")
    

In another module, I might do something like this:

    
    
    # another_module.py
    
    from my_module import MyThing
    
    thing = MyThing()
    thing.say()
    

But suppose that I don't want to do all that. What I really want is for
`my_module` to create an instance of MyThing automatically on `import` such
that I can just do something like the following:

    
    
    # yet_another_module.py
    
    import my_module
    
    my_module.say()
    

In other words, whatever method I call on the module, I want it to be
forwarded directly to a default instance of the class contained in it. So, to
the user of the module, it might seem that there is no class in it, just
direct function definitions in the module itself (where the functions are
actually methods of a class contained therein). Does that make sense? Is there
a short way of doing this?

I know I could do the following in `my_module`:

    
    
    class MyThing(object):
        def say():
            print("Hello!")
    
    default_thing = MyThing()
    
    def say():
        default_thing.say()
    

But then suppose `MyThing` has many "public" methods that I want to use, then
I'd have to explicitly define a "forwarding" function for every method, which
I don't want to do.

As an extension to my question above, is there a way to achieve what I want
above, but also be able to use code like `from my_module import *` and be able
to use methods of `MyThing` directly in another module, like `say()`?


Answer: In module `my_module` do the following:

    
    
    class MyThing(object):
        ...
    
    _inst = MyThing()
    say = _inst.say
    move = _inst.move
    

This is _exactly_ the pattern used by the [`random`
module](https://github.com/python/cpython/blob/master/Lib/random.py#L736).

Doing this automatically is somewhat contrived. First, one needs to find out
_which_ of the instance/class attributes are the methods to export... perhaps
export only names which do not start with `_`, something like

    
    
    import inspect
    for name, member in inspect.getmembers(Foo(), inspect.ismethod):
        if not name.startswith('_'):
            globals()[name] = member
    

However in this case I'd say that explicit is better than implicit.

