Как передать список в класс питон
Перейти к содержимому

Как передать список в класс питон

  • автор:

Объектно-ориентированное программирование

Python имеет множество встроенных типов, например, int, str и так далее, которые мы можем использовать в программе. Но также Python позволяет определять собственные типы с помощью классов . Класс представляет некоторую сущность. Конкретным воплощением класса является объект.

Можно еще провести следующую аналогию. У нас у всех есть некоторое представление о человеке, у которого есть имя, возраст, какие-то другие характеристики. Человек может выполнять некоторые действия — ходить, бегать, думать и т.д. То есть это представление, которое включает набор характеристик и действий, можно назвать классом. Конкретное воплощение этого шаблона может отличаться, например, одни люди имеют одно имя, другие — другое имя. И реально существующий человек будет представлять объект этого класса.

В языке Python класс определяется с помощью ключевого слова class :

class название_класса: атрибуты_класса методы_класса

Внутри класса определяются его атрибуты, которые хранят различные характеристики класса, и методы — функции класса.

Создадим простейший класс:

class Person: pass

В данном случае определен класс Person, который условно представляет человека. В данном случае в классе не определяется никаких методов или атрибутов. Однако поскольку в нем должно быть что-то определено, то в качестве заменителя функционала класса применяется оператор pass . Этот оператор применяется, когда синтаксически необходимо определить некоторый код, однако исходя из задачи код нам не нужен, и вместо конкретного кода вставляем оператор pass.

После создания класса можно определить объекты этого класса. Например:

class Person: pass tom = Person() # определение объекта tom bob = Person() # определение объекта bob

После определения класса Person создаются два объекта класса Person — tom и bob. Для создания объекта применяется специальная функция — конструктор , которая называется по имени класса и которая возвращает объект класса. То есть в данном случае вызов Person() представляет вызов конструктора. Каждый класс по умолчанию имеет конструктор без параметров:

tom = Person() # Person() - вызов конструктора, который возвращает объект класса Person

Конструкторы

Итак, для создания объекта класса используется конструктор. Так, выше когда мы создавали объекты класса Person, мы использовали конструктор по умолчанию, который не принимает параметров и который неявно имеют все классы. Однако мы можем явным образом определить в классах конструктор с помощью специального метода, который называется __init__() (по два прочерка с каждой стороны). К примеру, изменим класс Person, добавив в него конструктор:

class Person: # конструктор def __init__(self): print("Создание объекта Person") tom = Person() # Создание объекта Person

Итак, здесь в коде класса Person определен конструктор — функция __init__ . Конструктор должен принимать как минимум один параметр ссылку на текущий объект — self . Обычно конструкторы применяются для определения действий, которые должны производиться при создании объекта.

Теперь при создании объекта:

tom = Person()

выполняется вызов конструктора __init__() из класса Person, который выведет на консоль строку «Создание объекта Person».

Стоит отметить, что конструктор фактически представляет обычную функцию, только для вызовы конструктора используется не __init__ , а название класса. Кроме того, при вызове конструктора параметру self явным образом не передается никакого значения. При выполнении программы Python динамически будет определять self .

Атрибуты объекта

Атрибуты хранят состояние объекта. Для определения и установки атрибутов внутри класса можно применять слово self . Например, определим следующий класс Person:

class Person: def __init__(self, name, age): self.name = name # имя человека self.age = age # возраст человека tom = Person("Tom", 22) # обращение к атрибутам # получение значений print(tom.name) # Tom print(tom.age) # 22 # изменение значения tom.age = 37 print(tom.age) # 37

Теперь конструктор класса Person принимает еще два параметра — name и age. Через эти параметры в конструктор будут передаваться имя и возраст создаваемого человека.

Внутри конструктора устанавливаются два атрибута — name и age (условно имя и возраст человека):

def __init__(self, name, age): self.name = name self.age = age

Атрибуту self.name присваивается значение переменной name. Атрибут age получает значение параметра age. Название атрибутов не обязательно должно соответствовать названиям параметров.

Если мы определили в классе конструктор __init__ с параметрами (кроме self), то при вызове конструктора этим параметрам надо передать значения:

tom = Person("Tom", 22)

То есть в данном случае параметру name передается строка «Tom», а параметру age — число 22.

Далее по имени объекта мы можем обращаться к атрибутам объекта — получать и изменять их значения:

print(tom.name) # получение значения атрибута name tom.age = 37 # изменение значения атрибута age

Подобным образом мы можем создавать разные объекты класса Person с разным значением для атрибутов:

class Person: def __init__(self, name, age): self.name = name # имя человека self.age = age # возраст человека tom = Person("Tom", 22) bob = Person("Bob", 43) print(tom.name) # Tom print(bob.name) # Bob

Здесь создаются два объекта класса Person: tom и bob. Они соответствуют определению класса Person, имеют одинаковый набор атрибутов, однако их состояние будет отличаться. И в каждом случае Python будет динамически определять объект self. Так, в следующем случае

tom = Person("Tom", 22)

Это будет объект tom

bob = Person("Bob", 43)

Это будет объект bob

В принципе нам необязательно определять атрибуты внутри класса — Python позволяет сделать это динамически вне кода:

class Person: def __init__(self, name, age): self.name = name # имя человека self.age = age # возраст человека tom = Person("Tom", 22) tom.company = "Microsoft" print(tom.company) # Microsoft

Здесь динамически устанавливается атрибут company, который хранит место работы человека. И после установки мы также можем получить его значение. В то же время подобное определение чревато ошибками. Например, если мы попытаемся обратиться к атрибуту до его определения, то программа сгенерирует ошибку:

tom = Person("Tom", 22) print(tom.company) # ! Ошибка - AttributeError: Person object has no attribute company

Методы классов

Методы класса фактически представляют функции, которые определенны внутри класса и которые определяют его поведение. Например, определим класс Person с одним методом:

class Person: # определение класса Person def say_hello(self): print("Hello") tom = Person() tom.say_hello() # Hello

Здесь определен метод say_hello() , который условно выполняет приветствие — выводит строку на консоль. При определении методов любого класса, как и конструктора, первый параметр метода представляет ссылку на текущий объект, который согласно условностям называется self . Через эту ссылку внутри класса мы можем обратиться к функциональности текущего объекта. Но при самом вызове метода этот параметр не учитывается.

Используя имя объекта, мы можем обратиться к его методам. Для обращения к методам применяется нотация точки — после имени объекта ставится точка и после нее идет вызов метода:

объект.метод([параметры метода])

Например, обращение к методу say_hello() для вывода приветствия на консоль:

tom.say_hello() # Hello

В итоге данная программа выведет на консоль строку «Hello».

Если метод должен принимать другие параметры, то они определяются после параметра self , и при вызове подобного метода для них необходимо передать значения:

class Person: # определение класса Person def say(self, message): # метод print(message) tom = Person() tom.say("Hello METANIT.COM") # Hello METANIT.COM

Здесь определен метод say() . Он принимает два параметра: self и message. И для второго параметра — message при вызове метода необходимо передать значение.

Для обращения к атрибутам и методам объекта внутри класса в его методах также применяется слово self:

self.атрибут # обращение к атрибуту self.метод # обращение к методу

Например, следующий класс Person:

class Person: def __init__(self, name, age): self.name = name # имя человека self.age = age # возраст человека def display_info(self): print(f"Name: Age: ") tom = Person("Tom", 22) tom.display_info() # Name: Tom Age: 22 bob = Person("Bob", 43) bob.display_info() # Name: Bob Age: 43

Здесь определяется метод display_info(), который выводит информацию на консоль. И для обращения в методе к атрибутам объекта применяется слово self: self.name и self.age

В итоге мы получим следующий консольный вывод:

Name: Tom Age: 22 Name: Bob Age: 43

Деструкторы

Кроме конструкторов классы в Python также могут определять специальные методы — деструкторы , которые вызываются при удалении объекта. Деструктор представляет собой метод __del__(self) , в который, как и в конструктор, передается ссылка на текущий объект. В деструкторе определяются действия, которые надо выполнить при удалении объекта, например, освобождение или удаление каких-то ресурсов, которые использовал объект.

Деструктор вызывается автоматически интерпретатором, нам не нужно его явным образом вызывать. Простейший пример:

class Person: def __init__(self, name): self.name = name print("Создан человек с именем", self.name) def __del__(self): print("Удален человек с именем", self.name) tom = Person("Tom")

Здесь в деструкторе просто выведится уведомление об удалении объекта Person. Программа создает один объект Person и хранит ссылку на него в переменной tom. Создание объекта вызовет выполнение конструктора. При завершении программы автоматически будет выполняться деструктор объекта tom. В итоге консольный вывод программы будет следующим:

Создан человек с именем Tom Удален человек с именем Tom
class Person: def __init__(self, name): self.name = name print("Создан человек с именем", self.name) def __del__(self): print("Удален человек с именем", self.name) def create_person(): tom = Person("Tom") create_person() print("Конец программы")

Здесь объект Person создается и используется внутри функции create_person, поэтому жизнь создаваемого объекта Person ограничена областью этой функции. Соответственно, когда функция завершит свое выполнение, у объекта Person будет вызываться деструктор. В итоге мы получим следующий консольный вывод:

Создан человек с именем Tom Удален человек с именем Tom Конец программы

Как передать список обектов в функцию?

Author24 — интернет-сервис помощи студентам

Компилятор жалуеться на то что в функции display_persons у аргумента persons нету функции display.Как дать ему понять что список persons хранит обекты класса Person?

Лучшие ответы ( 1 )
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
Ответы с готовыми решениями:

Как посмотреть список всех обектов определённого типа?
Например у меня есть 10 обектов. Мне нужно в цыкле обращаться к каждому из них. Как мне это сделать?

Как передать список в функцию
Здравствуйте , подскажите как передать в функцию-шаблон список , выдает ошибку .

Как передать в функцию список смежности графа?
Как передать в функцию список смежности графа который представлений как вектор векторов -.

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

60 / 86 / 16
Регистрация: 25.03.2019
Сообщений: 235

Лучший ответ

Сообщение было отмечено Smoug1894 как решение

Решение

Убрать астериск из строки:

def display_persons(*persons):

Он там нафиг не нужен. То есть сделать так:

def display_persons(persons):

Примеры работы с классами в Python

Python — объектно-ориентированный язык с начала его существования. Поэтому, создание и использование классов и объектов в Python просто и легко. Эта статья поможет разобраться на примерах в области поддержки объектно-ориентированного программирования Python. Если у вас нет опыта работы с объектно-ориентированным программированием (OOП), ознакомьтесь с вводным курсом или учебным пособием, чтобы понять основные понятия.

Создание классов

Оператор class создает новое определение класса. Имя класса сразу следует за ключевым словом class , после которого ставиться двоеточие:

class ClassName: """Необязательная строка документации класса""" class_suite
  • У класса есть строка документации, к которой можно получить доступ через ClassName.__doc__ .
  • class_suite состоит из частей класса, атрибутов данных и функции.

Пример создания класса на Python:

 
class Employee: """Базовый класс для всех сотрудников""" emp_count = 0 def __init__(self, name, salary): self.name = name self.salary = salary Employee.emp_count += 1 def display_count(self): print('Всего сотрудников: %d' % Employee.empCount) def display_employee(self): print('Имя: <>. Зарплата: <>'.format(self.name, self.salary))
  • Переменная emp_count — переменная класса, значение которой разделяется между экземплярами этого класса. Получить доступ к этой переменной можно через Employee.emp_count из класса или за его пределами.
  • Первый метод __init__() — специальный метод, который называют конструктором класса или методом инициализации. Его вызывает Python при создании нового экземпляра этого класса.
  • Объявляйте другие методы класса, как обычные функции, за исключением того, что первый аргумент для каждого метода self . Python добавляет аргумент self в список для вас; и тогда вам не нужно включать его при вызове этих методов.

Создание экземпляров класса

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

 
# Это создаст первый объект класса Employee emp1 = Employee("Андрей", 2000) # Это создаст второй объект класса Employee emp2 = Employee("Мария", 5000)

Доступ к атрибутам

Получите доступ к атрибутам класса, используя оператор . после объекта класса. Доступ к классу можно получить используя имя переменой класса:

 
emp1.display_employee() emp2.display_employee() print("Всего сотрудников: %d" % Employee.emp_count)

Теперь, систематизируем все.

 
class Employee: """Базовый класс для всех сотрудников""" emp_count = 0 def __init__(self, name, salary): self.name = name self.salary = salary Employee.emp_count += 1 def display_count(self): print('Всего сотрудников: %d' % Employee.emp_count) def display_employee(self): print('Имя: <>. Зарплата: <>'.format(self.name, self.salary)) # Это создаст первый объект класса Employee emp1 = Employee("Андрей", 2000) # Это создаст второй объект класса Employee emp2 = Employee("Мария", 5000) emp1.display_employee() emp2.display_employee() print("Всего сотрудников: %d" % Employee.emp_count)

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

Имя: Андрей. Зарплата: 2000 Имя: Мария. Зарплата: 5000 Всего сотрудников: 2 

Вы можете добавлять, удалять или изменять атрибуты классов и объектов в любой момент.

 
emp1.age = 7 # Добавит атрибут 'age' emp1.age = 8 # Изменит атрибут 'age' del emp1.age # Удалит атрибут 'age'

Вместо использования привычных операторов для доступа к атрибутам вы можете использовать эти функции:

  • getattr(obj, name [, default]) — для доступа к атрибуту объекта.
  • hasattr(obj, name) — проверить, есть ли в obj атрибут name .
  • setattr(obj, name, value) — задать атрибут. Если атрибут не существует, он будет создан.
  • delattr(obj, name) — удалить атрибут.
 
hasattr(emp1, 'age') # возвращает true если атрибут 'age' существует getattr(emp1, 'age') # возвращает значение атрибута 'age' setattr(emp1, 'age', 8) #устанавливает атрибут 'age' на 8 delattr(empl, 'age') # удаляет атрибут 'age'

Встроенные атрибуты класса

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

  • __dict__ — словарь, содержащий пространство имен класса.
  • __doc__ — строка документации класса. None если, документация отсутствует.
  • __name__ — имя класса.
  • __module__ — имя модуля, в котором определяется класс. Этот атрибут __main__ в интерактивном режиме.
  • __bases__ — могут быть пустые tuple, содержащие базовые классы, в порядке их появления в списке базового класса.

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

 
class Employee: """Базовый класс для всех сотрудников""" emp_count = 0 def __init__(self, name, salary): self.name = name self.salary = salary Employee.empCount += 1 def display_count(self): print('Всего сотрудников: %d' % Employee.empCount) def display_employee(self): print('Имя: <>. Зарплата: <>'.format(self.name, self.salary)) print("Employee.__doc__:", Employee.__doc__) print("Employee.__name__:", Employee.__name__) print("Employee.__module__:", Employee.__module__) print("Employee.__bases__:", Employee.__bases__) print("Employee.__dict__:", Employee.__dict__)

Когда этот код выполняется, он возвращает такой результат:

Employee.__doc__: Базовый класс для всех сотрудников Employee.__name__: Employee Employee.__module__: __main__ Employee.__bases__: (,) Employee.__dict__: , 'display_count': , 'display_employee': , '__dict__': , '__weakref__': > 

Удаление объектов (сбор мусора)

Python автоматически удаляет ненужные объекты (встроенные типы или экземпляры классов), чтобы освободить пространство памяти. С помощью процесса ‘Garbage Collection’ Python периодически восстанавливает блоки памяти, которые больше не используются.

Сборщик мусора Python запускается во время выполнения программы и тогда, когда количество ссылок на объект достигает нуля. С изменением количества обращений к нему, меняется количество ссылок.

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

a = 40 # создали объект b = a # увеличивает количество ссылок c = [b] # увеличивает количество ссылок del a # уменьшает количество ссылок b = 100 # уменьшает количество ссылок c[0] = -1 # уменьшает количество ссылок

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

Пример работы __del__()
Деструктор __del__() выводит имя класса того экземпляра, который должен быть уничтожен:

 
class Point: def __init__(self, x=0, y=0): self.x = x self.y = y def __del__(self): class_name = self.__class__.__name__ print('<> уничтожен'.format(class_name)) pt1 = Point() pt2 = pt1 pt3 = pt1 print(id(pt1), id(pt2), id(pt3)) # выведите id объектов del pt1 del pt2 del pt3

Когда вышеуказанный код выполняется и выводит следующее:

17692784 17692784 17692784 Point уничтожен

В идеале вы должны создавать свои классы в отдельном модуле. Затем импортировать их в основной модуль программы с помощью import SomeClass .

Наследование класса в python

Наследование — это процесс, когда один класс наследует атрибуты и методы другого. Класс, чьи свойства и методы наследуются, называют Родителем или Суперклассом. А класс, свойства которого наследуются — класс-потомок или Подкласс.

Вместо того, чтобы начинать с нуля, вы можете создать класс, на основе уже существующего. Укажите родительский класс в круглых скобках после имени нового класса.

Класс наследник наследует атрибуты своего родительского класса. Вы можете использовать эти атрибуты так, как будто они определены в классе наследнике. Он может переопределять элементы данных и методы родителя.

Синтаксис наследования класса

Классы наследники объявляются так, как и родительские классы. Только, список наследуемых классов, указан после имени класса.

class SubClassName(ParentClass1[, ParentClass2, . ]): """Необязательная строка документации класса""" class_suite

Пример наследования класса в Python

 
class Parent: # объявляем родительский класс parent_attr = 100 def __init__(self): print('Вызов родительского конструктора') def parent_method(self): print('Вызов родительского метода') def set_attr(self, attr): Parent.parent_attr = attr def get_attr(self): print('Атрибут родителя: <>'.format(Parent.parent_attr)) class Child(Parent): # объявляем класс наследник def __init__(self): print('Вызов конструктора класса наследника') def child_method(self): print('Вызов метода класса наследника') c = Child() # экземпляр класса Child c.child_method() # вызов метода child_method c.parent_method() # вызов родительского метода parent_method c.set_attr(200) # еще раз вызов родительского метода c.get_attr() # снова вызов родительского метода

Когда этот код выполняется, он выводит следующий результат:

Вызов конструктора класса наследника Вызов метода класса наследника Вызов родительского метода Атрибут родителя: 200

Аналогичным образом вы можете управлять классом с помощью нескольких родительских классов:

class A: # объявите класс A . class B: # объявите класс B . class C(A, B): # C наследуется от A и B . 

Вы можете использовать функции issubclass() или isinstance() для проверки отношений двух классов и экземпляров.

  • Логическая функция issubclass(sub, sup) возвращает значение True , если данный подкласс sub действительно является подклассом sup .
  • Логическая функция isinstance(obj, Class) возвращает True , если obj является экземпляром класса Class или является экземпляром подкласса класса.

Переопределение методов

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

Пример переопределения методов:

 
class Parent: # объявите родительский класс def my_method(self): print('Вызов родительского метода') class Child(Parent): # объявите класс наследник def my_method(self): print('Вызов метода наследника') c = Child() # экземпляр класса Child c.my_method() # метод переопределен классом наследником

Когда этот код выполняется, он производит следующий результат:

Вызов метода наследника

Популярные базовые методы

В данной таблице перечислены некоторые общие функции. Вы можете переопределить их в своих собственных классах.

Метод, описание и пример вызова
1 __init__(self [, args. ]) — конструктор (с любыми необязательными аргументами)
obj = className(args)
2 __del__(self) — деструктор, удаляет объект
del obj
3 __repr__(self) — программное представление объекта
repr(obj)
4 __str__(self) — строковое представление объекта
str(obj)

Пример использования __add__

Предположим, вы создали класс Vector для представления двумерных векторов. Что происходит, когда вы используете дополнительный оператор для их добавления? Скорее всего, Python будет против.

Однако вы можете определить метод __add__ в своем классе для добавления векторов и оператор + будет вести себя так как нужно.

 
class Vector: def __init__(self, a, b): self.a = a self.b = b def __str__(self): return 'Vector (<>, <>)'.format(self.a, self.b) def __add__(self, other): return Vector(self.a + other.a, self.b + other.b) v1 = Vector(2, 10) v2 = Vector(5, -2) print(v1 + v2)

При выполнении этого кода, мы получим:

Vector(7, 8)

Приватные методы и атрибуты

Атрибуты класса могут быть не видимыми вне определения класса. Вам нужно указать атрибуты с __ вначале, и эти атрибуты не будут вызваны вне класса.

Пример приватного атрибута:

 
class JustCounter: __secret_count = 0 def count(self): self.__secret_count += 1 print(self.__secret_count) counter = JustCounter() counter.count() counter.count() print(counter.__secret_count)

При выполнении данного кода, имеем следующий результат:

1 2 Traceback (most recent call last): File "test.py", line 12, in print(counter.__secret_count) AttributeError: 'JustCounter' object has no attribute '__secret_count'

Вы можете получить доступ к таким атрибутам, так object._className__attrName . Если вы замените свою последнюю строку следующим образом, то она будет работать.

Python - Объектно Ориентированное Программирование (ООП)

1 что приходит на ум - абстракция. Мы не думаем о том как устроен объект, а думаем о том что мы можем с ним сделать.
Например, возьмём функцию dir() и передадим экземпляр объекта список в неё как аргумент:

dir(L)

методы списка (dir)

На выходе получим большой список. Большой список методов для списка.
У нас есть 2 пути:

  • опробовать некоторые из них (возможно, пытаясь передать какие-то атрибуты)
  • найти их описание в google по имени

Но в любом случае мы узнаем о том, "что можно делать со списком", не изучая то как он устроен.

При этом если мы создадим свою структуру данных, свой класс со своими объектами, то у них могут быть одноимённые методы (например, если они ведут себя аналогично).

Например, у строк есть несколько методов, одноимённых методом списков:
методы строки (dir)
Метод index() является одним из них.
Рассмотрим как он работает для наших примеров:
поиск по индексу для списка и строки

Легко заметить, что некоторые методы в списке имели по 2 подчёркивания с обеих сторон, например:

__len__

определение длинны списка и строки (len)

Это "стандартный" метод. Фактически, когда мы используем функцию len(), например:

то на самом деле вызывается метод __len__ соответствующего объекта.

Почему?
Всё потому же - если мы будем внутри функции языка len описывать как вычислять длину любого объекта, то это будет очень много кода. Да и для новых классов объектов (например, numpy.array) эта функция не будет работать.
А так у каждого класса внутри будет краткое описание того как это работает.

Что будет если сложить строку и список в python?

Так же это позволяет переопределить поведение некоторых операторов.
Например, что будет, если мы напишем:

Фактически будет вызван метод add - s.__add__(L)

Если в python сложить строку и список, то получится ошибка =)

В нашем примере мы получим ошибку:

а numpy array и список в python сложить можно (они должны быть одной длины и сложатся поэлементно)

Но некоторые классы объектов вполне могут принимать на вход "чужака" (не всякого конечно):

А ещё когда мы пишем

print L

, то на самом деле вызывается метод __str__, чтобы преобразовать список L в строку для печати.

  • класс - это инструкция, по которой собирается конкретный объект
  • экземпляр - это конкретный объект
  • а метод - это функция, присущая конкретному классу объектов.
  • [1, 2, 3, 4]
  • [1, 2, 3]

атрибут shape для numpy array

Примером атрибута может быть shape для numpy:

Мы просто создали вектор, передав в него данные. И при этом вычислился его размер.
Логично, для больших матриц в векторов проще хранить внутри 1 переменную с натуральным числом, чем каждый раз проходить по всем данным и тратить время для вычислений.

Давайте попрактикуемся

python - пример пустого класса

Создадим пустой класс, который ничего не делает и ничего не хранит:

Теперь создадим 1й метод у нашего класса.
Для этого создадим функцию, внутри метода. Она должна принимать по крайней мере 1 аргумент - self - это экземпляр того объекта, методов которого функция будет.

python - пример класса с 1 методом, выводящим на печать строку

Python - пример класса с простым методом, принимающим 1 аргумент

Если мы хотим передавать в метод какие-то параметры, то просто зададим их после self, как и обычные параметры функции:

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

создаём атрибут у уже существующего экземпляра объекта в python

Синтаксис для атрибутов аналогичен синтаксису методов (только после атрибута не надо ставить круглые скобки):

  • obj.method()
  • obj.atr

Давайте создадим атрибут у экземпляра объекта:

добавляем 2 разных атрибута в 2 разных экземпляра одного объекта в python

Вполне очевидно, что если я создам 2й экземпляр этого же класса, и присвою уже в нём атрибуту с таким же именем какое-то значение, то у разных экземпляров в одноимённом атрибуте будут разные значения:

создаём атрибут в классе python

Так же я могу определить переменную внутри класса и она станет атрибутов всех экземпляров этого класса.
Естественно, это не отменит возможность принудительного переопределения соответствующего атрибута у какого-то экземпляра:

Для экземпляров B и C значение атрибута равно значению по-умолчанию (списку), а для экземпляров E и A переопределено (на число и строку).

  • надо определить класс
  • создать объект
  • обратиться к каждому из атрибутов, записав туда кастомные данные
  • обратиться к каждому объекту, передав туда кастомные аргументы

Для этого служит метод __init__().

добавляем создание атрибута в инициализатор (конструктор) простого класса Python

Перепишем наш класс и убедимся, что его работа не изменилась:

Важно:

  • метод __init__(), как и другие методы класса должен принимать как минимум 1 аргумент self
  • к аргументам объекта можно обращаться из метода как аргументам self (например, self.arg)
  • Если аргумент создаётся конструктором __init__, то его не нужно описывать в классе как отдельную переменную

Если для конструктора __init__ мы зададим какие-то аргументы кроме self, то их можно будет передать в конструктор при создании экземпляра объекта, и сразу записать в аргументы, если необходимо.

Класс создания точки на плоскости с методом вычисления расстояния между точек

Давайте создадим чуть более осмысленный класс.
Пусть это будет класс "Точка". Точка у нас будет характеризоваться 2 координатами (x, y).
И сразу зададим метод для нашей точки, вычисляющий расстояние от неё до другой точки (для этого воспользуемся теоремой Пифагора):

Здесь метод dist принимает 2 аргумента: экземпляр текущего объекта и ещё одного, между которыми необходимо найти расстояние.
Поскольку метод применяется к текущему экземпляру, то при вызове метода в скобках я указываю только 2ю точку).

вызов метода из класса Python напрямую с передачей 2 объектов в качестве аргументов

Если я хочу передавать в мой метод аргументы привычным образом (как аргументы в скобках по порядку), то мне необходимо указать полный путь до метода. Он начнётся с имени класса:

Обратите внимание, что 2й способ обращения позволяет использовать классы как хранилище функций даже для стандартных типов данных.

Класс как хранилище функций - простой пример

Вот пример такого "хранилища":

Вывод на печать экземпляра объекта без метода __str__

Заметим, что если мы попытаемся напечатать экземпляр объекта (а не его атрибуты, как раньше), то ничего хорошего не получим:

Добавление метода __str__ для корректной печати экземпляров объекта в python

Мы можем понять экземпляром какого класса объект является и на какую область памяти смотрит указатель, но в работе это довольно бесполезно.
Согласитесь, печатая экземпляр списка мы получаем список - это удобно.
Воспользуемся стандартным методом __str__, который вызывается при его печати с помощью print:

Интересный эффект, который можно заметить - после пересоздания класса ранее созданные объекты не меняют своего поведения.

Дело в том, что класс - это тоже объект.

С точки зрения python мы создали 2 объекта. И на базе 1-ого создали несколько экземпляров.
Поэтому чтобы новые методы добавились у объектов, объекты придётся пересоздать.

Сравнение двух экземпляров одного объекта с идентичными атрибутами в python

Давайте заведём ещё 1 экземпляр объекта с точно такими же координатами, что и первый.
В бытовом понимании 2 такие точки "равны". Но что будет, если мы их сравним?

С точки зрения python это 2 разных объекта, а потому они НЕ равны.

Метод для сравнения двух экземпляров одного класса в python

Чтобы это исправить можно написать стандартный метод __eq__:

Замечу, что если мы заведём по новому атрибуту у наших точек (например, цвету), то операция сравнения их учитывать не будет:

метод класса учитывает не все атрибуты при сравнении в python (2 экземпляра имеют разные значения одного атрибута, но код считает их равными друг другу)

Геттеры и Сеттеры

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

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

геттеры и сеттеры в ООП python

Добавим в наш класс 2 новых метода:

  • сеттер - setColor - проверяет, что передаётся строка и записывает её в атрибут color экземпляра. Если передан другой тип данных, возвращает ошибку.
  • геттер - getColor - возвращает значение атрибута color текущего экземпляра

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

Наследование

  • атрибуты: число ног, имя, возраст.
  • методы: геттеры и сеттеры
  • атрибуты: имя и т.п.
  • методы: "говорение" (мяу) и т.п.

Наследник получает все методы и атрибуты родителя, а так же может некоторые из них переопределить (например, если мы сделаем класс "птицы" наследником класса "животные", то, вероятно, ограничение на число ног изменится с 4 до 2), а так же задать собственные атрибуты и методы.

Пример простого наследования в python с переопределением конструктора

Давайте в нашем примере представим, что наш класс точек - это объекты на географической карте. Точка может использоваться для оформления (например, прокладки маршрута из точек).
А новый класс будет представлять из себя географический маркер: банкомат, достопримечательность, организацию или что-то иное.
Новый класс будет наследником обычной точки, но мы чуть расширим конструктор, чтобы иметь больше атрибутов:

Как видим, наш класс получил возможность использовать сеттер родительского класса, да и стандартная функция __str__ тоже наследуется.

Пример простого наследования в python с переопределением методов

Давайте зададим нашему классу новый метод __str__, чтобы при выводе на печать понимать что это не просто точка, именно маркер. И внутри будем использовать метод __str__ родительского класса:

Т.е. вы всегда можете обратиться к родительским методам у экземпляров дочерних классов, если это необходимо.

Давайте создадим ещё пару классов.

Пример создания класса, который станет в будущем

1 будет идентичен предыдущим - это будет класс иконок с геттером и сеттером:

Такие классы ещё иногда называются "примесью", дальше станет понятно почему.

Пример множественного наследования в python

А вот 2 будет интереснее. Это будет класс организации. И мы не станем записывать для него ни атрибутов, ни классов. Но унаследуем его от 2 родителей:

Удивительно, но это работает.
При этом:

  • наследник получает все методы и атрибуты обоих родителей.
  • если у нескольких родителей есть одноимённые методы, то автоматически наследник получит методы того, кто раньше в списке (в нашем случае раньше был гео маркер, поэтому конструктор был унаследован от него, а не от организации).

Наследование от нескольких родителей иногда считается сомнительной практикой, будьте с ним аккуратны.

Переменные класса

Мы уже говорили про атрибуты в качестве хранилища данных (мы даже создавали их внутри класса в самом начале).
Есть ещё одно интересное применение для них - переменная класса. Т.е переменные, которые хранятся в классе, а не в экземпляре.

Модифицируем конструктор организации (добавим заодно поддержку url). В классе создадим переменную tag с первоначальным значением равным 0. В конструкторе же запишем в переменную ID создаваемого экземпляра значение из tag, а tag после этого увеличим на 1:
Переменная класса - атрибут класса изменяется при создании каждого экземпляра для создания счётчика числа экземпляров класса
Таким образом мы получили:

  • в атрибуте ID каждого объекта хранится его уникальный порядковый номер
  • в переменной tag класса хранится число созданных объектов (тут надо быть осторожнее, так как возможно мы захотим уменьшать это число при удалении объекта).

Ну и не забываем, что каждый экземпляр имеет доступ к атрибутам класса помимо собственных, т.е. tag:
Доступ к атрибуту класса (переменной класса) есть и из экземпляров

Переиспользование методов

Частичное наследование методов в python OOP

Мы уже говорили про наследование методов, мы даже использовали методы родительского класса.
Но можно наследовать часть родительского метода (и собирать из нескольких родительских 1 свой). Сократим наш код организации, унаследовав конструкторы гео маркера и иконки:

Мы совместили 2 наследуемых метода и свой код.
И всё это работает.
=)

Полезные ссылки:

  • https://www.ibm.com/developerworks/ru/library/l-python_part_6/index.html
  • https://ru.wikipedia.org/wiki/%D0%9E%D0%B1%D1%8A%D0%B5%D0%BA%D1%82%D0%BD%D0%BE-%D0%BE%D1%80%D0%B8%D0%B5%D0%BD%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%BD%D0%B0_Python
  • https://pythonworld.ru/osnovy/obektno-orientirovannoe-programmirovanie-obshhee-predstavlenie.html
  • https://www.codecademy.com/courses/learn-python/lessons/introduction-to-classes/exercises/why-use-classes
  • MIT6.00.1x про ООП:
    • https://youtu.be/nQXFr9Ma2lk
    • https://youtu.be/2Dy-JQZwz5A
    • https://youtu.be/cx7m9hDG_OE
    • https://youtu.be/6wMNPuoudrA
    • https://youtu.be/Vfw6XoUOOvc
    • https://youtu.be/08V2ukhKe1k
    • https://youtu.be/6CbZiKX5mRw
    • https://youtu.be/Y4sR0fUq6bY
    • https://youtu.be/LnnEPJebkbU
    • https://youtu.be/IxKLyEa4DsI

    Материалы по теме:

    • Как простой менеджер проектов на 1С-Битрикс пошёл учиться машинному обучению от Яндекса и МФТИ, а стал ментором Coursera
    • Решение систем линейных уравнений в Python

    Другие новости:

    Автор

    Задойный А.В.

    Специалист по 1С-Битрикс

    Автор интеграции шаблона на платформу 1С-Битрикс.
    Техническая поддержка в РФ.

    Python - Объектно Ориентированное Программирование (ООП)

    Python - Объектно Ориентированное Программирование (ООП)

    В данной статье даются основы ООП в питоне

    В python всё - объекты.

    *Аудитория в шоке, особо нервные дамочки падают в обморок*

    • Числа - объекты
    • Строки - объекты
    • Списки - объекты
    • Классы - объекты
    • .

    Если говорить просто, то "объекты" - это некая структура.

    И было слово.

    Чтобы создавать объекты, используются "конструкторы" или классы.

    • Класс - это схема, описывающая нашу структуру, возможные внутри неё данные и присущие ей методы.
    • Метод - это функция. Т.е. метод объекта - это функция, описанная внутри объекта, и присущая этому объекту. Метод - это функция, которая действует на объекты данного вида. Для удобства у разных видов объектов могут быть методы с одинаковыми именами, работающие по разному, но схожим образом.
    • Экземпляр - это конкретный объект, созданный из класса.

    Рассмотрим пример

    Список:

    L = [1, 2, 3, 4]

    • Список (List) - это класс объекта
    • Переменная L содержит экземпляр объекта (конкретно список [1, 2, 3, 4])
    • append(), sort() - методы объекта, т.е. функции, которые можно применить к его экземплярам.

    Пока звучит не очень сложно.
    Но по прежнему не понятно зачем это нужно. =)

    1 что приходит на ум - абстракция. Мы не думаем о том как устроен объект, а думаем о том что мы можем с ним сделать.
    Например, возьмём функцию dir() и передадим экземпляр объекта список в неё как аргумент:

    dir(L)

    методы списка (dir)
    На выходе получим большой список. Большой список методов для списка.
    У нас есть 2 пути:

    • опробовать некоторые из них (возможно, пытаясь передать какие-то атрибуты)
    • найти их описание в google по имени

    Но в любом случае мы узнаем о том, "что можно делать со списком", не изучая то как он устроен.

    При этом если мы создадим свою структуру данных, свой класс со своими объектами, то у них могут быть одноимённые методы (например, если они ведут себя аналогично).

    Например, у строк есть несколько методов, одноимённых методом списков:
    методы строки (dir)
    Метод index() является одним из них.
    Рассмотрим как он работает для наших примеров:
    поиск по индексу для списка и строки

    Легко заметить, что некоторые методы в списке имели по 2 подчёркивания с обеих сторон, например:

    __len__

    Это "стандартный" метод. Фактически, когда мы используем функцию len(), например:
    определение длинны списка и строки (len)
    то на самом деле вызывается метод __len__ соответствующего объекта.

    Почему?
    Всё потому же - если мы будем внутри функции языка len описывать как вычислять длину любого объекта, то это будет очень много кода. Да и для новых классов объектов (например, numpy.array) эта функция не будет работать.
    А так у каждого класса внутри будет краткое описание того как это работает.

    Так же это позволяет переопределить поведение некоторых операторов.
    Например, что будет, если мы напишем:
    Что будет если сложить строку и список в python?
    Фактически будет вызван метод add - s.__add__(L)

    В нашем примере мы получим ошибку:
    Если в python сложить строку и список, то получится ошибка =)

    Но некоторые классы объектов вполне могут принимать на вход "чужака" (не всякого конечно):
    а numpy array и список в python сложить можно (они должны быть одной длины и сложатся поэлементно)

    А ещё когда мы пишем

    print L

    , то на самом деле вызывается метод __str__, чтобы преобразовать список L в строку для печати.

    Итак,

    • класс - это инструкция, по которой собирается конкретный объект
    • экземпляр - это конкретный объект
    • а метод - это функция, присущая конкретному классу объектов.

    И это всё?

    Нет. =)

    Когда мы говорим, что есть 2 экземпляра объектов список:

    • [1, 2, 3, 4]
    • [1, 2, 3]

    то очевидно, что они содержат разные данные.
    Т.е. внутри объектов помимо методов есть данные, и хранятся они в атрибутах.

    Примером атрибута может быть shape для numpy:
    атрибут shape для numpy array
    Мы просто создали вектор, передав в него данные. И при этом вычислился его размер.
    Логично, для больших матриц в векторов проще хранить внутри 1 переменную с натуральным числом, чем каждый раз проходить по всем данным и тратить время для вычислений.

    Давайте попрактикуемся

    Создадим пустой класс, который ничего не делает и ничего не хранит:
    python - пример пустого класса

    Теперь создадим 1й метод у нашего класса.
    Для этого создадим функцию, внутри метода. Она должна принимать по крайней мере 1 аргумент - self - это экземпляр того объекта, методов которого функция будет.

    python - пример класса с 1 методом, выводящим на печать строку

    Если мы хотим передавать в метод какие-то параметры, то просто зададим их после self, как и обычные параметры функции:
    Python - пример класса с простым методом, принимающим 1 аргумент

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

    Синтаксис для атрибутов аналогичен синтаксису методов (только после атрибута не надо ставить круглые скобки):

    • obj.method()
    • obj.atr

    Давайте создадим атрибут у экземпляра объекта:
    создаём атрибут у уже существующего экземпляра объекта в python

    Вполне очевидно, что если я создам 2й экземпляр этого же класса, и присвою уже в нём атрибуту с таким же именем какое-то значение, то у разных экземпляров в одноимённом атрибуте будут разные значения:
    добавляем 2 разных атрибута в 2 разных экземпляра одного объекта в python

    Так же я могу определить переменную внутри класса и она станет атрибутов всех экземпляров этого класса.
    Естественно, это не отменит возможность принудительного переопределения соответствующего атрибута у какого-то экземпляра:
    создаём атрибут в классе python
    Для экземпляров B и C значение атрибута равно значению по-умолчанию (списку), а для экземпляров E и A переопределено (на число и строку).

    Пока пользоваться классами не очень удобно:

    • надо определить класс
    • создать объект
    • обратиться к каждому из атрибутов, записав туда кастомные данные
    • обратиться к каждому объекту, передав туда кастомные аргументы

    Однако, процесс можно усовершенствовать в помощью конструктора (на самом деле инициализатора, но мы в этой статье не будем углубляться в разницу). Конструктор вызывается автоматически при создании экземпляра.

    Для этого служит метод __init__().

    Перепишем наш класс и убедимся, что его работа не изменилась:
    добавляем создание атрибута в инициализатор (конструктор) простого класса Python
    Важно:

    • метод __init__(), как и другие методы класса должен принимать как минимум 1 аргумент self
    • к аргументам объекта можно обращаться из метода как аргументам self (например, self.arg)
    • Если аргумент создаётся конструктором __init__, то его не нужно описывать в классе как отдельную переменную

    Если для конструктора __init__ мы зададим какие-то аргументы кроме self, то их можно будет передать в конструктор при создании экземпляра объекта, и сразу записать в аргументы, если необходимо.

    Давайте создадим чуть более осмысленный класс.
    Пусть это будет класс "Точка". Точка у нас будет характеризоваться 2 координатами (x, y).
    И сразу зададим метод для нашей точки, вычисляющий расстояние от неё до другой точки (для этого воспользуемся теоремой Пифагора):
    Класс создания точки на плоскости с методом вычисления расстояния между точек

    Здесь метод dist принимает 2 аргумента: экземпляр текущего объекта и ещё одного, между которыми необходимо найти расстояние.
    Поскольку метод применяется к текущему экземпляру, то при вызове метода в скобках я указываю только 2ю точку).

    Если я хочу передавать в мой метод аргументы привычным образом (как аргументы в скобках по порядку), то мне необходимо указать полный путь до метода. Он начнётся с имени класса:
    вызов метода из класса Python напрямую с передачей 2 объектов в качестве аргументов
    Обратите внимание, что 2й способ обращения позволяет использовать классы как хранилище функций даже для стандартных типов данных.

    Вот пример такого "хранилища":
    Класс как хранилище функций - простой пример

    Заметим, что если мы попытаемся напечатать экземпляр объекта (а не его атрибуты, как раньше), то ничего хорошего не получим:
    Вывод на печать экземпляра объекта без метода __str__

    Мы можем понять экземпляром какого класса объект является и на какую область памяти смотрит указатель, но в работе это довольно бесполезно.
    Согласитесь, печатая экземпляр списка мы получаем список - это удобно.
    Воспользуемся стандартным методом __str__, который вызывается при его печати с помощью print:
    Добавление метода __str__ для корректной печати экземпляров объекта в python
    Интересный эффект, который можно заметить - после пересоздания класса ранее созданные объекты не меняют своего поведения.

    Дело в том, что класс - это тоже объект.

    С точки зрения python мы создали 2 объекта. И на базе 1-ого создали несколько экземпляров.
    Поэтому чтобы новые методы добавились у объектов, объекты придётся пересоздать.

    Давайте заведём ещё 1 экземпляр объекта с точно такими же координатами, что и первый.
    В бытовом понимании 2 такие точки "равны". Но что будет, если мы их сравним?
    Сравнение двух экземпляров одного объекта с идентичными атрибутами в python
    С точки зрения python это 2 разных объекта, а потому они НЕ равны.

    Чтобы это исправить можно написать стандартный метод __eq__:
    Метод для сравнения двух экземпляров одного класса в python
    Замечу, что если мы заведём по новому атрибуту у наших точек (например, цвету), то операция сравнения их учитывать не будет:

    метод класса учитывает не все атрибуты при сравнении в python (2 экземпляра имеют разные значения одного атрибута, но код считает их равными друг другу)

    Геттеры и Сеттеры

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

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

    Добавим в наш класс 2 новых метода:

    • сеттер - setColor - проверяет, что передаётся строка и записывает её в атрибут color экземпляра. Если передан другой тип данных, возвращает ошибку.
    • геттер - getColor - возвращает значение атрибута color текущего экземпляра

    геттеры и сеттеры в ООП python

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

    Наследование

    Идея в том, чтобы хранить в классе только необходимые для него объекты и атрибуты.
    И структурировать, объединить в иерархию объекты.
    Обычно это иллюстрируется на примерах животных: кошечки, собачки, кролики и т.п.
    Есть класс животные, он имеет

    • атрибуты: число ног, имя, возраст.
    • методы: геттеры и сеттеры

    Теперь создадим класс кошки. Кошки - тоже животные. Поэтому все атрибуты и методы класса животные им тоже присущи. Но кроме этого, у них могут быть свои:

    • атрибуты: имя и т.п.
    • методы: "говорение" (мяу) и т.п.

    Чтобы не дублировать код, класс кошки наследуется от класса животные.

    Наследник получает все методы и атрибуты родителя, а так же может некоторые из них переопределить (например, если мы сделаем класс "птицы" наследником класса "животные", то, вероятно, ограничение на число ног изменится с 4 до 2), а так же задать собственные атрибуты и методы.

    Давайте в нашем примере представим, что наш класс точек - это объекты на географической карте. Точка может использоваться для оформления (например, прокладки маршрута из точек).
    А новый класс будет представлять из себя географический маркер: банкомат, достопримечательность, организацию или что-то иное.
    Новый класс будет наследником обычной точки, но мы чуть расширим конструктор, чтобы иметь больше атрибутов:
    Пример простого наследования в python с переопределением конструктора
    Как видим, наш класс получил возможность использовать сеттер родительского класса, да и стандартная функция __str__ тоже наследуется.

    Давайте зададим нашему классу новый метод __str__, чтобы при выводе на печать понимать что это не просто точка, именно маркер. И внутри будем использовать метод __str__ родительского класса:
    Пример простого наследования в python с переопределением методов
    Т.е. вы всегда можете обратиться к родительским методам у экземпляров дочерних классов, если это необходимо.

    Давайте создадим ещё пару классов.

    1 будет идентичен предыдущим - это будет класс иконок с геттером и сеттером:
    Пример создания класса, который станет в будущем "примесью" при наследовании
    Такие классы ещё иногда называются "примесью", дальше станет понятно почему.

    А вот 2 будет интереснее. Это будет класс организации. И мы не станем записывать для него ни атрибутов, ни классов. Но унаследуем его от 2 родителей:
    Пример множественного наследования в python
    Удивительно, но это работает.
    При этом:

    • наследник получает все методы и атрибуты обоих родителей.
    • если у нескольких родителей есть одноимённые методы, то автоматически наследник получит методы того, кто раньше в списке (в нашем случае раньше был гео маркер, поэтому конструктор был унаследован от него, а не от организации).

    Наследование от нескольких родителей иногда считается сомнительной практикой, будьте с ним аккуратны.

    Переменные класса

    Мы уже говорили про атрибуты в качестве хранилища данных (мы даже создавали их внутри класса в самом начале).
    Есть ещё одно интересное применение для них - переменная класса. Т.е переменные, которые хранятся в классе, а не в экземпляре.

    Модифицируем конструктор организации (добавим заодно поддержку url). В классе создадим переменную tag с первоначальным значением равным 0. В конструкторе же запишем в переменную ID создаваемого экземпляра значение из tag, а tag после этого увеличим на 1:
    Переменная класса - атрибут класса изменяется при создании каждого экземпляра для создания счётчика числа экземпляров класса
    Таким образом мы получили:

    • в атрибуте ID каждого объекта хранится его уникальный порядковый номер
    • в переменной tag класса хранится число созданных объектов (тут надо быть осторожнее, так как возможно мы захотим уменьшать это число при удалении объекта).

    Ну и не забываем, что каждый экземпляр имеет доступ к атрибутам класса помимо собственных, т.е. tag:
    Доступ к атрибуту класса (переменной класса) есть и из экземпляров

    Переиспользование методов

    Мы уже говорили про наследование методов, мы даже использовали методы родительского класса.
    Но можно наследовать часть родительского метода (и собирать из нескольких родительских 1 свой). Сократим наш код организации, унаследовав конструкторы гео маркера и иконки:
    Частичное наследование методов в python OOP
    Мы совместили 2 наследуемых метода и свой код.
    И всё это работает.
    =)

    Полезные ссылки:
    • https://www.ibm.com/developerworks/ru/library/l-python_part_6/index.html
    • https://ru.wikipedia.org/wiki/%D0%9E%D0%B1%D1%8A%D0%B5%D0%BA%D1%82%D0%BD%D0%BE-%D0%BE%D1%80%D0%B8%D0%B5%D0%BD%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%BD%D0%B0_Python
    • https://pythonworld.ru/osnovy/obektno-orientirovannoe-programmirovanie-obshhee-predstavlenie.html
    • https://www.codecademy.com/courses/learn-python/lessons/introduction-to-classes/exercises/why-use-classes
    • MIT6.00.1x про ООП:
      • https://youtu.be/nQXFr9Ma2lk
      • https://youtu.be/2Dy-JQZwz5A
      • https://youtu.be/cx7m9hDG_OE
      • https://youtu.be/6wMNPuoudrA
      • https://youtu.be/Vfw6XoUOOvc
      • https://youtu.be/08V2ukhKe1k
      • https://youtu.be/6CbZiKX5mRw
      • https://youtu.be/Y4sR0fUq6bY
      • https://youtu.be/LnnEPJebkbU
      • https://youtu.be/IxKLyEa4DsI

    Специалист по 1С-Битрикс

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *