4

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?

  • 1
    This may contribute: stackoverflow.com/questions/1547145/… – User Aug 12 '17 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 Aug 12 '17 at 14:55
4

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.