关于python:为什么有些函数在函数名之前和之后都有下划线?

Why do some functions have underscores “__” before and after the function name?

这似乎经常发生,并且想知道这是Python语言中的一个需求,还是仅仅是一个约定的问题?

另外,有人能说出并解释哪些函数往往带有下划线,以及为什么(例如__init__)。


从python pep 8——python代码样式指南:

Descriptive: Naming Styles

The following special forms using leading or trailing underscores are
recognized (these can generally be combined with any case convention):

  • _single_leading_underscore: weak"internal use" indicator. E.g. from M import * does not import objects whose name starts with an underscore.

  • single_trailing_underscore_: used by convention to avoid conflicts with Python keyword, e.g.

    Tkinter.Toplevel(master, class_='ClassName')

  • __double_leading_underscore: when naming a class attribute, invokes name mangling (inside class FooBar, __boo becomes _FooBar__boo; see below).

  • __double_leading_and_trailing_underscore__:"magic" objects or attributes that live in user-controlled namespaces. E.g. __init__,
    __import__ or __file__. Never invent such names; only use them as documented.

请注意,具有双前导和尾随下划线的名称基本上是为Python本身保留的:"永远不要发明这样的名称;只在文档中使用它们"。


其他受访者正确地将双前导和尾随下划线描述为"特殊"或"魔力"方法的命名约定。

虽然您可以直接调用这些方法(例如,[10, 20].__len__()),但下划线的出现暗示了这些方法将被间接调用(例如,len([10, 20]))。大多数python操作符都有一个关联的"magic"方法(例如,a[x]是调用a.__getitem__(x)的常用方法)。


被双下划线包围的名称对于Python来说是"特殊的"。它们列在Python语言参考第3节"数据模型"中。


实际上,当需要区分父类和子类名称时,我会使用方法名称。我读过一些用这种方式创建父子类的代码。例如,我可以提供以下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
class ThreadableMixin:
   def start_worker(self):
       threading.Thread(target=self.worker).start()

   def worker(self):
      try:
        self._worker()
    except tornado.web.HTTPError, e:
        self.set_status(e.status_code)
    except:
        logging.error("_worker problem", exc_info=True)
        self.set_status(500)
    tornado.ioloop.IOLoop.instance().add_callback(self.async_callback(self.results))

以及有工人方法的孩子

1
2
3
4
5
6
class Handler(tornado.web.RequestHandler, ThreadableMixin):
   def _worker(self):
      self.res = self.render_string("template.html",
        title = _("Title"),
        data = self.application.db.query("select ... where object_id=%s", self.object_id)
    )


后面双下划线(名称混乱)/来自python文档

Any identifier of the form __spam (at least two leading underscores,
at most one trailing underscore) is textually replaced with
_classname__spam, where classname is the current class name with leading underscore(s) stripped. This mangling is done without regard
to the syntactic position of the identifier, so it can be used to
define class-private instance and class variables, methods, variables
stored in globals, and even variables stored in instances. private to
this class on instances of other classes.

Name mangling is intended to give classes an easy way to define
"private" instance variables and methods, without having to worry
about instance variables defined by derived classes, or mucking with
instance variables by code outside the class. Note that the mangling
rules are designed mostly to avoid accidents; it still is possible for
a determined soul to access or modify a variable that is considered
private.


此约定用于特殊变量或方法(所谓的"magic method"),如_uuu init_uuuuuu,len。这些方法提供特殊的句法特征或做特殊的事情。

例如,file表示python文件的位置,eq在执行a==b表达式时执行。

用户当然可以定制特殊的方法,这是非常罕见的情况,但往往会修改一些内置的特殊方法。(例如,您应该用init初始化类,该init将在创建类实例时首先执行。)

1
2
3
4
5
   class A:
      def __init__(self, a): # use special method '__init__' for initializing
        self.a = a
      def __custom__(self): # custom special method. you might almost do not use it
        pass