Является ли объявление переменной класса таким же, как объявление в методе __new__?

Я хотел бы знать, эквивалентны ли два подхода:

Подход 1

class A:
    toto = 1

по сравнению с подходом 2:

class A:
   def __new__(cls, *args, **kwargs):
       cls.toto = 1
       return super().__new__(cls, *args, **kwargs)

Для меня они выглядят одинаково. В частности, печать dir(A) дает тот же результат:

['__class__',
 '__delattr__',
 '__dict__',
 '__dir__',
 '__doc__',
 ...
 'toto']

Спасибо

Ну, не точно то же самое, делая это в __new__ делает это каждый раз, когда вы создаете экземпляр объекта A. Итак, предположим, что вы делаете A(); A.toto = 10; A(); print(A.toto), он напечатает 1, но если вы сделаете с подходом 1, A(); A.toto = 10; A(); print(A.toto) он напечатает 10

juanpa.arrivillaga 22.04.2022 21:23

Кроме того, примечание по терминологии: Python на самом деле не использует объявления переменных имеют, если только вы не имеете в виду аннотации типов, которые работают таким образом, или global/nonlocal. Но эти два — частные случаи. В общем, вы никогда не объявляете переменные в Python. Вы просто определяете их, и они появляются без объявления

juanpa.arrivillaga 22.04.2022 21:24
3 метода стилизации элементов HTML
3 метода стилизации элементов HTML
Когда дело доходит до применения какого-либо стиля к нашему HTML, существует три подхода: встроенный, внутренний и внешний. Предпочтительным обычно...
Формы c голосовым вводом в React с помощью Speechly
Формы c голосовым вводом в React с помощью Speechly
Пытались ли вы когда-нибудь заполнить веб-форму в области электронной коммерции, которая требует много кликов и выбора? Вас попросят заполнить дату,...
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Будучи разработчиком веб-приложений, легко впасть в заблуждение, считая, что приложение без JavaScript не имеет права на жизнь. Нам становится удобно...
Flatpickr: простой модуль календаря для вашего приложения на React
Flatpickr: простой модуль календаря для вашего приложения на React
Если вы ищете пакет для быстрой интеграции календаря с выбором даты в ваше приложения, то библиотека Flatpickr отлично справится с этой задачей....
В чем разница между Promise и Observable?
В чем разница между Promise и Observable?
Разберитесь в этом вопросе, и вы значительно повысите уровень своей компетенции.
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Клиент для URL-адресов, cURL, позволяет взаимодействовать с множеством различных серверов по множеству различных протоколов с синтаксисом URL.
2
2
23
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Нет, это не эквивалентно.

Подход 1 устанавливает только переменную класса однажды. Подход 2 устанавливает его, возможно, 0 или столько раз, сколько раз вы создаете экземпляр объекта A.

Рассмотрим простейший случай:

>>> class A:
...     toto = 1
...
>>> print(A.toto)
1

Однако:

>>> class A:
...    def __new__(cls, *args, **kwargs):
...        cls.toto = 1
...        return super().__new__(cls, *args, **kwargs)
...
>>> print(A.toto)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: type object 'A' has no attribute 'toto'

Теперь рассмотрим более сложный случай:

>>> class A:
...     toto = 1
...
>>> a = A()
>>> A.toto = 42
>>> a = A()
>>> print(A.toto)
42

Однако:

>>> class A:
...    def __new__(cls, *args, **kwargs):
...        cls.toto = 1
...        return super().__new__(cls, *args, **kwargs)
...
>>> a = A()
>>> A.toto = 42
>>> a = A()
>>> print(A.toto)
1

Привет. То же самое относится и к закрытым переменным в классе? Пример: class A: __toto = 1

High-Octane 22.04.2022 21:45

@High-Octane, поэтому в Python на самом деле нет «частных» переменных. __toto = 1 превратит имя искажено внутри определения класса в _A__toto, но, если не считать этого искажения, все будет работать точно так же. Например. class A: __toto = 1, но тогда снаружи A._A__toto = 42; A(); print(A._A__toto) будет вести себя так же

juanpa.arrivillaga 22.04.2022 21:48

Понял, спасибо!

High-Octane 22.04.2022 21:50

Другие вопросы по теме