Defining private module functions in python

Viewed 305656

According to http://www.faqs.org/docs/diveintopython/fileinfo_private.html:

Like most languages, Python has the concept of private elements:

  • Private functions, which can't be called from outside their module

However, if I define two files:

#a.py
__num=1

and:

#b.py
import a
print a.__num

when i run b.py it prints out 1 without giving any exception. Is diveintopython wrong, or did I misunderstand something? And is there some way to do define a module's function as private?

11 Answers

embedded with closures or functions is one way. This is common in JS although not required for non-browser platforms or browser workers.

In Python it seems a bit strange, but if something really needs to be hidden than that might be the way. More to the point using the python API and keeping things that require to be hidden in the C (or other language) is probably the best way. Failing that I would go for putting the code inside a function, calling that and having it return the items you want to export.

For methods: (I am not sure if this exactly what you want)

print_thrice.py

def private(method):
    def methodist(string):
        if __name__ == "__main__":
            method(string)
    return methodist
    
@private
def private_print3(string):
    print(string * 3)

private_print3("Hello ") # output: Hello Hello Hello

other_file.py

from print_thrice import private_print3
private_print3("Hello From Another File? ") # no output

This is probably not a perfect solution, as you can still "see" and/or "call" the method. Regardless, it doesn't execute.

Sorry if I'm late to answer, but in a module, you can define the packages to "export" like this:

mymodule
  __init__.py
  library.py
main.py

mymodule/library.py

# 'private' function
def _hello(name):
    return f"Hello {name}!"

# 'public' function which is supposed to be used instead of _hello
def hello():
    name = input('name: ')
    print(_hello(name))

mymodule/__init__.py

# only imports certain functions from library
from .library import hello

main.py

import mymodule
mymodule.hello()

Nevertheless, functions can still be accessed,

from mymodule.library import _hello
print(_hello('world'))

But this approach makes it less obvious

See PEP8 guideline:

Method Names and Instance Variables

Use the function naming rules: lowercase with words separated by underscores as necessary to improve readability.

Use one leading underscore only for non-public methods and instance variables.

To avoid name clashes with subclasses, use two leading underscores to invoke Python’s name mangling rules.

Python mangles these names with the class name: if class Foo has an attribute named __a, it cannot be accessed by Foo.__a. (An insistent user could still gain access by calling Foo._Foo__a.) Generally, double leading underscores should be used only to avoid name conflicts with attributes in classes designed to be subclassed.

Designing for Inheritance

Always decide whether a class’s methods and instance variables (collectively: “attributes”) should be public or non-public. If in doubt, choose non-public; it’s easier to make it public later than to make a public attribute non-public.

Public attributes are those that you expect unrelated clients of your class to use, with your commitment to avoid backwards incompatible changes. Non-public attributes are those that are not intended to be used by third parties; you make no guarantees that non-public attributes won’t change or even be removed.

We don’t use the term “private” here, since no attribute is really private in Python (without a generally unnecessary amount of work).

Related