foo и _foo - о переменных внутри класса - PullRequest
0 голосов
/ 21 апреля 2010
class ClassName(object):
    """
    """    
    def __init__(self, foo, bar):
        """
        """
        self.foo = foo # read-write property
        self.bar = bar # simple attribute

    def _set_foo(self, value):
        self._foo = value

    def _get_foo(self):
        return self._foo

    foo = property(_get_foo, _set_foo)

a = ClassName(1,2)
#a._set_foo(3)
print a._get_foo()

Когда я печатаю a._get_foo (), функция _get_foo печатает переменную self._foo. Но откуда это? self._foo и self.foo разные, не так ли?

РЕДАКТИРОВАТЬ: Проблема в том, что я до сих пор не понимаю, что делает свойство. Дай мне немного времени.

Ответы [ 5 ]

2 голосов
/ 22 апреля 2010

Я очень рекомендую этот сайт:

http://adam.gomaa.us/blog/2008/aug/11/the-python-property-builtin/

Хорошее объяснение свойства-функции.

2 голосов
/ 21 апреля 2010

Документы для property объясняют, как это должно использоваться. Нет разницы между этими строками:

self.foo = foo # read-write property

и

a.foo = 3

Вы также не должны вызывать сеттеры и геттеры вручную.

eta : если вы не понимаете, что делает property, взглянув на примеры, приведенные в документации и прочитав наши ответы, вам, возможно, следует просто отказаться от его использования. Это действительно не самая важная из возможностей Python. Возможно, вы захотите начать с более простого примера, который легко понять:

>>> class ClassName(object):
    def __init__(self, foo):
        self.foo = foo


>>> a = ClassName(1, 2)
>>> a.foo
1
>>> a.foo = 42
>>> a.foo
42
1 голос
/ 21 апреля 2010

self._foo и self.foo будут отличаться, за исключением того, что вы присвоите созданному свойству имя foo: foo = property(_get_foo, _set_foo).

Итак, теперь у вас есть два определенных имени foo, которое является свойством, которое определяется в терминах методов _set_foo и _get_foo. У вас также определено имя _foo, но это тот же атрибут, который используется в _set_foo и _get_foo и, следовательно, в свойстве foo.

То есть вы два имени, но только один объект.

        foo
        /\
       /  \
_set_foo  _get_foo
       \   /
        \ /
       _foo --> object

Примечание: Для примера, в котором у вас есть Python, это излишне, нет необходимости использовать методы getter и setter, если в них не будет бизнес-логики. атрибут с именем foo, вы всегда можете обернуть его в свойстве в будущем, не влияя на клиентский код, если выяснится, что вам нужны какие-то смарты для доступа к атрибуту.

Измените свой код на:

class ClassName(object): 
    def __init__(self, foo, bar):
    self.foo = foo # read-write property
    self.bar = bar # simple attribute

И foo, и bar доступны для чтения и записи, если вам нужен более точный контроль, вы можете рассмотреть возможность использования свойства.

1 голос
/ 21 апреля 2010

Вы определяете foo как свойство с геттерами и сеттерами.

Эти геттеры и сеттеры используют переменную self._foo, поскольку вы кодировали ее таким образом:

def _set_foo(self, value):
  self._foo = value

В вашем случае вы бы столкнулись с проблемой, если бы у вас была немного другая реализация:

class ClassName(object):
    """
    """    
    def __init__(self,):
        """
        """
        pass

    def _set_foo(self, value):
        self._foo = value

    def _get_foo(self):
        return self._foo

    foo = property(_get_foo, _set_foo)


 a = ClassName()
 print a.foo
 -> AttributeError

 b = ClassName()
 b.foo = 1 # implicitely sets self._foo !
 print b.foo
 >> OK, this is 1

Как это происходит, вы действительно должны установить self.foo в __init__, так как установщик создает self._foo. (Или, конечно, инициализировать self._foo в __init__ напрямую).

Итак, откуда взялись self.foo и self._foo? Это явно в коде. self.foo - это свойство, а self._foo - это переменная, в которой вы решили сохранить значение этого свойства.

0 голосов
/ 21 апреля 2010

Согласно вашему коду, это "исходит от" _set_foo. В вашем init, когда вы делаете self.foo = foo, это вызывает _set_foo (1), который выполняет self._foo = 1.

Вы можете увидеть это более четко, если добавите оператор печати внутри _set_foo ().

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