2011-10-18 2 views
39

Мне было интересно, что было наилучшей практикой для инициализации атрибутов объектов в Python, в теле класса или внутри функции __init__?Инициализация/объявление атрибутов в классе Python: куда их поместить?

т.е.

class A(object): 
    foo = None 

против

class A(object): 
    def __init__(self): 
     self.foo = None 

ответ

49

Если вы хотите, чтобы атрибут, который будет общим для всех экземпляров класса, использование атрибутов класса:

class A(object): 
    foo = None 

Это приводит к ('foo',None) для пары (key,value) в A.__dict__.

Если вы хотите, чтобы атрибут быть настраиваемым на основе каждого экземпляра, используйте атрибут экземпляра:

class A(object): 
    def __init__(self): 
     self.foo = None 

Это вызывает ('foo',None) быть (key,value) пара в a.__dict__ где a=A() является экземпляром A.

+1

имеет смысл, я думал, что они ограничены экземпляром в обоих случаях ... спасибо :) – fortran

+6

Python имеет сложный набор [правил поиска атрибутов] (http://www.cafepy.com/article/python_attributes_and_methods/ python_attributes_and_methods.html). Не вдаваясь в дескрипторы, для этого случая достаточно знать, что 'a .__ dict__' сначала ищет ключ' foo', и если он там не найден, выполняется поиск 'A .__ dict__'. Вот почему вы можете использовать 'a.foo', даже если' foo' является атрибутом класса. – unutbu

+1

Также следует отметить, что для атрибутов класса, если бы вы выполняли 'a.foo = whatever', вы фактически создали бы новый атрибут экземпляра (который скрывает атрибут класса). 'A.foo' не изменится. Это своего рода получение, так как вы можете получить доступ к значению 'A.foo' с помощью' a.foo', но при назначении ему будет создан новый атрибут экземпляра. – Kat

2

Атрибуты, определенные в определении класса, считаются переменными класса (например, статические переменные в Java), тогда как те, которые установлены в инициализаторе, являются атрибутами экземпляра (обратите внимание на разницу между self.something = 1 и something = 1). См. this question для получения более подробной информации и this one еще больше. Между этими двумя случаями нет большой практической разницы, поскольку определение уровня класса дает атрибуту значение по умолчанию, но если вы хотите использовать какую-то логику для установки атрибута перед использованием экземпляра объекта, вы должны сделать это в метод __init__().

Смежные вопросы