2012-04-11 1 views
4

Я прихожу из Java, поэтому я запутался здесь.переменные члена или класса в python

class Sample(object): 
    x = 100      # class var? 
    def __init__(self, value): 
     self.y = value   # instance var? 
     z = 300     # private var? how do we access this outside Sample? 

В чем разница между тремя объявлениями переменных?

+1

Duplicate, duplicate, duplicate ... lots и * lots * вопросов, подобных этому, лотов и * лотов * полной документации. –

+5

@ChrisMorgan: если вы собираетесь называть дубликат, по крайней мере, найдите лучший дубликат ответов и разместите ссылку здесь. –

+1

Чтобы выбрать несколько примеров, которые демонстрируют все точки этого вопроса: [переменные класса и экземпляра] (http://stackoverflow.com/questions/207000/python-difference-between-class-and-instance-attributes), [private variables] (http://stackoverflow.com/questions/3294764/simulate-private-variables-in-python) –

ответ

17
class Sample(object): 
    x = 100  
    _a = 1 
    __b = 11    
    def __init__(self, value): 
     self.y = value  
     self._c = 'private'  
     self.__d = 'more private' 
     z = 300   

В этом примере:

  • x является переменным классом,
  • _a переменным частным класса (по именованию)
  • __b является частным переменным классом (искажается переводчиком),
  • y является переменной экземпляра,
  • _c является частным переменным экземпляром (по именованию),
  • __d является частным переменным экземпляром (искажается переводчиком),
  • z является локальной переменным в пределах объема __init__ метода.

В случае единственного подчеркивания в именах это строго конвенция. Доступ к этим переменным все же возможен. В случае двойных имен подчеркивания они искажены. По-прежнему можно обойти это.

+4

Однако dunderscore редко используется в Python. Обычно только одно подчеркивание добавляется к сигналу о том, что переменная предназначена для внутреннего использования. –

+0

@NiklasB: одиночное подчеркивание - это всего лишь указание, в то время как двойное подчеркивание выполняется интерпретатором. – vartec

+1

Я просто говорю, что много реального кода Python не использует это «принуждение», потому что оно не имеет реального преимущества. И да, вы можете легко получить к нему доступ в любом случае через 'self._Class__variable'. –

1

Возможно, вам это нравится. Единственный, о котором вы были совершенно неправы, - z = 300. Это имя, которое является локальным для метода __init__. Python never вставляет self для вас таким же образом, что C++ и Java будут принимать this, где это возможно.

Одна вещь, которую следует помнить, когда вы продолжаете изучать Python, состоит в том, что функции-члены всегда могут выполняться как члены класса. Рассмотрим следующий пример:

>>> class Sample(object): 
... def __init__(self, value): 
...  self.value = value 
... def get_value(self): 
...  return self.value 
... 
>>> s = Sample(1) 
>>> t = Sample(2) 
>>> s.get_value() 
1 
>>> Sample.get_value(s) 
1 
>>> t.__class__.get_value(s) 
1 

Последние три примера все вызываем функцию член от s объекта. Последние два используют тот факт, что get_value является всего лишь атрибутом класса Sample, который ожидает получить в качестве аргумента экземпляр Sample.

+0

. я наткнулся на статью, которая говорит, создавая локальную переменную метода __init__, как частный var (как в Java). Но я не мог найти способ получить доступ к z в другом месте. – John

+0

также, я потерял ссылку на эту статью. :( – John

2

@vartec - место сверху. Так как вы пришли из Java, однако, некоторые уточнения в порядке:

  • Java имеет public и private членов. Доступ к private членам строго запрещен, и это обеспечивается языком.
  • Python имеет только публичные элементы. Существует no способ принудительного использования ключевого слова java private.

    Если вы хотите заявить, что что-то является только деталью реализации, и на него нельзя полагаться другим кодом, вы должны указать его на одно подчеркивание - _variable, _function().Это подсказка другим программистам, что они не должны использовать эту переменную или эту функцию, но она не установлена ​​.

    Может показаться, что функция была опущена на Python, но культура в Python - «все - взрослый человек, согласный». Если вы сообщите другим программистам, что что-то «частное», префиксное с подчеркиванием, они обычно берут подсказку.

+0

Ну, технически вы можете сделать правду частным, вам просто нужно калечить свой класс, переопределив '__setattr __()', чтобы в любой момент сделать ошибку, чтобы установить заданное значение вне самого класса. Конечно, это ОЧЕНЬ не-Pythonic, но если вы хотите Javaize Python (и у меня был менеджер, который заставлял нас делать это на предыдущей работе), вы можете это сделать. –

+0

@ sr2222: Я качаю назад и вперед в углу, когда мы говорим. –

+1

@LiAungYip Я действительно верю, что есть PEP, который говорит, что это правильный ответ на такую ​​практику. –