Я довольно плохо знаком с фактическими языками программирования, и Python является моим первым. Я знаю, что мой путь вокруг Linux немного, достаточно получает работу на лето с ним (я нахожусь все еще в средней школе), и на задании, у меня есть много свободного времени, которое я использую для изучения Python.
Одна вещь получала меня все же. Что точно отличается в Python, когда у Вас есть выражения такой как
x.__add__(y) <==> x+y
x.__getattribute__('foo') <==> x.foo
Я знаю то, что методы делают и наполняют, и я получаю то, что они делают, но мой вопрос: Как удваивают те методы подчеркивания выше различного от их более просто выглядящих эквивалентов?
P.S., я не возражаю читаться лекции по программированию истории, на самом деле, я нахожу очень полезным знать :) Если это главным образом исторические аспекты Python, не стесняйтесь начинать околачиваться.
Well, power for the programmer is good, so there should be a way to customize behaviour. Like operator overloading (__add__
, __div__
, __ge__
, ... ), attribute access (__getattribute__
, __getattr__
(those two are differnt), __delattr__
, ...) etc. In many cases, like operators, the usual syntax maps 1:1 to the respective method. In other cases, there is a special procedure which at some point involves calling the respective method - for example, __getattr__
is only called if the object doesn't have the requested attribute and __getattribute__
is not implemented or raised AttributeError. And some of them are really advanced topics that get you deeeeep into the object system's guts and are rarely needed. So no need to learn them all, just consult the reference when you need/want to know. Speaking of reference, here it is.
Вот создатель Python объясняет это:
... вместо того, чтобы разрабатывать новый синтаксис для специальных видов методов класса (таких как инициализаторы и деструкторы), я решил, что эти особенности можно справиться, просто потребовав от пользователя реализовывать методы со специальными именами, такими как
__init__
,__del__
, и и так далее. Это соглашение об именовании было взято из языка C, где идентификаторы начинающиеся с символов подчеркивания, зарезервированы компилятором и часто имеют специальное значение (например, макросы, такие как.__FILE__
в препроцессоре языка Си).
...
Я также использовал эту технику, чтобы позволить пользовательским классам переопределять поведение операторов Python. Как уже отмечалось ранее отмечалось, Python реализован на языке C и использует таблицы указателей функций для реализации различных возможностей встроенных объектов (например, "получить атрибут", "добавить" и "вызвать"). Чтобы позволить этим возможностям быть определенными в классах, определяемых пользователем, я отобразил различные указатели функций в специальные именам методов, таких как
__getattr__
,__add__
, и__call__
. Существует прямое соответствие между этими именами и таблицами функций указателей, которые необходимо определить при
Когда вы запускаете метод с двумя символами подчеркивания (без конечных подчеркиваний), применяются правила изменения имени Python . Это способ имитации ключевого слова private
из других объектно-ориентированных языков, таких как C ++ и Java. (Даже в этом случае метод по-прежнему технически не является частным, как частные методы Java и C ++, но к нему «труднее добраться» извне экземпляра.)
Рассматриваются методы с двумя ведущими и двумя завершающими символами подчеркивания. чтобы быть «встроенными» методами, то есть они используются интерпретатором и обычно являются конкретной реализацией перегруженных операторов или других встроенных функций.
Они используются для указания того, что интерпретатор Python должен использовать их в определенных ситуациях.
Например, функция __add__
позволяет оператору +
работать для пользовательских классов. В противном случае при попытке добавить вы получите ошибку типа not defined.
С исторической точки зрения, начальные подчеркивания часто использовались как метод, указывающий программисту, что имена должны считаться внутренними по отношению к пакету / модулю / библиотеке, который их определяет. В языках, которые не обеспечивают хорошей поддержки частных пространств имен, использование подчеркивания является условием для имитации этого. В Python, когда вы определяете метод с именем '__foo__', программист по обслуживанию знает по имени, что происходит что-то особенное, чего не происходит с методом с именем 'foo'. Если бы Python решил использовать «add» в качестве внутреннего метода для перегрузки «+», то у вас никогда не было бы класса с методом «add», не вызывая большой путаницы. Подчеркивания служат признаком того, что произойдет какое-то волшебство.