Ответ 1
Нет, по той же причине, что и:
>>> class Foo(object):
... bar = 'Foo attribute'
...
>>> f = Foo()
>>> f.bar
'Foo attribute'
>>> Foo.bar
'Foo attribute'
>>> f.bar = 'instance attribute'
>>> f.bar
'instance attribute'
>>> Foo.bar
'Foo attribute'
Когда вы назначаете атрибут объекту, атрибут класса с тем же именем будет "затмеваться" объектом. Однако при поиске атрибутов, если объект, о котором идет речь, не определяет указанный атрибут, вместо него будет возвращен класс 1.
В Django эти атрибуты класса используются слоем ORM для генерации механизма, который преобразуется в SQL-запросы и операции (глубокая, метаклассическая магия происходит за кадром).
edit: Чтобы ответить на ваш вопрос -
Чтобы понять это, вам нужно немного разобраться в модели данных Python . По сути, оба класса и объекты имеют пространства имен. Это видно, если вы заглядываете в свой специальный атрибут __dict__
:
>>> print Foo.__dict__
{'__dict__': <attribute '__dict__' of 'Foo' objects>, '__weakref__': <attribute
'__weakref__' of 'Foo' objects>, '__module__': '__main__', 'bar': 'Foo attribute
', '__doc__': None}
>>> f = Foo()
>>> print f.__dict__
{}
Когда объект f
сначала создается, он имеет пустое пространство имен. Когда вы выполняете поиск, f.bar
, это пространство имен (действительно, словарь) просматривается. Поскольку там нет атрибута 'bar'
, f
class, Foo
, просматривается. Найдем 'bar': 'Foo attribute'
. Итак, что будет возвращено:
>>> f.bar
'Foo attribute'
Теперь, когда вы назначаете значение атрибута объекту, а указанное имя атрибута еще не существует в его пространстве имен, оно создается:
>>> f.bar = 'instance attribute'
>>> print f.__dict__
{'bar': 'instance attribute'}
>>> f.bar
'instance attribute'
Теперь вы знаете, что произойдет в следующий раз, когда f.bar
будет поднят! f.__dict__['bar']
существует и будет возвращен, прежде чем мы даже посмотрим на пространство имен Foo
.
Конечно, если ваше намерение состоит в том, чтобы всегда получать доступ и манипулировать атрибутом класса вместо экземпляра, вам нужно будет использовать имя класса.
>>> Foo.bar
'Foo attribute'
>>> Foo.__dict__['bar']
'Foo attribute'