Как Pythonic способ инициализировать атрибуты или свойства? - PullRequest
2 голосов
/ 09 февраля 2012

Python поддерживает атрибуты класса, атрибуты экземпляра и свойства.

from time import ctime, sleep

class MyClass(object):
    A = ctime()            # class attribute
    def __init__(self):
        self.B = ctime()   # instance attribute
        self._C = None

    @property
    def C(self):           # property
        if self._C is None:
            self._C = ctime()
        return self._C
    @C.setter
    def C(self, c):
        self._C

Для пользователя, который не знает, как реализован MyClass, A, B и C показывают похожее поведение:

sleep(2)
myObject = MyClass()
sleep(2)
print myObject.A         # prints time module was initialized
print myObject.B         # prints time instance was created, 2 sec later
print myObject.C         # prints time this line was called, 2 sec later
myObject.A = 'foo'       # myObject.A is now an instance attribute
myObject.B = 'foo'       # myObject.B is still an instance attribute
myObject.C = 'foo'       # myObject.C is still an (instance) property
print myObject.A         # prints 'foo'
print myObject.B         # prints 'foo'
print myObject.C         # prints 'foo'

Из ответа, который я получил здесь, я понял следующее: когда напечатано myObject.A в первый раз, myObject.A - это myObject.__Class__.A - MyClass.A.Второй раз myObject.A не myObject.__Class__.A.Fine.

В приведенном выше примере ctime() использовался только для иллюстрации различий между A, B и C.Теперь предположим, что вместо этого мы используем неизменную константу:

class MyClass(object):
    A = 'bar'               # class attribute
    def __init__(self):
        self.B = 'meta'     # instance attribute
        self._C = None

    @property
    def C(self):            # property
        if self._C is None:
            self._C = 'foobar'
        return self._C
    @C.setter
    def C(self, c):
        self._C = c

myObject = MyClass()

myObject.A по-прежнему является атрибутом класса MyClass.A, тогда как myObject.B является атрибутом экземпляра, а myObject.C является свойством.Все они делают именно то, что я хочу.У них есть значение по умолчанию, и я могу назначить другое значение.Какой стиль я должен использовать, A, B или C?

Ответы [ 3 ]

1 голос
/ 09 февраля 2012

По-видимому, существует два стиля создания простых свойств или атрибутов.

Они вообще не являются "стилями", и выполняется только одно: назначение.

Они имеют разные эффекты.

В Python следует логическое правило, согласно которому материал, объявленный в блоке class, принадлежит классу.Таким образом, A является атрибутом класса (примерно аналогичным объявленному static в C ++, Java или C #).B - это атрибут каждого экземпляра, генерируемый автоматически при запуске __init__ на экземплярах.

Что касается вашего обновления, я понятия не имею, что вы пытаетесь задать.Попробуйте использовать настоящие имена, а не «A» и объясните свой вариант использования (например, , почему вы хотите делать, что бы это ни было).

1 голос
/ 09 февраля 2012

Зависит от того, когда вы хотите, чтобы инициализация была запущена, и какой экземпляр вы хотите.

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

Кроме того, ваши примеры кода содержат атрибуты, а не свойства.

Не могу понять ваше обновление вопроса. Вам, вероятно, нужно сделать шаг назад и объяснить причину проблемы.

0 голосов
/ 09 февраля 2012

Предпочтительный способ инициализации атрибута константы класса находится в самом определении класса.

Глядя на код в вопросе, кажется, что существует некоторая путаница в том, как получить доступ к атрибутам класса из объекта экземпляра..

Обратите внимание, что в объекте экземпляра вы можете получить доступ к атрибутам класса по имени, потому что, когда атрибут не найден во внутреннем словаре, поиск продолжается в словаре классов.То есть, если instance.A не существует, вместо него будет возвращено instance.__class__.A, если оно доступно.

Однако, когда атрибут создается в экземпляре объекта, атрибут класса затеняется.То есть instance.A = <value> создает новый атрибут экземпляра, и в следующий раз, когда вы получите доступ к instance.A, будет возвращено <value>.Тем не менее, атрибут класса все еще можно получить с помощью instance.__class__.A.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...