Что такое self
Перейти к содержимому

Что такое self

  • автор:

Параметр self#

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

Пример с использованием другого имени, вместо self:

In [15]: class Switch: . : def info(sw_object): . : print(f'Hostname: sw_object.hostname>\nModel: sw_object.model>') . : 

Работать все будет аналогично:

In [16]: sw1 = Switch() In [17]: sw1.hostname = 'sw1' In [18]: sw1.model = 'Cisco 3850' In [19]: sw1.info() Hostname: sw1 Model: Cisco 3850 

Хотя технически использовать другое имя можно, всегда используйте self.

Во всех «обычных» методах класса первым параметром всегда будет self. Кроме того, создание переменной экземпляра внутри класса также выполняется через self.

Пример класса Switch с новым методом generate_interfaces: метод generate_interfaces должен сгенерировать список с интерфейсами на основании указанного типа и количества и создать переменную в экземпляре класса. Для начала, вариант создания обычно переменной внутри метода:

In [5]: class Switch: . : def generate_interfaces(self, intf_type, number_of_intf): . : interfaces = [f"intf_type>number>" for number in range(1, number_of_intf + 1)] . : 

В этом случае, в экземплярах класса не будет переменной interfaces:

In [6]: sw1 = Switch() In [7]: sw1.generate_interfaces('Fa', 10) In [8]: sw1.interfaces --------------------------------------------------------------------------- AttributeError Traceback (most recent call last) ipython-input-8-e6b457e4e23e> in module>() ----> 1 sw1.interfaces AttributeError: 'Switch' object has no attribute 'interfaces' 

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

Чтобы список с интерфейсами был доступен как переменная в экземплярах, надо присвоить значение в self.interfaces:

In [9]: class Switch: . : def info(self): . : print(f"Hostname: self.hostname>\nModel: self.model>") . : . : def generate_interfaces(self, intf_type, number_of_intf): . : interfaces = [f"intf_type>number>" for number in range(1, number_of_intf+1)] . : self.interfaces = interfaces . : 

Теперь, после вызова метода generate_interfaces, в экземпляре создается переменная interfaces:

In [10]: sw1 = Switch() In [11]: sw1.generate_interfaces('Fa', 10) In [12]: sw1.interfaces Out[12]: ['Fa1', 'Fa2', 'Fa3', 'Fa4', 'Fa5', 'Fa6', 'Fa7', 'Fa8', 'Fa9', 'Fa10'] 

self

self — это стандартное имя первого аргумента для методов объекта.

На заметку

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

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

В ходе исполнения метода объекта в первом аргументе автоматически окажется экземпляр класса (передевать его специально не требуется).

 class MyClass:

def say(self):
print(self)


my_1 = MyClass() # Создаём объект класса.
my_1.say() #

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

 MyClass.say(my_1) #

Если передать в несвязанный [с объектом] метод класса объект, тип которого не совпадает с типом класса, в котором определён метод, поведение в Python 3 отличается от Python 2. Смотрите пример ниже.

 MyClass.say('нечто') 
# Python 3: нечто
# Python 2: TypeError: unbound method say() must be called with MyClass instance as first argument (got str instance instead)

Python. Что такое self, наследование и с чем их едят?

Что же такое self, как работает передача определенных значений переменных между функциями и как это все между собой работает? Дело в том, что я задался целью написать небольшую текстовую RPG игру, в целях преодоления на своем пути определенного ряда трудностей и расширения своих знаний касательно ООП. Набросав небольшой макет действий, я принялся к его реализации. Использовать я решил библиотеку tkinter, в целях отрисовки графической составляющей игры и столкнулся со следующей проблемой. При попытке запуска моего кода, я столкнулся с ошибкой, что будет описана под ним.

Main.py ------- from tkinter import * from Constants import * class Main(): def __init__(self): # Отрисовка окна и его параметры self.root = Tk() self.root.title('Hero dash') self.root.geometry(geometry_size) self.running = True self.root.resizable(False,False) def render(self): root.configure(background='#f23f23') def main_loop(self): # Основной цикл игры while self.running == True: root.render() root.mainloop() Main.main_loop() --------------------------- Constants.py ------------ geometry_size = '800x600+250+40' 

А вот и код ошибки.

TypeError: main_loop() missing 1 required positional argument: 'self' 

Как я понял, беда в нехватке аргументов, которые я передаю в функцию, при попытке её вызова. Но у меня возник вопрос, а что же вообще такое эта ‘self’ и для чего она используется, какие значения может принимать и каким образом я могу воспользоваться root в других функциях? Имеется в виду, как её значение «внедрить» в другую функцию?

Что означает self в Python?

Язык программирования Python

В Python self является причиной многих проблем для разработчиков, которые занимаются объектно-ориентированным программированием, давайте попробуем разобраться в этом вопросе!

Когда я начал всерьез интересоваться Python и объектно-ориентированным программированием, я никак не мог понять одну вещь: self.

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

Очень важно, чтобы вы понимали, что означает это “self” и почему оно полезно при разработке на Python.

Это ключевое понятие в объектно-ориентированном программировании, которое вам необходимо понять!

Создадим класс

Допустим, вы фанат велоспорта и хотите создать программу для борьбы с вашей всепоглощающей зависимостью от облегающих спортивных шорт:

class Velo: wheels = 2 def __init__(self, brand, price, weight): self.brand = brand self.price = price self.weight = weight velo = Velo(self="Peugeot", price=500, weight=100)

Для начала я напомню вам разницу между переменной экземпляра и переменной класса, чтобы вам было понятнее:

Переменные класса – это переменные, которые являются общими для всех экземпляров вашего класса.

В нашем классе Velo переменная wheels является переменной класса.

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

Мы определяем их внутри класса, но вне всех остальных методов!

Примечание. Внутри класса мы говорим уже не о функциях, а о методах.

С другой стороны, у нас есть переменные экземпляра, значения которых отличаются от экземпляра к экземпляру.

В нашем примере переменные self.brand, self.price и self.weight являются переменными экземпляра.

Как вы можете видеть, они определяются внутри метода init.

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

Поэтому вы должны вложить все, что свойственно объекту, который вы хотите создать.

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

class Velo: wheels = 2 def __init__(self, brand, price, weight): self.brand = brand self.price = price self.weight = weight velo_01 = Velo("btwin", 250, 15) velo_02 = Velo("rockrider", 170, 12) print(velo_01.wheels) # 2 print(velo_02.wheels) # 2 print(velo_01.brand) # btwin print(velo_02.brand) # rockrider'

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

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

В чем цель self?

Когда я создавал свой метод init, вы заметили, что в дополнение к параметрам я добавил слово self.

Я также использовал его для определения переменных экземпляра.

Self используется для представления экземпляра класса! Благодаря ему я могу получить доступ к атрибутам и методам своего класса.

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

class Velo: wheels = 2 def __init__(self, brand, price, weight): self.brand = brand self.price = price self.weight = weight def drive(self): print("Лучший велосипед: <> !".format(self.brand)) velo_01 = Velo("btwin", 250, 15) velo_02 = Velo("rockrider", 170, 12) print(velo_01.wheels) # 2 print(velo_02.wheels) # 2 print(velo_01.brand) # btwin print(velo_02.brand) # rockrider velo_01.drive() # Лучший велосипед: btwin ! velo_02.drive() # Лучший велосипед: rockrider !

Я создал метод drive в классе Velo и указал self в качестве первого параметра:

def drive(self): print("Лучший велосипед: <> !".format(self.brand))
Code language: PHP (php)

Поэтому я могу вызвать этот метод drive на всех созданных мною экземплярах.

Примечание. Обратите внимание, что вам не нужно явно использовать слово self, поскольку оно не является зарезервированным словом в Python. Если вы пришли из другого языка программирования, например, JavaScript, вам, возможно, привычнее это использовать. Поэтому вы можете использовать Maria вместо self, и это будет работать точно так же.

В Python мы традиционно используем слово self, но вы можете поступать так, как хотите (мы не советуем, даже если нам нравится Мария )!

С другой стороны, есть правило, которое вы должны соблюдать абсолютно точно:

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

Секрет self

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

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

Я думаю, вы поняли, это все self!

Когда я это делаю:

velo_01.drive()
Code language: CSS (css)

Вот что происходит за кулисами:

Velo.drive(velo_01)
Code language: CSS (css)

Интерпретатор Python автоматически выполняет “преобразование” за вас!

С одной стороны, это делает ваш код более эстетичным, а с другой – облегчает жизнь, когда вы хотите наследовать свой класс от других классов.

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

def drive(): print("Лучший велосипед: <> !".format(self.brand)) velo_01.drive() #TypeError: drive() takes 0 positional arguments but 1 was given
Code language: CSS (css)

Эта ошибка часто непонятна людям, не привыкшим к объектно-ориентированному программированию.

Python сообщает нам, что методу drive был передан аргумент (1 was given), однако, если посмотреть на наш код, мы не передаем никакого аргумента.

velo_01.drive()
Code language: CSS (css)

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

Итак, аргумент передается методу drive, просто вы этого не видите, и это делаете не вы, Python сам об этом позаботится.

# Используем метод drive для экземпляра velo_01.drive() # Это то же самое, что пройти через класс и передать экземпляр Velo.drive(velo_01)
Code language: CSS (css)

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

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

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