Reputation: 14346
I am writing a Python module whose purpose is to export a single data structure. I believe this means my module should export a single symbol (e.g. foo
), with all its other symbols being underscore-prefixed.
Generating the data structure takes a fair amount of code - how should I structure the module to ensure that no symbols within this code are exported without a prefix? Two possible approaches are:
Put the generation code at the top-level, being careful to use underscores throughout, e.g.:
_bar = ...
for _i in ...:
_bar.append(...)
foo = [_bar, ...]
Put the generation code within a function which returns the data structure. This requires only the function name to use an underscore. For example:
def _generate_foo():
bar = ...
for i in ...:
bar.append(...)
return [bar, ...]
foo = _generate_foo()
Is either of these approaches considered better? Or, is there another way to structure this module which would be preferred?
Upvotes: 15
Views: 12832
Reputation: 251478
Note that using the underscore or using __all__
only prevents that name from being imported with from module import *
(as documented). It doesn't make the name "private" in any real way. People can still see everything in your module by doing import module
and then module._hiddenStuff
.
If you want to prevent the symbol from being included in from model import *
, you should use __all__
. Have the code be whatever you want, but at the top of the module do:
__all__ = ['foo'] # foo being the one thing you do want to export in the wildcard `from module import *`
This has the same effect as using underscores but is much better when you want to exclude most things instead of include them.
Upvotes: 29
Reputation: 2315
I prefer the function definition approach from a sheer maintainability perspective.
It is also important to remember that we are all consenting adults and it is the users responsibility to use your module in the manner best suited for their use.
The use of the underscore however is supported by PEP-8 and so any _symbols will not be imported by a import *
Upvotes: 0