Чем метод отличается от функции python?

Метод это функция, которая принадлежит к конкретному классу и не может быть использована отдельно от него. Например, методы строк ( count() , replace() , split() и др.) применяются только к объектам класса str (тип данных str это объекты класса str ), но не могут применяться к объектам других классов.
Функции же не привязаны к какому либо классу и могут использоваться без ограничений
Функции и методы в Python: передача функции в функцию. Декоратор
Эта статья посвящена теме декораторов в Python. Поговорим о том, что это такое, уделим особое внимание свойствам функций в Python, на базе которых реализована данная идея, а также рассмотрим декораторы, которые принимают аргументы и возвращают значение из функции.
Что надо знать о методах и функциях в Python?
Говоря о функциях в Python, нужно упомянуть два аспекта: 1) функция в Python — есть объект специального вида, который можно передавать в виде аргумента другим функциям; 2) внутри функций в Python вы можете создавать другие функции, а также вызывать их, возвращая результат посредством return.
Теперь давайте поговорим об этом подробнее.
Функция как объект в Python
В языке программирования Python часто практикуется передача одной функции в виде аргумента другой функции. Представьте, что есть список целых чисел, и вы желаете на его базе получить другой список с элементами, которые будут квадратами первого списка. Вот, как это можно реализовать в Python:
В нашем примере мы передали функции map в виде первого аргумента функцию sq. Последняя будет по очереди применяться ко всем элементам нашего списка a.
Кроме того, в Python функция является специальным объектом, имеющим метод __call__() . Представьте, что мы создали следующий класс:
Объект такого класса в Python мы сможем вызывать как функцию:
Функция внутри функции в Python
Функции в Python мы можем создавать, вызывать и возвращать из других функций. Кстати, на этом основана идея замыкания (closures) в Python.
Давайте создадим функцию, умножающую 2 числа:
В этой функции в Python реализованы два важных свойства: 1) внутри функции mul() мы создаём ещё одну функцию helper() ; 2) функция mul() возвращает нам функцию helper() в качестве результата работы.
Вызов этой функции в Python:
Особенность заключается в том, что мы можем создавать на базе функции mul() собственные кастомизированные функции. Давайте создадим функцию в Python, умножающую на 3:
В результате была построена функция three_mul() , умножающая на 3 любое переданное ей число.
Декоратор функции в Python
Конструктивно речь идёт о некоторой функции, в качестве аргумента которого выступает другая функция. Декоратор в Python добавляет дополнительный функционал к функции, не меняя её содержимое.
Создание
Представьте, что мы имеем пару простых функций в Python:
При этом мы желаем их дополнить таким образом, чтобы перед вызовом основного кода нашей функции печаталась строчка “Start function”, а в конце – строка “Stop function”.
Реализовать поставленную задачу можно несколькими методами. Во-первых, мы можем добавить необходимые строки в конец и начало каждой функции. Но вряд ли это удобно, ведь если мы пожелаем их убрать, придётся модифицировать тело функции.
Теперь поговорим о втором пути. Для начала создадим функцию:
Теперь нужно обернуть функции в оболочку:
Обратите внимание, что функции first_test и second_test не поменялись.
Наши функции second_test_wrapped и first_test_wrapped обладают функционалом, который нам и нужен.
Теперь, если надо, чтобы так работали функции с именами first_test и second_test, делаем следующее:
Выполненные нами действия и являются реализацией идеи декоратора.
Правда, вместо строк:
мы можем написать иначе:
В нашем случае @simple_decore – это не что иное, как декоратор функции.
Передаём аргументы в функцию с помощью декоратора
Бывает, что функция требует наличие аргумента, поэтому мы можем передать его через декоратор. Давайте создадим декоратор, принимающий аргумент и выводящий информацию о декорируемой нами функции и её аргументе.
Чтобы продемонстрировать работу, создадим функцию, выводящую квадратный корень переданного ей числа, а в качестве декоратора, укажем созданный param_transfer:
Теперь давайте выполним данную функцию с аргументом 4:
Декораторы для методов класса в Python
С декоратором можно объявлять и методы классов. Давайте выполним модификацию декоратора param_transfer:
Теперь приступим к созданию класса для представления 2-мерного вектора (математического). В классе определим метод norm() , выводящий модуль вектора.
Что же, осталось продемонстрировать работу нашего метода:
Возвращаем результат работы функции через декоратор
Зачастую создаваемые функции выполняют возвращение какого-либо значения. Чтобы это стало возможным осуществить через декоратор, нужно специальным образом построить нашу внутреннюю функцию:
Возможно применение этого декоратора и для оборачивания функций, принимающих различные аргументы и возвращающие значение:
13. Методы¶
Не так просто дать определение, что же такое объектно-ориентированное программирование, но мы уже видели некоторые его свойства:
- Программы строятся из определений объектов и определений функций, и большинство вычислений выражается в терминах операций над объектами.
- Каждое определение объекта соответствует некоторому объекту или понятию реального мира, а функции, работающие с объектом, соответствуют тому, как взаимодействуют реальные объекты.
Например, класс Time , определенный в предыдущей главе, соответствует тому, как люди привыкли записывать время. А определенные нами функции соответствуют действиям, которые люди выполняют над временем. Подобным же образом, классы Point и Rectangle соответствуют математическим понятиям точки и прямоугольника.
До сих пор мы не пользовались средствами, которые Python предоставляет для объектно-ориентированного программирования. Строго говоря, эти средства не являются необходимыми для создания программ. По большей части, они предоставляют альтернативный синтаксис для тех вещей, которые мы уже делали. Однако, часто этот синтаксис оказывается более кратким и выразительным.
Например, в программе Time нет очевидной связи между определением класса и следующими за ним определениями функций. Если присмотреться, то оказывается, что каждая из функций принимает в качестве параметра, по крайней мере, один объект Time .
Это наблюдение мотивирует нас перейти к методам. Мы уже встречали некоторые методы, например, keys и values , которые вызываются на словарных объектах. Каждый метод связан с классом и предназначен для использования с объектами этого класса.
Методы похожи на функции, но есть два отличия:
- Методы определяются внутри определения класса, чтобы сделать отношения между классом и методом явными.
- Синтаксис для вызова метода отличается от синтаксиса для вызова функции.
В следующих разделах мы превратим функции из предыдущей главы в методы. Это преобразование почти механическое. Мы сделаем это, выполнив определенную последовательность шагов.
13.2. Метод increment ¶
Для начала давайте превратим в метод функцию increment .
Для этого достаточно поместить определение функции внутрь определения класса. Хорошим тоном будет также переименование параметра time в self (хоть делать это и не обязательно). Как вы, должно быть, помните, в сообществе программистов Python существует соглашение, согласно которому первому параметру метода дают имя self (англ.: сам).
Обратите внимание на сдвиг кода метода относительно заголовка класса:
Преобразование чисто механическое — мы переместили определение метода в определение класса, и изменили имя первого параметра.
Теперь можно вызвать increment как метод, используя точечную нотацию:
Объект, на котором вызывается метод, присваивается первому параметру метода. Таким образом, в данном случае my_time присваивается параметру self . Второй параметр, seconds , получает значение 600 .
В процедурном программировании предполагается, что функции выполняют необходимые действия. Синтаксис для вызова функции , increment(my_time, 600) , говорит: Эй, increment ! Вот тебе объект Time и 600 секунд, сделай с ними все необходимое.
Синтаксис объектно-ориентированном программировании предполагает, что необходимые действия выполняет объект. Вызов, подобный my_time.increment(600) говорит: Эй, my_time ! Пожалуйста, увеличь себя на 600 секунд!
Является ли полезным такое изменение взгляда на вещи? Дело в том, что иногда, передавая ответственность от функций объектам, мы можем писать более гибкий код. Также становится проще поддерживать и повторно использовать такой код.
13.3. Более сложный пример¶
Функция after немного более сложная, поскольку она имеет дело с двумя объектами Time . Первый из параметров переименуем в self , второй оставим без изменений:
Мы вызываем этот метод на одном объекте Time , и передаем второй объект Time в качестве аргумента:
Программа состоит из предложений на почти естественном английском языке: Если время готовности (done_time) позднее, чем текущее время (current_time), то.
13.4. Инициализирующий метод¶
Как мы уже знаем, инициализирующий метод — это специальный метод, который вызывается при создании объекта. Этот метод имеет имя __init__ (два символа подчеркивания, init , и еще два символа подчеркивания). Инициализирующий метод класса Time выглядит так:
Заметьте, что между атрибутом self.hours и параметром hours не возникает конфликта имен. Точечная нотация устраняет конфликт.
Метод, вызываемый при создании объекта и инициализирующий состояние объекта, также называют конструктором. В Python метод __init__ является конструктором.
Когда мы создаем объект Time , указанные нами аргументы передаются конструктору:
Поскольку параметры метода __init__ имеют значения по умолчанию, мы можем и не передавать аргументы при создании объекта:
Или передать только первый аргумент:
Или только первые два аргумента:
Мы также можем передать часть аргументов, явно поименовав их:
13.5. Метод __str__ ¶
Метод __str__ имеет специальное назначение в Python, он возвращает строковое представление объекта. Определим метод __str__ для класса Time , позаимствовав решение из функции print_time из предыдущей главы:
Если класс предоставляет метод с именем __str__ , то тем самым переопределяет поведение встроенной функции Python str .
При выводе объекта Time с помощью print неявно вызывается __str__ на этом объекте. Поэтому добавление метода __str__ также меняет поведение print :
Как видите, добавление метода __str__ к классу Time сделало ненужным написанную ранее функцию print_time .
Когда мы пишем новый класс, мы почти всегда начинаем с написания метода __init__ , который облегчает создание объектов, и метода __str__ , который часто полезен для отладки.
13.6. Снова Points ¶
Теперь, для закрепления изученного материала, давайте перепишем класс Point в стиле ООП:
Инициализирующий метод принимает x и y как опциональные параметры, значение по умолчанию для каждого из них 0.
Метод __str__ возвращает строковое представление объекта Point :
13.7. Перегрузка операторов¶
Некоторые языки программирования позволяют изменять определения встроенных операторов для использования этих операторов с типами, определенными пользователем. Это свойство называется перегрузкой операторов.
Например, для перегрузки оператора + , класс должен предоставить метод __add__ :
Как обычно, первый параметр метода представляет объект, на котором вызывается метод. Второй параметр удачно назван other (англ.: другой) чтобы противопоставить его первому, self . Для того, чтобы сложить два объекта Point , мы создаем и возвращаем новый объект Point , содержащий сумму координат x и сумму координат y двух объектов.
Теперь, когда мы применяем оператор + к объектам Point , Python вызывает метод __add__ :
Выражение p1 + p2 равнозначно выражению p1.__add__(p2) , только более изящно.
В качестве упражнения вам будет предложено самостоятельно написать метод __sub__(self, other) , который перегрузит оператор вычитания.
Перегрузить оператор умножения можно, определив метод __mul__ , или __rmul__ , или оба эти метода. Если левый операнд оператора * является объектом Point , то Python вызовет метод __mul__ , который ожидает, что второй операнд также является объектом Point . Этот метод рассчитает произведение точек согласно известной из математики формуле (сумма квадратов катетов равна квадрату гипотенузы):
Если левый операнд оператора * является примитивным числовым типом, а правый операнд — объект Point , то Python вызовет метод __rmul__ , который выполнит умножение объекта Point на число:
Результатом будет новый объект Point , чьи координаты кратны первоначальным координатам. Если other окажется типом, который нельзя умножить на число с плавающей точкой, то __rmul__ сгенерирует ошибку.
Следующий пример демонстрирует оба вида умножения:
А что случится, если мы попробуем вычислить p2 * 2 ? Так как первый аргумент является объектом Point , то Python вызовет __mul__ и передаст 2 в качестве второго аргумента. Внутри метода, __mul__ попытается получить атрибут x объекта other , что закончится неудачей, поскольку целое число не имеет атрибутов:
13.8. Полиморфизм¶
Большинство написанных нами методов работают только с определенными типами данных. Когда создается новый класс, то пишутся методы, которые работают с объектами этого класса.
Но есть некоторые операции, которые хотелось бы уметь выполнять с разными типами данных, например, арифметические операции из предыдущего раздела. Если разные типы поддерживают одни и те же операции, значит, можно писать функции, работающие с любым из этих типов.
Например, операция multadd (обычная в линейной алгебре) имеет три параметра; первые два перемножаются, и к полученному произведению прибавляется третий. Можем записать это на языке Python таким образом:
Этот метод будет работать с любыми значениями x и y , которые можно перемножить, и с любым значением z , которое можно прибавить к полученному произведению.
Можно вызвать этот метод с числовыми значениями:
Или с объектами Point :
В первом случае, Point умножается на число и складывается с другим Point . Во втором случае, произведение двух Point дает числовое значение, и третий аргумент также является числом.
Функции, подобные этой, которые могут принимать аргументы различных типов, называются полиморфными.
В качестве еще одного примера, рассмотрим метод front_and_back , который печатает список дважды, сначала — в прямом, а затем и в обратном порядке:
Поскольку метод reverse модифицирующий, мы делаем копию списка, прежде чем расставить его элементы в обратном порядке. Таким образом, метод reverse не изменяет список, который он получает в качестве параметра.
Вот пример использования метода front_and_back со списком:
Поскольку мы предназначили эту функцию для работы со списками, неудивительно, что она работает, как ожидалось. Было бы удивительно, если бы мы смогли применить эту функцию к объекту Point .
Для того, чтобы определить, может ли функция быть применена к новому типу, мы воспользуемся основным правилом полиморфизма: Если все операции внутри функции могут быть применены к данному типу, то вся функция может быть применена к данному типу.
Операции внутри функции включают copy , reverse и print .
copy работает с любым объектом. Мы уже написали метод __str__ для Point . Нам остается написать метод reverse для класса Point :
Теперь можно передать объект Point функции front_and_back :
Замечательное свойство языка Python — это непреднамеренный полиморфизм, когда вы обнаруживаете, что написанная вами функция может работать с типами, для которых вы ее не предназначали.
13.9. Глоссарий¶
13.10. Упражнения¶
Переделайте функцию convert_to_seconds в метод класса Time :
Добавьте в класс Point метод __sub__(self, other) , который перегрузит оператор вычитания, и попробуйте с ним поработать.
Перепишите класс Rectangle в объектно-ориентированном стиле, определив методы __init__ и __str__ .
Добавьте в класс Rectangle методы move_rect и grow_rect , созданные на основе одноименных функций из предыдущей главы.
Определите класс Pet (англ.: любимое животное) с атрибутами имя и возраст, инициализируемыми в методе __init__ значениями параметров метода. Метод __str__ должен возвращать строку с именем и возрастом животного. Поэкспериментируйте, создавая объекты класса Pet и выводя их на печать.
Классы, объекты и методы в Python
Наследование в Python основано на сходных идеях, используемых в других объектно-ориентированных языках, таких как Java, C ++ и т. Д. Новый класс может быть получен из существующего класса следующим образом.
BaseClass является уже существующий (родительский) класс, а DerivedClass это новый (дочерний) класс , который наследует (или подклассов) атрибуты BaseClass .Примечание: По состоянию на Python 2.2, все классы неявно наследуются от object класса , который является базовым классом для всех встроенных типов.
Определим родительский Rectangle класс в примере ниже, который неявно наследует от object :
Rectangle класс может быть использован в качестве базового класса для определения Square класса, как квадрат является частным случаем прямоугольника.
Square класс автоматически наследует все атрибуты Rectangle класса, а также класса объектов. super() используется для вызова __init__() метод Rectangle класса, по существу , вызовом любой перекрытый метод базового класса. Примечание: в Python 3, super() не требует аргументов.
Объекты производного класса могут получать доступ и изменять атрибуты своих базовых классов:
Встроенные функции, которые работают с наследованием
issubclass(DerivedClass, BaseClass) : возвращает True , если DerivedClass является подклассом BaseClass
isinstance(s, Class) : возвращает True , если ы является экземпляром Class или любой из производных классов Class
Переменные класса и экземпляра
Переменные экземпляра уникальны для каждого экземпляра, а переменные класса являются общими для всех экземпляров.
Переменные класса могут быть доступны в экземплярах этого класса, но присвоение атрибуту класса создаст переменную экземпляра, которая затеняет переменную класса
Обратите внимание , что мутирует переменный класс случаев может привести к неожиданным последствиям.
Связанные, несвязанные и статические методы
Идея связанных и несвязанных методов был удален в Python 3.В Python 3 при объявлении метода в классе, вы используете def ключевое слово, тем самым создавая объект функции. Это обычная функция, и окружающий класс работает как пространство имен. В следующем примере мы указываем метод f в пределах класса A , и это становится функцией A.f :
В Python 2 поведение отличается: объекты функций внутри класса были неявно заменены объектами типа instancemethod , которые назывались несвязанных метода , потому что они не были связаны с каким — либо конкретным экземпляром класса. Удалось получить доступ к основной функции с помощью .__func__ свойства.
Последнее поведение подтверждается проверкой — методы распознаются как функции в Python 3, в то время как различие поддерживается в Python 2.
В обеих версиях функции Python / метод A.f может быть вызван непосредственно, при условии , что вы передаете экземпляр класса A в качестве первого аргумента.
Теперь предположим , что a является экземпляром класса A , что a.f тогда? Ну, интуитивно это должно быть тем же самым методом f класса A , только он должен каким — то образом «знает» , что он был применен к объекту a — в Python это называется метод , связанный с. a
В суровых буднях детали следующим образом : запись af вызывает магический __getattribute__ метод , который сначала проверяет , является ли имеет атрибут с именем a a f (не), а затем проверяет , класс A , содержит ли это метод с таким именем (он делает), и создает новый объект m типа method , который имеет ссылку на исходные Af в m.__func__ и ссылку на объект a в m.__self__ .Когда этот объект вызывается как функция, он просто выполняет следующие действия : m(. ) => m.__func__(m.__self__, . ) .Таким образом , этот объект называется связанный метод потому , что при вызове он знает , чтобы поставить объект был привязан к качестве первого аргумента. (Эти вещи работают одинаково в Python 2 и 3).
Наконец, Python имеет методы класса и статические методы — специальные виды методов. Методы класса работают точно так же , как и обычные методы, за исключением того, что при вызове на объекте они связываются с классом объекта , а не к объекту. Таким образом , m.__self__ = type(a) .При вызове такого связанного метода, он проходит класс в качестве первого аргумента. a Статические методы еще проще: они вообще ничего не связывают и просто возвращают базовую функцию без каких-либо преобразований.
Обратите внимание, что методы класса привязаны к классу даже при обращении к экземпляру:
Стоит отметить , что на самом низком уровне, функции, методы, staticmethods и т.д., на самом деле дескрипторы , которые вызывают __get__ , __set и , возможно , `del__` специальные методы. Для более подробной информации о методах классов и статических методах:
Классы нового стиля против старого стиля
Новые классы в стиле были введены в Python 2.2 для объединения классов и типов. Они наследуют от верхнего уровня object типа. Класс нового типа является определенный пользователем тип, и очень похож на встроенных типов.
Классы старого типа не наследуют от object .Экземпляры старого типа всегда реализуется с помощью встроенного в instance типа.
В Python 3 классы старого стиля были удалены.
Новые классы стиля в Python 3 неявно наследуют от object , поэтому нет необходимости указывать MyClass(object) больше.
Значения по умолчанию для переменных экземпляра
Если переменная содержит значение неизменяемого типа (например, строку), тогда можно назначить значение по умолчанию, подобное этому.
Нужно быть осторожным при инициализации изменяемых объектов, таких как списки в конструкторе. Рассмотрим следующий пример:
Такое поведение вызвано тем, что в Python параметры по умолчанию связаны при выполнении функции, а не при ее объявлении. Чтобы получить переменную экземпляра по умолчанию, которая не разделяется между экземплярами, следует использовать такую конструкцию:
Смотрите также Мутабельные Аргументы по умолчанию и «изумление» Наималейшего и изменяемый по умолчанию аргумент .
Множественное наследование
Python использует C3 линеаризацию алгоритм для определения порядка , в котором для решения атрибутов класса, включая методы. Это известно как Порядок разрешения методов (MRO).
Вот простой пример:
Теперь, если мы создаем экземпляр FooBar , если мы ищем атрибут foo , мы видим, что атрибут Foo находится первым
Можно просто сказать, что алгоритм Python MRO
- Глубина первого (например , FooBar затем Foo ) , если
- общий родительский ( object ) блокируется ребенком ( Bar ) и
- круговые отношения не допускаются.
То есть, например, Bar не может наследовать от FooBar, а FooBar наследует от Bar.
Другая характерная особенность в наследстве является super .Супер может получить функции родительских классов.
Множественное наследование с помощью метода init класса, когда у каждого класса есть собственный метод init, тогда мы пытаемся получить множественное наследование, тогда вызывается только метод init класса, который наследуется первым.
для примера ниже Foo метод инициализировать класс вызывался класс Bar не INIT вызывался
Но это не значит, что Bar класс не наследуется. Instance конечного класса FooBar также экземпляр класса Bar и класса Foo.
Дескрипторы
Дескрипторы являются объектами , которые являются ( как правило) атрибутами классов и которые имеют какие — либо из __get__ , __set__ или __delete__ специальных методов.
Дескрипторы данных имеют какой — либо из __set__ или __delete__
Они могут контролировать пунктирный поиск на экземпляре, и используются для реализации функций, staticmethod , classmethod и property .
Методы класса: альтернативные инициализаторы
Методы класса представляют альтернативные способы создания экземпляров классов. Чтобы проиллюстрировать это, давайте посмотрим на пример.
Давайте предположим , что мы имеем относительно простой Person класс:
Возможно, было бы удобно иметь возможность создавать экземпляры этого класса, указав полное имя вместо имени и фамилии отдельно. Один из способов сделать это будет иметь last_name быть необязательным параметром, и при условии , что , если не дано, мы прошли полное имя:
Однако с этим битом кода связаны две основные проблемы:
- Параметры first_name и last_name теперь вводит в заблуждение, так как вы можете ввести полное имя для first_name .
- Кроме того, если есть больше падежей и / или больше параметров, которые обладают такой гибкостью, ветвление if / elif / else может быстро раздражать.
Введите методы класса. Вместо того , чтобы иметь один инициализатор, мы создадим отдельный инициализатору, называемый from_full_name , и украсить его с (встроенный) classmethod декоратора.
Обратите внимание на cls вместо self в качестве первого аргумента from_full_name .Методы класса применяется к общему классу, не является экземпляром данного класса (что self обычно обозначает). Так что , если cls является наш Person класс, то возвращается значение из from_full_name метода класса является Person(first_name, last_name, age) , который использует Person «s __init__ создать экземпляр Person класса.
В частности, если мы должны были сделать подкласс Employee из Person , то from_full_name будет работать в Employee классе , а также.
Для того, чтобы показать , что это работает , как и ожидалось, давайте создавать экземпляры Person в более чем одним способом , без разветвлений в __init__ :
- https://docs.python.org/2/library/functions.html#classmethod
- https://docs.python.org/3.5/library/functions.html#classmethod
Композиция классов
Композиция классов позволяет явные отношения между объектами. В этом примере люди живут в городах, которые принадлежат странам. Композиция позволяет людям получить доступ ко всем людям, живущим в их стране:
Monkey Patching (исправление обезьяны)
В этом случае «исправление обезьяны» означает добавление новой переменной или метода в класс после его определения. Например, скажем , мы определили класс A , как
Но теперь мы хотим добавить еще одну функцию позже в коде. Предположим, что эта функция выглядит следующим образом.
Но как же мы добавим это как метод в A ? Это просто мы просто по существу поместить эту функцию в с помощью оператора присваивания. A
Почему это работает? Потому что функции — это объекты, как и любой другой объект, а методы — это функции, принадлежащие классу.
Функция get_num должна быть доступна для всех существующих (уже создан) , а также к новым экземплярам A
Эти дополнения доступны для всех экземпляров этого класса (или его подклассов) автоматически. Например:
Обратите внимание, что, в отличие от некоторых других языков, этот метод не работает для определенных встроенных типов и не считается хорошим стилем.
Список всех членов класса
dir() функция может быть использована для получения списка членов класса, например:
Обычно ищут только «немагических» участников. Это можно сделать с помощью простого понимания , в котором перечислены члены, имена которых не начиная с __ :
Предостережения:
Классы можно определить __dir__() метод. Если этот метод существует вызова dir() будем называть __dir__() , в противном случае Python будет пытаться создать список членов класса. Это означает, что функция dir может иметь неожиданные результаты. Две цитаты важности из официальной документации питона :
Если объект не содержит каталог ( как правило ), функция пытается все возможное , чтобы собрать информацию из атрибута Dict объекта, если он определен, и от его типа объекта. Полученный список не обязательно является полным, и может быть неточным , если объект имеет собственный GetAttr ().
Примечание: Поскольку реж () поставляется в первую очередь для удобства использования в интерактивной командной строке, он пытается поставить интересный набор имен больше , чем он пытается поставить строго или последовательно определенный набор имен, и его детальное поведение может измениться по релизы. Например, атрибуты метакласса отсутствуют в списке результатов, когда аргумент является классом.
Введение в классы
Класс, функционирующий как шаблон, который определяет основные характеристики конкретного объекта. Вот пример:
Есть несколько вещей, на которые стоит обратить внимание при рассмотрении приведенного выше примера.
Теперь давайте сделаем несколько экземпляров нашего Person класса!
В настоящее время мы имеем три Person объектов, kelly , joseph и john_doe .
Мы можем получить доступ к атрибутам класса из каждого экземпляра с помощью оператора точки . Еще раз обратите внимание на разницу между атрибутами класса и экземпляра:
Мы можем выполнить методы класса с использованием того же оператора точки . :
Cвойства
Классы Python поддерживают свойства, которые выглядят как обычный переменный объект, но с возможностью прикрепления пользовательского поведения и документации.
Объекта , класса MyClass , будет иметь имеют свойство .string , однако его поведение теперь жестко контролируется:
Помимо полезного синтаксиса, описанного выше, синтаксис свойства позволяет проверять или добавлять другие дополнения к этим атрибутам. Это может быть особенно полезно с общедоступными API-интерфейсами, где пользователю должен быть предоставлен определенный уровень помощи.
Другое распространенное использование свойств — это предоставление классу возможности представлять «виртуальные атрибуты» — атрибуты, которые на самом деле не хранятся, но вычисляются только по запросу.
Синглтон класс
Синглтон — это шаблон, который ограничивает создание экземпляра класса одним экземпляром / объектом. Для получения дополнительной информации о питоных одноэлементных шаблонах проектирования, см здесь .
Другой способ — украсить свой класс. Следуя пример из этого ответа создать класс Singleton: