Что означает инструкция: self.__set_x(x)?
Мне не понятен смысл инструкции self.__set_x(x). По всем канонам это должна быть операция присваивания т.е. self.__set_x = x. Вот полный код и он работает:
class Data: def __init__(self, x): self.__set_x(x) def __get_x(self): print("Get X") return self.__x def __set_x(self, x): self.__x = x print("Set X") x = property(__get_x, __set_x)
Отслеживать
4,925 6 6 золотых знаков 11 11 серебряных знаков 29 29 бронзовых знаков
задан 7 июн 2022 в 2:55
Айдар Абдуллин Айдар Абдуллин
23 6 6 бронзовых знаков
Это называется сеттер и геттер. Почитайте про них.
7 июн 2022 в 3:05
Я прекрасно знаю что такое сеттер и геттер. Но я нигде (!) не нашел их сочетание с — х(х) — maestro 🙂
7 июн 2022 в 3:59
А как же по вашему должны быть описаны сеттеры и геттеры в классе? Они именно в виде специальных методов и описываются
7 июн 2022 в 4:50
Есть три способа: 1. Обычный 2. Через декоратор 3. Через функцию-декоратор — это мой случай. В лит. описана инициализация как self.__x = x . А у меня стоит self.__set_x(x). Мне не понятно и я не могу найти ответа. Помоги если можешь.
7 июн 2022 в 5:02
Айдар, вопрос, скорее, откуда такой код взялся, и зачем он такой? Остальное — в ответе.
7 июн 2022 в 5:19
3 ответа 3
Сортировка: Сброс на вариант по умолчанию
Давайте попробую описать на примере. Ниже ваш код и пара строк вызова вашего класса Data
class Data: def __init__(self, x): self.__set_x(x) def __get_x(self): print("Get X") return self.__x def __set_x(self, x): self.__x = x print("Set X") x = property(__get_x, __set_x) myx = Data( 1 ) print( myx.x )
Если запустить эту программу, то мы увидим такой результат
Set X Get X 1
self.__set_x(x) в конструкторе класса вызывает собственную функцию установки переменной икс x
Вместо этого, наверное, можно было написать прямо в конструкторе
Но нет. При попытке такого присваивания получаем ошибку
Traceback (most recent call last): File "main.py", line 17, in print( myx.x ) File "main.py", line 8, in __get_x return self.__x AttributeError: 'Data' object has no attribute '_Data__x'
Потому что __set_x это не переменная и в неё ничего нельзя присваивать. __set_x — это функция или метод, а значит мы должны передать в неё значение, вызывав эту функцию и открыть круглые скобки, т.е. вот так self.__set_x( x )
Отслеживать
ответ дан 7 июн 2022 в 5:33
593 5 5 серебряных знаков 16 16 бронзовых знаков
Как же я не догадался, что это вызов собственной(!) функции. и только ради того, чтобы запустить print(‘Set X’). Питон 🙂
7 июн 2022 в 7:29
кроме print(‘Set X’) она же ещё и саму переменную устанавливает __x = x 🙂
8 июн 2022 в 8:05
Айдар, к «как не догадался?» — надо было либо на бумажке посмотреть, как работает, либо в отладчике. И увидели бы.
8 июн 2022 в 17:58
Разницы большой нет. self.__set_x(x) вызывает как раз «литературный» self.__x = x из метода класса. Если в отладчике по шагам идти, то видно, как ведёт себя класс.
Например, код ниже с обращением к классу:
a = Data(5)
даст на выходе: «Set X». Идя в отладчике по шагам, мы модем видеть, что после обращения к классу в строке выше далее мы попадаем в __init__(self, x) , который сразу вызывает метод класса __set_x(self, x) , где и срабатывает self.__x = x .
Отслеживать
ответ дан 7 июн 2022 в 5:21
4,925 6 6 золотых знаков 11 11 серебряных знаков 29 29 бронзовых знаков
Если ответ был полезным, его можно отметить плюсом (нажать треугольник вверх слева от вопроса). Если ответ полностью решил задачу — принять ответ (нажать на галку под треугольниками слева). Можно и то, и другое, если сильно понравилось:-)
7 июн 2022 в 5:24
Ну просто при таком способе описания геттера и сеттера у вас есть в явном виде метод __set_x , так почему его нельзя вызвать при инициализации?
При более традиционном методе описания геттера и сеттера они получаются скрытыми, в явном виде методы геттера и сеттера не видимы как отдельные методы, поэтому их и не используют как методы.
В целом, конечно, питон довольно гибок и многое в нём можно делать разными способами. И тут мы видим как-раз такой пример. Но на мой взгляд геттеры и сеттеры как отдельные методы особого смысла не имеют и такой способ их описания лучше не использовать.
Что такое self в Python?
Совсем непонятно, что такое self. Понятно, что его по умолчанию нужно писать как первый параметр описании каждого метода. То есть определение уже наизусть выучил, но трудно понять что оно значит. Вроде никаких затруднений пока что ни с чем больше нет, только с этим. Уже давно ищу, что это такое.
- Вопрос задан более трёх лет назад
- 119915 просмотров
Комментировать
Решения вопроса 1
Легко нагуглил.
stackoverflow.com/a/21366809/3307167 — по мне так самый понятный вариант.
stackoverflow.com/a/31096552/3307167 — а тут картиночки даже есть, для лучшего понимания.
Ответ написан более трёх лет назад
Нравится 10 9 комментариев
444 @444 Автор вопроса
Не совсем понял. Может перевел неправильно.
444 @444 Автор вопроса
То есть вместо self всегда представлять себе объект?
class A: def test(self, a): self.a = a MyObject = A() MyObject.test(10) # A.test(MyObject, 10) -> MyObject.a = 10
444: а вообще, лучше представлять self как self. Ссылка на себя внутри объекта.
444 @444 Автор вопроса
А все понятно.
444 @444 Автор вопроса
444: пожалуйста 🙂
444 @444 Автор вопроса
Defman21: да я примерно так и думал всегда только очень сильно сомневался, я просто немного тупой.
444 @444 Автор вопроса
444: То есть не «немного».
Ответы на вопрос 8
Объяснение self в python:
dog: у котов внутри есть мурчалка
dog: она реализована для всех котов в классе кот
dog: в объекте кот надо как то вызвать метод мурчало у класса кот
dog: как ты это сделаешь?
dog: кот.мурчало()
dog: ежели ты вызовешь кот.мурчало(), муркнут сразу все коты на свете
dog: а ежели ты вызовешь self.мурчало(), муркнет только тот кот, на которого указывает self
Ответ написан более трёх лет назад
Нравится 61 5 комментариев
Я бы заменил кот на мурзик. типа того:
dog: у котов внутри есть мурчалка
dog: она реализована для всех котов в классе кот
dog: в объекте мурзик надо как то вызвать метод мурчало у класса кот
dog: как ты это сделаешь?
dog: кот.мурчало()
dog: ежели ты вызовешь кот.мурчало(), муркнут сразу все коты на свете
dog: а ежели ты вызовешь self.мурчало(), муркнет только тот кот, на которого указывает self — т.е. мурзик ))
ты гений:) Огромное спасибо.
объяснил настолько хорошо, что даже тот кто не программирует поймет как работает self. Спасибо)
Вадим, Вам бы Мурзилку издавать по ООП 🙂
а ежели вызовешь @staticmethod мурчало(), то муркнет кошачий дух представитель всех котов
Константин Довнар @SolidlSnake
Ваш дружелюбный сосед
Аналог слова this из других языков.
В Python «Явное лучше неявного» поэтому его необходимо задавать так конкретно.
Ссылается на конкретный экземпляр класса, а не на класс в целом.
Ответ написан более трёх лет назад
Нравится 7 1 комментарий
444 @444 Автор вопроса
Ну я про this знаю, потому и написал, что думал тоже самое только сомневался, но спасибо за ответ.
self — это ни в коем случае не зарезервированное слово. Это просто название переменной.
В методах класса первый параметр функции по соглашению именуют self, и это ссылка на сам объект этого класса. Но это именно соглашение. Вы вольны называть параметры как угодно.
Зачем это нужно?
Ну вот есть объект и вы хотите создать/изменить поле у этого объекта из метода этого самого объекта.
class Human: def __init__(self): self.blood = 7000 def add_blood(self, volume): self.blood += volume
Ответ написан более трёх лет назад
Нравится 6 2 комментария
self помогает методу определить к какому объекту он относиться ?
Да, self — это и есть этот объект.
Vovanchick @Vovanchick
И все равно ничего не понятно
Ответ написан более трёх лет назад
Нравится 4 2 комментария
что не понятно?!
class Human: def __init__(self): self.blood = 7000 def add_blood(self, volume): self.blood += volume
Здесь создается своя переменная blood в каждом объекте, который создан по шаблону класса Human.
Иначе получишь только одну глобальную переменную для всех и вся:
class Human: def __init__(): blood = 7000 def add_blood(volume): blood += volume
Поэтому важно поучить строготипизированные языки, чтобы понимать что реально происходит, кто кому принадлежит.
Помогите не понимаю ничего
Я думаю, для понимания self нужно обратиться к static.
Я далее буду называть поля класса просто переменными класса.
В языке Object Pascal приписка self приписывается автоматически (неявно) к переменным класса. То есть её ставить не надо.
Можно рассматривать класс, как табличку с инструкцией для создания объектов и придания им свойств. Если перед переменой (полем) класса ничего не стоит, значит перед ней неявно присутствует self (в Object Pascal). Такая переменная НЕ меняется в классе (табличке с инструкцией), а присваивается конкретному объекту. То есть такая self переменная в классе (табличке с инструкцией) не изменяется. Чтобы переменная изменилась и в самом классе, нужно перед переменной поставить static. И она будет меняться уже и в самом классе (на той самой пресловутой табличке с инструкцией). Static используют, например, для подсчёта количества созданных объектов. Для этого к static переменной при создании объекта попросту добавляют 1 (единичку). Через конструктор, например. Каждый новый объект будет в результате своего создания добавлять к static переменной ещё одну единичку.
Но это в Object Pascal.
А в Python всё почти что наоборот. Все переменные (поля) класса изначально статичные static (неявно). А чтобы переменную сделать динамической (переменной объекта) то есть self, её просто нужно задать в каком-нибудь методе класса в аргументах. Метод _init_, мне кажется, подойдёт. И назвать, так чтобы она отражала свою сущность – ‘self’ или ‘my_object ‘ (отсылка, что переменная изменяется в объекте, а не в самом классе)
Ответ написан более года назад
Комментировать
Нравится 1 Комментировать
Автор вопроса, плиз ответь мне, таже самая проблема что и у тебя, не понимаю как этот self работает (((
Ответ написан более трёх лет назад
Simon_Says492 @Simon_Says492
На сколько я понимаю, self — это, своего рода, ссылка на объект. Объект — это экземпляр класса (пример ниже).
class KOT(): def __init__(self, name): self.name = name def muur(self): print(self.name, 'мурчит: мур мур') Matroskin = KOT('Матроскин') # это и есть объект (экземпляр класса) Matroskin.muur() # т.е если я сам, все правильно понял, то self становится Matroskin-ым
Грубо говоря, мы сделали Matroskin-а — главным героем нашего класса. Записали в его паспорт имя «Матроскин». И потом, он обратился к своему навыку muur, чтобы помурлыкать)
Ярослав @Yareeek192
self — это обращение именно к объекту,
class Human:
def __init__(self):
self.blood = 7000
self — выступает простым обращением к объекту.
x.blood = 7000 — можно присвоить конкретно этому объекту любое другое значение, например: x.blood = 6500.
соответсвенно и при вызове оно будет изменено
можно ничего не менять и если просто написать, то оно выдаст значение по умолчанию.
>>>x.blood
7000
Ответ написан более года назад
Комментировать
Нравится Комментировать
kosta_skull @kosta_skull
Была та же проблема. Я понял для себя так:
Как мы знаем, для вызова метода необходим такой синтаксис:
something.my_method(a, b, . )
где something — это объект класса MyClass.
Когда мы описываем(создаем) класс MyClass, в котором нам нужно прописать метод my_method, то мы пишем
class MyClass: def my_method(self, a, b, . ):
при этом self — это способ получить данные из той переменной, к которой этот метод применяют. В таких переменных лежат объекты с определенным атрибутами. В нашем примере, это объект, хранящийся в переменной something. То есть, первый параметр при описании нового метода — это место для указания переменной-объекта, к которому этот метод будут применять. Мы создали объект something, и self для этого объекта превратилась в something.
По этой причине мы можем вызвать тот же метод другим синтаксисом:
MyClass.my_method(something, a, b, . )
Результат будет такой же, как и при
Следующий слой понимания и ответа на вопрос: А зачем?
Допустим, у нашего объекта есть атрибут age, хранящий какое-то численное значение (например, 3). Это значение сделаем общим для всех создаваемых объектов этого класса. Мы хотим, чтобы написанный нами метод брал это значение и умножал на 2. Делаем мы это так
class MyClass: age = 3 def my_method(self): return self.age * 2
Теперь создадим объект something класса MyClass и посмотрим, чему равен атрибут age
something = MyClass() print(something.age) #Вывод: 3
Теперь посмотрим результат работы нашего метода
print(something.my_method()) #Вывод: 6
Теперь при вызове something.my_method() будет возвращено значение something.age*2, то есть 3*2=6
Мы во второй строке указали age = 3. Значение атрибута age будет в этом случае равнятся 3 для всех объектов этого класса, которые мы будем создавать. Но что, если мы хотим указывать age отдельно для каждого объекта?
Есть специальный метод __init__. Именно с таким именем. Напишете по-другому — не сработает. Он пишется в самом начале описания класса и его параметры задаются в скобках при создании объекта, то есть, вызов этого метода включен в процесс создание объекта класса автоматически. Сейчас на примере. Допустим, мы хотим, чтобы в нашем объекте было два атрибута: age, len. Атрибут age мы будем указывать при создании класса, а len будет считаться автоматически, и будет равен age*2.
class MyClass: def __init__(self, age): self.age = age self.len = age*2
теперь нам нужно будет при создании объекта something задать параметр age:
чему равны атрибуты age и len?
print(something.age) print(something.len) #Вывод: #6 #12
При создании объекта класса, синтаксис
something = MyClass(a, b, . )
работает аболютно так же, как
MyClass.__init__(something, a, b, . )
Сам новичок в ООП, так что могу что-то не так понять и вообще написать не сработающий код, так что жду комментов и предложений
Методы классов. Параметр self
Мы продолжаем изучать ООП языка Python. Как я говорил на первом занятии, класс может содержать свойства (данные) и методы (функции). Благодаря методам внутри класса можно реализовывать самые разные алгоритмы, то есть методы – это действия. Именно поэтому, в названиях методов используют глаголы, например:
set_value, get_param, start, stop, и т.п.
В то время как именами свойств (данных) выступают существительные:
color, size, x, y, и т.п.
Рекомендуется придерживаться этого простого правила.
Давайте, для примера объявим метод set_coords в классе Point, который будет просто выводить в консоль сообщение «вызов метода set_coords»:
class Point: color = 'red' circle = 2 def set_coords(self): print("вызов метода set_coords")
Здесь сразу бросается в глаза вот этот параметр self, который автоматически прописывает интегрированная среда. Зачем он здесь, если мы пока ничего не собираемся передавать этому методу? Давайте его уберем! Пока никаких проблем не возникло. Мало того, мы можем его вызвать из класса Point:
Point.set_coords()
и все будет работать без ошибок. Здесь мы видим, как вызываются методы класса. Все довольно очевидно. Записываем имя класса (Point), и через точку указываем имя метода. В конце обязательно прописываем круглые скобки, так как это оператор вызова функций. И, так как метод – это функция класса, то для вызова метода используется тот же оператор, что и для вызова функций.
В результате, мы получили класс, в котором два свойства и один метод. Далее, создадим экземпляр этого класса:
pt = Point()
И, как мы с вами говорили, через объект pt можно обращаться ко всем атрибутам класса Point, в том числе и к методу set_coords:
pt.set_coords
Этот атрибут ссылается на объект-функцию, которую мы определили в классе Point. Попробуем ее вызвать:
pt.set_coords()
Видим ошибку, что в метод set_coords при вызове передается один аргумент, а он у нас определен без параметров. Дело в том, что когда мы вызываем методы класса через его объекты, то интерпретатор Python автоматически добавляет первым аргументом ссылку на объект, из которого этот метод вызывается.
Поэтому, если мы хотим внутри класса определить метод, который можно было бы вызывать из его экземпляров, то дополнительно прописывается первый параметр, обычно, с именем self:
class Point: color = 'red' circle = 2 def set_coords(self): print("вызов метода set_coords " + str(self))
Еще раз, параметр self будет ссылаться на экземпляр класса, из которого вызывается метод. Зачем это надо? Сейчас узнаете. После этого дополнения мы уже не сможем вызвать данный метод через класс без указания первого аргумента:
Point.set_coords()
но можем через его объекты:
pt.set_coords()
То есть, когда метод вызывается через класс, то Python автоматически не подставляет никаких аргументов. А когда вызов идет через экземпляры класса, то первый аргумент – это всегда ссылка на экземпляр. Данный момент нужно знать и помнить.
Но мы все же можем вызвать метод set_coords и через класс, если явно передадим ссылку на объект pt, следующим образом:
Point.set_coords(pt)
Именно это на автомате делает Python, когда вызов осуществляется через объекты классов.
Так зачем понадобилось такое поведение? Дело в том, что метод класса – это тоже его атрибут и когда создаются экземпляры класса, то метод становится общим для всех объектов и не копируется в них. Фактически, только благодаря параметру self мы «знаем» какой объект вызвал данный метод и можем организовать с ним обратную связь.
Например, пусть метод set_coords задает координаты точек для текущего объекта. Тогда, мы пропишем в нем два дополнительных параметра и через self в самом экземпляре класса создадим (либо переопределим) два свойства:
class Point: color = 'red' circle = 2 def set_coords(self, x, y): self.x = x self.y = y
В результате, при вызове метода:
pt.set_coords(1, 2) print(pt.__dict__)
в объекте pt будут созданы два свойства x, y со значениями 1 и 2. Вот для чего нужен этот параметр self. Если в программе создать еще один объект:
pt2 = Point()
и через него вызвать тот же самый метод:
pt2.set_coords(10, 20) print(pt2.__dict__)
То увидим, что свойства x, y со значениями 10 и 20 были созданы только в нем (в его пространстве имен) и никак не связаны с координатами другого объекта pt или классом Point. То есть, через self мы работаем с конкретным объектом, из которого был вызван данный метод.
Конечно, в классах мы можем прописывать произвольное количество методов. Например, определим еще один, который будет возвращать координаты точки в виде кортежа значений:
class Point: color = 'red' circle = 2 def set_coords(self, x, y): self.x = x self.y = y def get_coords(self): return (self.x, self.y)
И ниже в программе можем вызвать его:
print(pt.get_coords())
Интересно, что так как имя метода – это атрибут класса, то мы можем обратиться к нему через знакомую нам уже функцию:
res = getattr(pt, 'get_coords') print(res)
Видим, что это ссылка на объект-функцию. А раз так, то ничто нам не мешает ее здесь вызывать:
print(res())
Конечно, так делают очень редко. Обычно используют синтаксис через точку. Я привел это, чтобы еще раз подчеркнуть, что имена методов – это те же самые атрибуты, просто они ведут не на данные, а на функции. Во всем остальном они схожи с атрибутами-данными класса.
Заключение
Итак, на этом занятии вы должны были узнать, как определяются простые методы класса, за что отвечает параметр self и как происходит обращение к методам и их вызов. Если все это понятно, то смело переходите к следующему занятию, где мы продолжим эту тему.
Видео по теме
Концепция ООП простыми словами
#1. Классы и объекты. Атрибуты классов и объектов
#2. Методы классов. Параметр self
#3. Инициализатор __init__ и финализатор __del__
#4. Магический метод __new__. Пример паттерна Singleton
#5. Методы класса (classmethod) и статические методы (staticmethod)
#6. Режимы доступа public, private, protected. Сеттеры и геттеры
#7. Магические методы __setattr__, __getattribute__, __getattr__ и __delattr__
#8. Паттерн Моносостояние
#9. Свойства property. Декоратор @property
#10. Пример использования объектов property
#11. Дескрипторы (data descriptor и non-data descriptor)
#12. Магический метод __call__. Функторы и классы-декораторы
#13. Магические методы __str__, __repr__, __len__, __abs__
#14 Магические методы __add__, __sub__, __mul__, __truediv__
#15. Методы сравнений __eq__, __ne__, __lt__, __gt__ и другие
#16. Магические методы __eq__ и __hash__
#17. Магический метод __bool__ определения правдивости объектов
#18. Магические методы __getitem__, __setitem__ и __delitem__
#19. Магические методы __iter__ и __next__
#20. Наследование в объектно-ориентированном программировании
#21. Функция issubclass(). Наследование от встроенных типов и от object
#22. Наследование. Функция super() и делегирование
#23. Наследование. Атрибуты private и protected
#24. Полиморфизм и абстрактные методы
#25. Множественное наследование
#26. Коллекция __slots__
#27. Как работает __slots__ с property и при наследовании
#28. Введение в обработку исключений. Блоки try / except
#29. Обработка исключений. Блоки finally и else
#30. Распространение исключений (propagation exceptions)
#31. Инструкция raise и пользовательские исключения
#32. Менеджеры контекстов. Оператор with
#33. Вложенные классы
#34. Метаклассы. Объект type
#35. Пользовательские метаклассы. Параметр metaclass
#36. Метаклассы в API ORM Django
#37. Введение в Python Data Classes (часть 1)
#38. Введение в Python Data Classes (часть 2)
#39. Python Data Classes при наследовании
© 2023 Частичное или полное копирование информации с данного сайта для распространения на других ресурсах, в том числе и бумажных, строго запрещено. Все тексты и изображения являются собственностью сайта
X self что значит
Всем привет, знающие расскажите пожалуйста подробнее эту строку.
Self.x-10*dt
Таким событием скролю всю сцену. Но не до конца понимаю что к чему.
1. Для чего нужен self (я знаю что он двигает объект, но каким образом)
2. Для чего нужно умножать на delta time (dt)
И как лучше будет и правильнее писать просто: self.x-10 или все же: self.x-10*dt
Если лучше то почему?)
Спасибо:)
Последний раз редактировалось EksPRO 03 мар 2016, 13:54, всего редактировалось 1 раз.
Сообщений: 364 Я тут с 14 мар 2015 Репутация 5 [ ? ]
эмм.. по сути self — это обозначение объекта. т.е. при выборе действия для объекта мячик, можно писать не мячик .х, мячик .у, мячик .angle, а просто: self .x, self .y, self .angle
TimeDelta — это время за которое проходит один тик. т.е. время прогонки скрипта сверху до низу
Сообщений: 2957 Я тут с 19 дек 2012 Откуда: Новый Уренгой Репутация 331 [ ? ]
EksPRO , self.x-10 и self.x-10*dt будут разные скорости
«dt — ПРОСТО ЧИСЛО. Это время с момента смены одного кадра до следующий смены. Оно зависит от мощности процессора.
FPS, кстати, можно вот так посчитать: 1/dt.»
Последний раз редактировалось Developed 03 мар 2016, 13:42, всего редактировалось 1 раз.
Сообщений: 619 Я тут с 04 фев 2014 Репутация 147 [ ? ]
Величина dt напрямую зависит от фпс. При 60фпс dt=0,016. Обычно, её используют в виде: EveryTick: set Object.X to Object.X+1*60*dt — чтобы независимо от фпс объект двигался с одинаковой скоростью визуально
Сообщений: 2957 Я тут с 19 дек 2012 Откуда: Новый Уренгой Репутация 331 [ ? ]
EksPRO , dt, как сказал mef1sto, это время на 1 тик. Равно оно 1/60, при fps равном 60. Если fps падает, то, соответственно увеличивается dt. Если из-за чего-то упадет fps, при использовании dt, объект пройдет то же самое расстояние и не произойдет рывка.
Фактически 10*dt означает 10 пикселей в секунду (повторюсь, независимо от скорости выполнения)
Сообщений: 1283 Я тут с 10 фев 2013 Откуда: Челябинск / Екатеринбург Двиг: C2.r241 Лицензия: Personal VK: vyntershtoff Репутация280 [ ? ]
- Сайт
Всем спасибо за такое обширное объяснение) теперь все ясно.
Сообщений: 364 Я тут с 14 мар 2015 Репутация 5 [ ? ]
Сообщений: 6 • Страница 1 из 1
Сейчас эту тему просматривают
Зарегистрированные пользователи: нет зарегистрированных пользователей
- Список форумов
- Наша команда • Удалить cookies конференции • Часовой пояс: UTC + 3 часа