Подтвердить что ты не робот

Язык Python: атрибуты объекта() vs Функция

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

>>> a = object()
>>> a.hhh = 1

throws

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'object' object has no attribute 'hhh'

Однако для объекта функции это нормально.

>>> def f():
...   return 1
...
>>> f.hhh = 1

В чем обоснование этой разницы?

4b9b3361

Ответ 1

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

Чтобы поддерживать атрибуты произвольного экземпляра, тип должен предоставлять каждому из своих экземпляров __dict__, что не имеет большого значения для функций (которые никогда не являются крошечными объектами в любом случае), но вполне возможно, что для других объектов, крошечный. Сделав тип object таким же легким, как мы могли, а также предоставив __slots__, чтобы избежать исключения в каждом экземпляре __dict__ в подтипах object, мы поддерживали небольшие специализированные типы значений, насколько это возможно.

Ответ 2

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

class myobject(object):
    pass

o = myobject()
o.anything = 123

Или более эффективный (и лучше документированный), если вы знаете атрибуты:

class myobject(object):
    __slots__ = ('anything', 'anythingelse')

o = myobject()
o.anything = 123
o.anythingelse = 456

Ответ 3

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

Подумайте о object как временном взломе, наводящем типы и классы старого стиля. В Python 3.0 он будет исчезать в неизвестность, потому что он больше не будет использоваться как часть

class Foo( object ):
    pass

f = Foo()
f.randomAttribute = 3.1415926

Ответ 4

Вот еще одна альтернатива, как можно короче:

>>> dummy = type('', (), {})()
>>> dummy.foo = 5
>>> dummy.foo
5