Почему некоторые функции подчеркивают "__" до и после имени функции?

Это, кажется, происходит много, и было интересно, было ли это требованием на языке Python или просто вопросом конвенции?

Кроме того, может ли кто-то назвать и объяснить, какие функции имеют тенденцию иметь символы подчеркивания и почему (__init__, например)?

Ответ 1

Из Python PEP 8 - Руководство по стилю для кода Python:

Описательный: стили именования

Следующие специальные формы с использованием ведущих или завершающих подчеркиваний (они обычно могут быть объединены с любым случаем):

  • _single_leading_underscore: слабый индикатор "внутреннего использования". Например. from M import * не импортирует объекты, имя которых начинается с подчеркивания.

  • single_trailing_underscore_: используется по соглашению, чтобы избежать конфликтов с ключевым словом Python, например

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

  • __double_leading_underscore: при присвоении имени атрибуту класса вызывается обращение к имени (внутри класса FooBar, __boo становится _FooBar__boo, см. ниже).

  • __double_leading_and_trailing_underscore__: "магические" объекты или атрибуты, которые находятся в контролируемых пользователем пространствах имен. Например. __init__ __import__ или __file__. Никогда не изобретайте такие имена; используйте их только как задокументированные.

Обратите внимание, что имена с двойными ведущими и завершающими символами подчеркивания по существу зарезервированы для самого Python: "Никогда не изобретайте такие имена, используйте их только как документально".

Ответ 2

Другие респонденты правильны в описании двойных ведущих и завершающих подчеркиваний в качестве соглашения об именах для "специальных" или "магических" методов.

Хотя вы можете напрямую вызвать эти методы (например, [10, 20].__len__()), наличие подчеркиваний - это намек на то, что эти методы предназначены для косвенного вызова (например, len([10, 20])). Большинство операторов python имеют связанный "магический" метод (например, a[x] - обычный способ вызова a.__getitem__(x)).

Ответ 4

На самом деле я использую имена методов, когда мне нужно различать имена родительского и дочернего классов. Я прочитал несколько кодов, которые использовали этот способ создания родительских классов. В качестве примера я могу предоставить этот код:

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))

...

и ребенок, у которого есть метод _worker

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)
    )

...

Ответ 5

Это соглашение используется для специальных переменных или методов (так называемый "магический метод"), таких как __init__, len. Эти методы предоставляют специальные синтаксические функции или делают специальные вещи.

Например, file указывает местоположение файла Python, eq выполняется, когда выполняется выражение == b.

Пользователь, конечно, может создать специальный специальный метод, это очень редкий случай, но часто может изменить некоторые встроенные специальные методы. (Например, вы должны инициализировать класс с помощью init, который будет выполняться сначала при создании экземпляра класса.)

   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