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

Но вокруг класса, экземпляра — ядра объектно-ориентированного программирования, регулярных выражений (регулярных выражений), понимания списков, памяти, манипулирования многомерными массивами, разницы между объектно-ориентированным языком программирования и языком, управляемым событиями, и того, как они используются и т.

В частности, что это за def, self, ->, :, __init__, __main__, @ (декораторы) в классах? Это вызвало у меня головную боль, не говоря уже о том, что во всех колодах из школы только одна страница говорила о классе. Это похоже на это, но ничего больше.

А что такое объект? Я думал, мы говорим о классе и определении методов??? Как будто в школе вас учат 1+1=2, а в реальном мире вы ссоритесь.

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

Мне удалось понять содержание колоды, но когда дело доходит до просмотра примеров из реальной жизни, таких как Django-React-Boilerplate или Cookiecutter-django: Моих знаний в Python не хватило, и я ненавидел мое поверхностное понимание. Я думаю, что многие другие думали так же, и надеюсь, что эта статья может помочь.

self : почему он везде — в скобках или вне скобок и как его использовать

Я просмотрел документацию по python о том, почему selfиспользуется явно, и это определенно не похоже на человеческий язык. Это можно понять только после того, как вы на самом деле написали классы и создали атрибуты экземпляров и изучили поведение, играя с ним.

Во-первых, более очевидно, что вы используете метод или атрибут экземпляра вместо локальной переменной. Чтение self.x или self.meth() делает абсолютно ясным, что используется переменная или метод экземпляра, даже если вы не знаете определение класса наизусть. В C++ это можно определить по отсутствию объявления локальной переменной (при условии, что глобальные переменные редки или легко узнаваемы), но в Python нет объявлений локальных переменных, поэтому вам придется искать определение класса, чтобы быть конечно. Некоторые стандарты кодирования C++ и Java требуют, чтобы атрибуты экземпляра имели префикс m_, так что эта явность по-прежнему полезна и в этих языках.

Во-вторых, это означает, что нет необходимости в специальном синтаксисе, если вы хотите явно сослаться на метод или вызвать его из определенного класса. В C++, если вы хотите использовать метод из базового класса, который переопределяется в производном классе, вы должны использовать оператор :: — в Python вы можете написать baseclass.methodname(self, <argument list>). Это особенно полезно для методов __init__() и вообще в тех случаях, когда метод производного класса хочет расширить одноименный метод базового класса и, таким образом, должен каким-то образом вызывать метод базового класса.

Наконец, например, переменные, это решает синтаксическую проблему с присваиванием: поскольку локальные переменные в Python — это (по определению!) те переменные, которым присваивается значение в теле функции (и которые явно не объявлены глобальными), должны быть каким-то способом сообщить интерпретатору, что присваивание предназначено для присваивания переменной экземпляра, а не локальной переменной, и желательно, чтобы оно было синтаксическим (по соображениям эффективности). C++ делает это с помощью объявлений, но Python не имеет объявлений, и было бы жаль вводить их только для этой цели. Использование явного self.var прекрасно решает эту проблему. Точно так же для использования переменных экземпляра необходимость писать self.var означает, что ссылки на неполные имена внутри метода не должны искать каталоги экземпляра. Иными словами, локальные переменные и переменные экземпляра находятся в двух разных пространствах имен Python, и вам нужно указать Python, какое пространство имен использовать.

Если перевести это на обычный язык — зачем и когда использовать self:

  • Более быстрое понимание: Чтение something.something или something.something() (прочитайте его вслух, как резиновую утку, как something dot something) поможет вам понять, что это метод или атрибут экземпляра, определенный в каком-то class или каком-то def , не углубляясь в тот же файл или другие файлы. . (Атрибуты метода и экземпляра различаются. Метод – это то, что следует сразу после def, а атрибут экземпляра – это то, что у вас есть отступ, записанный в строках ниже определения.)
  • Ясность области и пространства имен переменной: в Python нет var, const или let, как в Javascript, чтобы различать, может ли переменная быть обновлена ​​и в какой области, ни, как в C, вы не можете объявить глобальную переменную в основной функции или локальная переменная в другом месте. Все неявно. (Ну, вы можете как бы объявить глобальную переменную в python, набрав global YOURVARIABLE.) Следовательно, вызов self.var указывает на то, что это локальная переменная внутри функции, и вы можете использовать isinstance(), чтобы проверить, к какому классу/методу принадлежит эта переменная.
  • Быстрое кодирование и интерпретация: после того, как вы определите метод в классе с помощью baseclass.method(self,argument1,..), вы сможете либо вызвать метод с помощью baseclass.method(object, argument1,…), либо object.method(argument1,…) после того, как вы object = baseclass(), что намного быстрее. Оба метода - одно и то же. В классе он действует как заполнитель, чтобы имитировать то, что вы можете делать, когда вы назначаете объект этому классу и вызываете его с помощью object.method. Интерпретатор может сначала обратиться к локальной области видимости, и переменная будет найдена быстрее. Когда вы вызываете переменную, последовательность поиска интерпретатора сначала будет искать локальную область видимости —> включающую область —> глобальную область видимости —> встроенную. Если вы не укажете self в качестве первого аргумента, когда у метода нет аргументов, вы вызовете TypeError при вызове метода с помощью object.method.

Почему одни пишут class ClassName(object)`:, а другие пишут class ClassName`:

В некоторых примерах GeekforGeeks, особенно один, объясняющий магические методы (все, что имеет двойное подчеркивание, также называемое методами dunder) (object) стоял за именем класса. class ClassName(object): использовался в Python 2.x, но в Python 3.x запись (object) избыточна, так как при использовании __init__ объект наследуется.

Если они пишут это таким образом, вероятно, они кодируют уже довольно давно.

Также включите еще несколько ссылок, если вы заинтересованы:

Почему классы Python наследуют объект
Класс старого и нового стиля
Разница между классами старого и нового стиля в Python — StackOverflow
Что делать (объект) дальше к имени класса в Python

«→» и «:»

Иногда вы сталкивались с очень загадочными и длинными функциями, подобными этой.

def StrongHuman(forearm:'circumference_of_forearm', abdomen:'number_of_pack_on_abdomen')-> 'Judging_a_strong_human':
    self.forearm = 0
    self.abdomen = 1

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

StrongHuman.__annotations__

Он вернет вам словарь аннотаций, связанный с этим методом. __annotations__ является частью встроенной функции во встроенной области.
Вывод:

{'forearm': 'circumference_of_forearm',  'abdomen': 'number_of_pack_on_abdomen',  'return': 'Judging_a_strong_human'}

Чтобы узнать больше об аннотациях функций и о том, как они используются, смотрите здесь. В ответе Raymond также подробно описаны варианты использования аннотаций функций.

Чтобы понять локальную область, глобальную область, встроенную область и пространства имен, я нашел это и это полезными.