Почему Python использует два подчеркивания для определенных вещей? - PullRequest
50 голосов
/ 09 августа 2010

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

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

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

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

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

Ответы [ 7 ]

28 голосов
/ 09 августа 2010

Вот создатель Python , объясняющий это :

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

Я также использовал эту технику, чтобы позволить пользовательским классам переопределить поведение операторов Python.Как отмечалось ранее, Python реализован на C и использует таблицы указателей функций для реализации различных возможностей встроенных объектов (например, «get attribute», «add» и «call»).Чтобы эти возможности могли быть определены в пользовательских классах, я сопоставил различные указатели функций с именами специальных методов, такими как __getattr__, __add__ и __call__.Существует прямое соответствие между этими именами и таблицами указателей функций, которые необходимо определить при реализации новых объектов Python в C.

16 голосов
/ 09 августа 2010

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

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

7 голосов
/ 09 августа 2010

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

4 голосов
/ 09 августа 2010

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

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

3 голосов
/ 09 августа 2010

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

1 голос
/ 11 мая 2015

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

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

Многие разработчики неофициально называют их «тупыми методами», что означает «Двойной UNDERscore».

Некоторые люди используют термин «магические методы», но это несколько двусмысленно в смысле «более сложные методы», «специальные методы» (см. Ниже) или что-то среднее между ними.


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

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

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

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

0 голосов
/ 25 октября 2014

[Предположение] Python находился под влиянием Algol68 , Guido , возможно, использовал Algol68 в Университете Амстердама , где Algol68 имеет аналогичный« режим обрезки » называется «Обрезка цитаты».В Algol68 операторы, типы и ключевые слова могут появляться в другом шрифте (обычно ** полужирный ** или __ подчеркнутый __)в файлах исходного кода эта гарнитура достигается с помощью кавычек, например, '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 __
  • ' плюс '⇒ __add __
  • ' раз '⇒ __mul __
  • ' mod '⇒ __mod __
  • 'div' ⇒ __truediv __
  • 'over' ⇒ __div __
  • 'вверх' ⇒ __pow __
  • 'im' ⇒ imag
  • 're' ⇒ real
  • 'coe' ⇒ сопряженное

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

Мои 2 цента: ¢Так что иногда - как призрак - когда вы вырезаете и вставляете классы Python в вики, вы волшебным образом перевоплощаете ключевые слова Algol68 bold

...