В Python разница в __dict__ между object() и классом MyClass (объект)

#python

#python

Вопрос:

Я возился с динамическими атрибутами и заметил, что не смогу использовать атрибут __dict__, если я создам объект непосредственно из класса object(), но если я создам новый класс, который является прямым потомком object, я смогу получить доступ к атрибуту __dict__. В чем разница?

Примеры:

 # This gives an AttributeError  
o = object()
o.__dict__
  
 # This works: prints {}
class myClass(object):
    pass
o = myClass()
o.__dict__
  

Комментарии:

1. Возиться с __dict__ напрямую почти всегда не нужно и плохая идея. Название динамических атрибутов обычно лучше оформлять как ключи словаря, но в некоторых случаях это оправдано — но вы можете просто использовать setattr в этих случаях.

Ответ №1:

object реализован на C и не имеет __dict__ атрибута. (Не все объекты Python также имеют это; посмотрите __slots__ ).

Комментарии:

1. @Jamie Обратите внимание, что вы также не можете назначать случайные атрибуты экземпляру, полученному в результате выполнения object() , в то время как вы можете с экземпляром myClass . На самом деле вы мало что можете сделать с экземпляром object , который не является экземпляром какого-либо другого класса.

Ответ №2:

Я не совсем уверен, почему это работает для вашего класса, но не для исходного object класса. Я бы предположил, что когда ваш класс инициализируется, он создает __dict__ .

Используя этот код:

 class Test(object):
    def __init__(self):
        pass

def main():
    print 'OBJECT:', dir(object())
    print
    print 'TEST:', dir(Test())
    return
  

Пришел к такому выводу:

 OBJECT: ['__class__', '__delattr__', '__doc__', '__getattribute__', '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__']

TEST: ['__class__', '__delattr__', '__dict__', '__doc__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', '__weakref__']
  

Как вы можете видеть, __dict__, __module__ и __weakref__ находятся в тестовом объекте, но не в базовом объекте

Комментарии:

1. Это неотъемлемая часть Python — от определения класса зависит, хотят ли они предоставлять атрибут dict или нет (его исключение может сэкономить изрядное количество места на экземпляр). Поскольку dict включен в экземпляры по умолчанию, вы должны предпринять конкретные действия во время определения класса, чтобы избежать его предоставления.