Javascript has a pattern for creating private functions called JavaScript's Revealing Module Pattern.
It hides your functions in a closure that returns an object modified to provide access to the functions you want public.
Both languages have the same lack of a private keyword. Sure you can use the leading underscore convention to signal your desire for privacy but some apparently want to enforce this.
Is there any technical reason this pattern doesn't exist in Python? Python isn't quiet the prototyped language that javascript is but it's close. It has closures as well so I was surprised that I could find no references to this pattern from the Python community. Does it go by a different name there?
Is there a technical reason it can't be done in Python or is this simply a difference in community culture?
-
1This may contribute: stackoverflow.com/questions/1547145/…User– User2017年08月12日 08:08:58 +00:00Commented Aug 12, 2017 at 8:08
-
generally, the python culture is like "we are all consenting adults here", so just a convention for private stuff is enough — if someone wants to shoot themselves in the foot, then enforced encapsulation won't hold them anyway, and sometimes it's handy to have direct access to private stuff if one acknowledges possible negative consequences.Display Name– Display Name2017年08月12日 14:55:26 +00:00Commented Aug 12, 2017 at 14:55
1 Answer 1
Python has built-in support for modules and classes, so approaches like the revealing module pattern are less necessary. But since Python does not support any encapsulation except by convention, imitating JS-style modules is sometimes convenient.
The difficulty is that Python does not have anonymous functions/lambdas with statement bodies. You therefore cannot write an IIFE (immediately invoked function expression) like (function () { ... })()
. We must instead use a named function.
def make_module():
private_var = 42
def private_function():
pass
class PrivateClass(object):
pass
class PublicClass(object):
pass # may use the private symbols
return PublicClass
the_module = make_module() # the_module is actually PublicClass
We can use a decorator to invoke a function declaration immediately. With the module contents the same, this code has the same effect as above:
def module(make_module):
return make_module()
@module
def the_module():
... # as above
Python's class
declarations work very similar to this @module
except that instead of returning some symbols, all locals()
of the declaration body are captured and turned into the members of a new class. You could therefore perhaps also use metaclass hackery to remove some functions from a class definition.
A drawback of closure-based modules is that the private symbols do not have a fully qualified global name – you can't address them from the outside. I know that is the entire point of encapsulation, but this also means that you cannot pickle
such objects, which may be a problem for some use cases.