9

In C++ I would write:

namespace LowerLevel{
int DoStuff() {}; //
}

And access it via:

LowerLevel::DoStuff()

How do I do both in Python?

3 Answers3

12

The closest in spirit would be to use a module.

In a file lower_level.py you'd have

def do_stuff():
  pass

and then elsewhere you'd do:

import lower_level
lower_level.do_stuff()

EDIT / addendums: That's the simple way. There's things like packages, where you'd have a folder lower_level, and inside that folder is an __init__.py identifying lower_level as a package. Inside that package you'd have .py files that'd be modules, or you put certain imports and declarations into the __init__.py. But it can also just remain empty. I guess packages would amount to nested namespaces.

- prog.py
\MyNameSpaceA
    - __init__.py # just an empty file
    - ObjA.py # A python Module
    \SubPackageB
       - __init__.py
       - ObjB.py # another python module
Joran Beasley
  • 110,522
  • 12
  • 160
  • 179
cadolphs
  • 9,014
  • 1
  • 24
  • 41
  • And of course there's a bunch of variations on that theme, for example `from lower_level import do_stuff` and that puts `do_stuff` into the namespace of the importing module. Or you do the EVIL and NOT RECOMMENDED `from lower_level import *` and then everything from `lower_level` is in the importing namespace... – cadolphs Mar 13 '17 at 21:45
  • Or a package (don't forget `__init__.py`!), which is really just a folder with modules in it. – Dan Mar 13 '17 at 21:46
  • How would I do nested namespaces? SpaceA::SpaceB::DoStuff()? –  Mar 13 '17 at 21:47
  • See my addendum. Packages, implemented as nested folders – cadolphs Mar 13 '17 at 21:49
  • @Dan In newer versions of Python, `__init__.py` is no longer required. – Christian Dean Mar 13 '17 at 22:12
2

One more option is to define everything in a function and return the locals. The advantage is that all definitions are in the same scope, so they can reference each other without any prefixes. Also you can have many of these in the same file.

import argparse

def InitLowerLevel():
    def DoStuff():
        return 1
    def DoOtherStuff():
        return DoStuff()
    kFoo = 0
    return argparse.Namespace(**locals())

lower_level = InitLowerLevel()

lower_level.DoStuff()

pkarnakov
  • 123
  • 1
  • 7
  • 1
    `argparse` is used for taking command line arguments into the program. I don't see any reason to use it for anything else... – Tomerikoo Sep 30 '20 at 16:49
  • 1
    @Tomerikoo `argparse.Namespace` is convenient for this case, and `argparse` is a standard module, so why not use it. any alternative? – pkarnakov Sep 30 '20 at 18:28
  • yeah well I guess you're right, I mean it's convenient to use the `**kwargs` option in the constructor. It's just that a `Namespace` object is very basic and you could do that with any other object, even a function. – Tomerikoo Oct 01 '20 at 08:02
0

The argparse module may also be an option to consider, depending on your use case. The original answer is what I would say the better Software Development best practice, but this module provides the functionality you originally asked for.

It allows the dot notation to set and get variables. But complains less than dicts for when you are trying to add new variables/functions.

Python 3

>>> import argparse
>>> def my_test_function(): return
>>> ...
>>> args = argparse.Namespace()
Namespace()
>>> args.minutes  = 5
>>> args.test = my_test_function
>>> args
Namespace(minutes=5, test=<function times_close_enough at 0x000001D2BEEAA550>)

Although the proper way to use argparse can be found at its documentation , some further examples can be found on this StackOverflow question (helps if you understand better by example!)

Adehad
  • 519
  • 6
  • 16