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

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

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

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

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

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

7 ответов


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


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

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

...

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


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

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


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

Е. Г., элемент позволяет + оператор для работы с пользовательскими классами. В противном случае вы получите какую-то неопределенную ошибку при попытке добавить.


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


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

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

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

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


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

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

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

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


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

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

  • 'и' ⇒ __и__
  • 'или' ⇒ __или__
  • 'не' ⇒ не
  • '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__
  • ' up ' ⇒ __pow__
  • ' им ' ⇒ imag
  • ' re' ⇒ настоящий
  • 'conj' ⇒ сопряженный

в Algol68 они были указаны как смелый имена, например,abs, но" под-под-abs " _ _ abs_ _ в python.

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