Почему python использует два символа подчеркивания для определенных вещей?

Я новичок в реальных языках программирования, а Python - мой первый. Я немного разбираюсь в Linux, достаточно, чтобы получить летнюю работу (я все еще в старшей школе), и на работе у меня много свободного времени, которое я использую для изучения Python.

Одна вещь меня достала. Что именно отличается в Python, когда у вас есть такие выражения, как

x.__add__(y) <==> x+y
x.__getattribute__('foo') <==> x.foo

Я знаю, какие методы делают и что делают, и я получаю то, что они делают, но мой вопрос: как эти двойные методы подчеркивания отличаются от их более простых эквивалентов?

P.S., я не против читать лекции по истории программирования, на самом деле, мне очень полезно знать:) Если это в основном исторические аспекты Python, не стесняйтесь начинать бессвязно.

Ответ 1

Ну, сила для программиста хорошая, поэтому должен быть способ настроить поведение. Подобно перегрузке оператора (__add__, __div__, __ge__,...), доступ к атрибутам (__getattribute__, __getattr__ (эти два отличаются), __delattr__,...) и т.д. Во многих например, операторы, обычные синтаксические карты 1:1 для соответствующего метода. В других случаях существует специальная процедура, которая в какой-то момент включает вызов соответствующего метода - например, __getattr__ вызывается только в том случае, если у объекта нет запрошенного атрибута, а __getattribute__ не реализован или не поднят AttributeError. И некоторые из них - это действительно продвинутые темы, которые помогут вам разобраться в кистях объектной системы и редко нужны. Поэтому нет необходимости изучать их все, просто ознакомьтесь со ссылкой, когда вам нужно/нужно знать. Говоря о ссылке, здесь.

Ответ 2

Вот создатель Python объясняя это:

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

...

Я также использовал эту технику, чтобы пользовательские классы для переопределения поведения операторов Python. Как раньше отметил, что Python реализован на C и использует таблицы указателей функций для реализовать различные возможности встроенные объекты (например, "get атрибут", "добавить" и "вызвать" ). разрешить эти возможности в пользовательских классах я сопоставил различные указатели функций на специальные имена методов, такие как __getattr__, __add__ и __call__. Eсть прямое соответствие между этими имена и таблицы функций указатели нужно определить, когда реализация новых объектов Python в C.

Ответ 3

Когда вы начинаете метод с двумя символами подчеркивания (и без подчеркивания подчеркивания), применяются правила Python name mangling. Это способ свободно имитировать ключевое слово private из других языков OO, таких как С++ и Java. (Тем не менее, метод по-прежнему технически не является приватным в том смысле, что методы Java и С++ являются частными, но "сложнее получить" из-за пределов экземпляра.)

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

Ответ 4

Они используются, чтобы указать, что интерпретатор Python должен использовать их в определенных ситуациях.

Например, функция __add__ позволяет оператору + работать для пользовательских классов. В противном случае при попытке добавить вы получите некоторую неопределенную ошибку.

Ответ 5

С исторической точки зрения ведущие подчеркивания часто использовались в качестве метода для указания программисту, что имена должны считаться внутренними для пакета/модуля/библиотеки, которые их определяют. В языках, которые не обеспечивают хорошую поддержку частных пространств имен, использование подчеркивания - это соглашение, чтобы подражать этому. В Python, когда вы определяете метод с именем "__foo__", программист по обслуживанию знает от имени, что происходит что-то особенное, которое не происходит с методом с именем "foo". Если бы Python выбрал "добавление" в качестве внутреннего метода для перегрузки "+", то у вас никогда не было бы класса с методом "добавить", не вызывая большого путаницы. Подчеркивания служат признаком того, что произойдет какая-то магия.

Ответ 6

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

На самом деле официального названия нет.

Многие разработчики неофициально называют их "методами dunder", для "Double UNDERscore".

Некоторые люди используют термин "магические методы", но несколько неоднозначный между методами определения смысла, специальными методами (см. ниже) или чем-то где-то между ними.


Существует официальный термин "специальные атрибуты", который частично перекрывается, но не полностью с использованием методов dunder. Глава Модель данных в ссылке никогда не объясняет, каков особый атрибут, но основная идея состоит в том, что это по крайней мере одно из следующего:

  • Атрибут, предоставляемый самим интерпретатором или встроенным кодом, например __name__ для функции.
  • Атрибут, который часть протокола реализована самим интерпретатором, например __add__ для оператора +, или __getitem__ для индексирования и нарезки.
  • Атрибут, который интерпретатору разрешено специально искать, игнорируя экземпляр и переходя к классу, например __add__.

Большинство специальных атрибутов - это методы, но не все (например, __name__ нет). И большинство используют соглашение "dunder", но не все (например, метод next для итераторов в Python 2.x).

Между тем, большинство методов dunder - это специальные атрибуты, но не все - в частности, не так уж редко, когда stdlib или внешние библиотеки хотят определять свои собственные протоколы, которые работают одинаково, например pickle.

Ответ 7

[Спекуляция] На Python повлияло Algol68, Guido возможно, использовалось Algol68 в Амстердамском университете, где Algol68 имеет аналогичный " режим стропинга", называемый "Копирование штрихов". В Algol68 операторы, типы и ключевые слова могут отображаться в другом шрифте (обычно ** жирным шрифтом ** или __underlined__), в файлах исходного кода этот шрифт достигается с помощью кавычек, например 'abs' (цитирование похоже на цитирование в wikitext ')

Algol68 ⇒ Python (Операторы, сопоставленные с функциями-членами)

  • 'и' ⇒ __and __
  • 'или' ⇒ __or __
  • 'not' ⇒ not
  • 'entier' ⇒ __trunc __
  • 'shl' ⇒ __lshift __
  • 'shr' ⇒ __rshift __
  • 'upb' ⇒ __sizeof __
  • 'long' ⇒ __long __
  • 'int' ⇒ __int __
  • 'real' ⇒ __float __
  • 'format' ⇒ __format __
  • 'repr' ⇒ __repr __
  • 'abs' ⇒ __abs __
  • 'минус' ⇒ __neg __
  • 'минус' ⇒ __sub __
  • 'plus' ⇒ __add __
  • 'times' ⇒ __mul __
  • 'mod' ⇒ __mod __
  • 'div' ⇒ __truediv __
  • 'over' ⇒ __div __
  • 'вверх' ⇒ __pow __
  • 'im' ⇒ imag
  • 're' ⇒ real
  • 'conj' ⇒ сопряженный

В Algol68 они назывались жирным именем, например. abs, но "under-under-abs" __abs__ в python.

Мои 2 цента: ¢ Поэтому иногда - как призрак - когда вы вырезаете и вставляете классы python в вики, вы волшебным образом перевоплотите Algol68 жирные ключевые слова. ¢