Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it a good practice to add names to __all__ using a decorator?

Is this a good practice in Python (from Active State Recipes -- Public Decorator)?

import sys

def public(f):
  """Use a decorator to avoid retyping function/class names.

  * Based on an idea by Duncan Booth:
  http://groups.google.com/group/comp.lang.python/msg/11cbb03e09611b8a
  * Improved via a suggestion by Dave Angel:
  http://groups.google.com/group/comp.lang.python/msg/3d400fb22d8a42e1
  """
  all = sys.modules[f.__module__].__dict__.setdefault('__all__', [])
  if f.__name__ not in all:  # Prevent duplicates if run from an IDE.
      all.append(f.__name__)
  return f

public(public)  # Emulate decorating ourself

The general idea would be to define a decorator that takes a function or class and adds its name to the __all__ of the current module.

like image 841
Ed L Avatar asked Jun 01 '11 18:06

Ed L


People also ask

Which of the following is true about decorators in Python?

Decorators can be chained A Decorator function is used only to format the output of another function dec keyword is used for decorating a function Decorators always return None” Code Answer.

What is the use of decorator in Python?

A decorator in Python is a function that takes another function as its argument, and returns yet another function . Decorators can be extremely useful as they allow the extension of an existing function, without any modification to the original function source code.

How do you use multiple decorators in Python?

Chaining decorators means applying more than one decorator inside a function. Python allows us to implement more than one decorator to a function. It makes decorators useful for reusable building blocks as it accumulates several effects together. It is also known as nested decorators in Python.

What is the Python decorator give an example?

When to Use a Decorator in Python. You'll use a decorator when you need to change the behavior of a function without modifying the function itself. A few good examples are when you want to add logging, test performance, perform caching, verify permissions, and so on.


4 Answers

The more idiomatic way to do this in Python is to mark the private functions as private by starting their name with an underscore:

def public(x):
      ...


def _private_helper(y):
    ...

More people will be familiar with this style (which is also supported by the language: _private_helper will not be exported even if you do not use __all__) than with your public decorator.

like image 64
luispedro Avatar answered Oct 16 '22 12:10

luispedro


Yes, it's a good practice. This decorator allows you to state your intentions right at function or class definition, rather than directly afterwards. That makes your code more readable.

@public 
def foo():
    pass 

@public 
class bar():
    pass

class helper(): # not part of the modules public interface! 
    pass

Note: helper is still accessible to a user of the module by modulename.helper. It's just not imported with from modulename import *.

like image 26
Steven Rumbalski Avatar answered Oct 16 '22 12:10

Steven Rumbalski


I think the question is a bit subjective, but I like the idea. I usually use __all__ in my modules but I sometimes forget to add a new function that I intended to be part of the public interface of the module. Since I usually import modules by name and not by wildcards, I don't notice the error until someone else in my team (who uses the wildcard syntax to import the entire public interface of a module) starts to complain.

Note: the title of the question is misleading as others have already noticed among the answers.

like image 1
Tamás Avatar answered Oct 16 '22 11:10

Tamás


This doesn't automatically add names to __all__, it simply allows you to add a function to all by decorating it with @public. Seems like a nice idea to me.

like image 1
LaC Avatar answered Oct 16 '22 11:10

LaC