2015-07-07 3 views
2

В процессе обучения Python, я наткнулся на это странное поведение:Доступ к частным переменная класса

Рассмотрим этот простой класс:

class Human(object): 
    def __init__(self, name): 
    self.__name = name 

    def description(self): 
    print("Hello, my name is %s" % self.__name) 

Я хочу, чтобы избежать возможности изменить имя после того, как объект был создан ,

Если я использую это:

MyHuman = Human("Andy") 
MyHuman.__name = "Arthur" 
MyHuman.age = 23 

MyHuman.description() 
print MyHuman.age 

Это не меняет название после того, как объект при создании экземпляра, который хорош, потому что я хочу, переменную экземпляра, чтобы быть частными. С другой стороны, я думал, что он будет жаловаться на доступ к этой переменной. Он даже не жалуется на доступ к таинственной переменной «возраст» и печатает ее позже.

Я родом из C#, и мне кажется странным. Где моя ошибка?

+4

Ваша ошибка заключалась в том, что в Python есть частные переменные. Ближайшая эмуляция конфиденциальности - «не обращать внимания на эту переменную за занавеской». Если кто-то действительно хочет заглянуть за занавеску, это зависит от них. Официальная фраза - «соглашающиеся взрослые». – TigerhawkT3

+0

Вот некоторые [документация] (https://docs.python.org/3.4/tutorial/classes.html#python-scopes-and-namespaces) о объектах и ​​областях Python. – TigerhawkT3

+0

Хорошо, но как насчет переменной «возраст»? Это немного запутанно, что вы можете создать переменную «на лету» (например, если бы я просто сделал опечатку), не так ли? –

ответ

3

Вы должны знать следующее:

  1. Когда вы пишете на атрибут объекта, который не существует, система питон обычно не жалуются, а просто создайте новый атрибут.
  2. Частные атрибуты не защищены системой Python. Это по расчетному решению.
  3. Частные атрибуты будут замаскированы. Причина в том, что в цепочке наследования не должно быть столкновений. Маскирование выполняется путем неявного переименования. Частные атрибуты будут иметь имя реального
"_<className>__<attributeName>" 

С этим именем, она может быть доступна извне. При доступе изнутри класса имя будет автоматически изменено правильно.

+0

Исходя из C#, автообновление членов класса немного беспокоит меня. Я привыкну к этому :) Спасибо за это объяснение и ваше время. –

+0

@AndyM: Добро пожаловать. Да, у Python действительно есть некоторые странности, и частные члены являются одним из них. Вы можете счесть это тем фактом, что Python - это язык сценариев, а также гордится этим;) Дизайнеры хотели, чтобы вещи были явными и не хотели иметь безопасную систему типа, как на других языках, - она ​​просто полагается гораздо больше на открытость и ясность. Он обеспечивает меньшую нагрузку, но полагается на «хорошее поведение» пользователей. – Juergen

2

использование эмуляция readonly/private переменных в Python, использование property синтаксиса. (Комментарии/другие ответы указывают на то, что переменная может быть доступна, если вы знаете, как - спасибо за головы). Вот один из способов сделать это:

>>> class Test: 
     def __init__(self): 
      self.__a = 1 

     @property 
     def a(self): 
      return self.__a 

>>> t = Test() 
>>> t.a 
1 
>>> t.a = 2 
AttributeError: cannot set attribute 
>>> t.__a 
AttributeError: 'Test' object has no attribute '__a' 
+1

'>>> t._Test__a',' 1'. – TigerhawkT3

+0

Возможно ли, что этот пример ведет себя по-разному на python 2.7 и 3.0? Является ли моя IDE, используя python 2.7, я не получаю сообщение об ошибке, а t.a = 2 разрешено. Испытывая это на онлайн-переводчике 3.0, я получаю ту же ошибку, что и вы ... –

+1

@ AndyM да, это кажется очень возможным. Вы пробовали определить свой класс Python 2 как класс нового стиля, 'class Classname (object)'? Это может иметь значение. Я не знаю. – Sam