Прежде всего, __setattr__
def не требуется:
>>> class MyList(list):
... pass
>>> MyList.hack = 'haha'
>>> x = MyList()
>>> x.hack
'haha'
Вы добавляете атрибут не к экземпляру (x
), а к классу (MyList
). (В некоторых языках есть ключевое слово static
для этих атрибутов (C ++, Java, PHP, ...).)
Это примерно эквивалентно:
>>> class MyList(list):
... hack = 'haha' # class attribute, ie. "static"
>>> x = MyList()
>>> x.hack
'haha'
Обратите внимание, что это не имеет ничего общего с предварительной / последующей инициализацией:
>>> class MyList(list):
... hack = 'haha'
>>> x = MyList()
>>> MyList.hack2 = 'hehe' # post init
У вас есть:
>>> x.hack
'haha'
Но также:
>>> x.hack2
'hehe'
Подводя итог, в Python:
- вы можете добавить атрибуты класса после определения класса;
- если
x
является экземпляром C
и attr
атрибутом C
, то x.attr
эквивалентно C.attr
.
Для записи вы можете предотвратить это гибкое поведение с помощью метакласса:
>>> class MyListMeta(type):
... def __setattr__(self, name, value):
... raise AttributeError()
>>> class MyList(list, metaclass=MyListMeta):
... hack = 'haha'
Как и ожидалось:
>>> x = MyList()
>>> x.hack
'haha'
Но теперь:
>>> MyList.hack2 = 'hehe'
Traceback (most recent call last):
...
AttributeError
Обратите внимание, что вы также не можете установить существующие атрибуты:
>>> MyList.hack = 'hehe'
Traceback (most recent call last):
...
AttributeError
Примечания:
- Не делайте этого, если вы не знаете, что делаете.
- Не используйте это для защиты ваших классов: это поведение можно легко обойти и добавить атрибуты класса.
Резюме из замечаний: не делать это .