Если вы сомневаетесь, оставьте это "публичным" - я имею в виду, не добавляйте ничего, чтобы скрыть имя вашего атрибута.Если у вас есть класс с некоторым внутренним значением, не беспокойтесь об этом.Вместо записи:
class Stack(object):
def __init__(self):
self.__storage = [] # Too uptight
def push(self, value):
self.__storage.append(value)
напишите это по умолчанию:
class Stack(object):
def __init__(self):
self.storage = [] # No mangling
def push(self, value):
self.storage.append(value)
Это наверняка спорный способ ведения дел.Новички в Python просто ненавидят его, и даже некоторые старые парни из Python презирают это значение по умолчанию, но в любом случае это значение по умолчанию, поэтому я очень рекомендую вам следовать ему, даже если вы чувствуете себя неловко.1010 * хочу отправить сообщение "Не могу потрогать это!"для ваших пользователей обычным способом является добавление к переменной one подчеркивания.Это просто соглашение, но люди понимают его и проявляют двойную осторожность при работе с такими вещами:
class Stack(object):
def __init__(self):
self._storage = [] # This is ok but pythonistas use it to be relaxed about it
def push(self, value):
self._storage.append(value)
Это также может быть полезно для избежания конфликта между именами свойств и именами атрибутов:
class Person(object):
def __init__(self, name, age):
self.name = name
self._age = age if age >= 0 else 0
@property
def age(self):
return self._age
@age.setter
def age(self, age):
if age >= 0:
self._age = age
else:
self._age = 0
А как насчет двойного подчеркивания?Итак, магия двойного подчеркивания используется в основном , чтобы избежать случайной перегрузки методов и конфликтов имен с атрибутами суперкласса .Это может быть очень полезно, если вы напишите класс, который, как ожидается, будет многократно расширен.
Если вы хотите использовать его для других целей, вы можете, но это не является ни обычным, ни рекомендуемым.
РЕДАКТИРОВАТЬ : Почему это так?Что ж, обычный стиль Python не подчеркивает необходимость делать вещи приватными - наоборот!Для этого есть много причин - большинство из них противоречивы ... Давайте рассмотрим некоторые из них.
Python обладает свойствами
Большинство современных языков программирования используют противоположный подход: чего не следуетиспользоваться не должно быть видимым, поэтому атрибуты должны быть закрытыми.Теоретически это привело бы к более управляемым, менее связанным классам, потому что никто не мог бы безрассудно изменять значения внутри объектов.
Однако это не так просто.Например, классы Java имеют множество атрибутов и , которые просто получают значения и , которые просто устанавливают значения.Вам нужно, скажем, семь строк кода, чтобы объявить один атрибут - что, как сказал бы программист Python, излишне сложно.Кроме того, на практике вы просто пишете весь этот код, чтобы получить одно открытое поле, поскольку вы можете изменить его значение с помощью методов получения и установки.
Так зачем следовать этой политике конфиденциальности по умолчанию?Просто сделайте ваши атрибуты общедоступными по умолчанию.Конечно, это проблематично в Java, потому что, если вы решите добавить некоторую проверку в ваш атрибут, вам потребуется изменить все
person.age = age;
в вашем коде, скажем, на
person.setAge(age);
setAge()
:
public void setAge(int age) {
if (age >= 0) {
this.age = age;
} else {
this.age = 0;
}
}
Таким образом, в Java (и других языках) по умолчанию в любом случае используется метод получения и установки, потому что они могут раздражать при записи, но могут сэкономитьМного времени, если вы окажетесь в ситуации, которую я описал.
Однако вам не нужно делать это в Python, поскольку у Python есть свойства.Если у вас есть этот класс:
class Person(object):
def __init__(self, name, age):
self.name = name
self.age = age
, а затем вы решаете подтвердить возраст, вам не нужно изменять person.age = age
фрагменты вашего кода.Просто добавьте свойство (как показано ниже)
class Person(object):
def __init__(self, name, age):
self.name = name
self._age = age if age >= 0 else 0
@property
def age(self):
return self._age
@age.setter
def age(self, age):
if age >= 0:
self._age = age
else:
self._age = 0
Если вы можете сделать это и по-прежнему использовать person.age = age
, зачем вам добавлять личные поля и методы получения и установки?
(Кроме того,см. Python не Java и эта статья о вреде использования геттеров и сеттеров .).
В любом случае все видно - и попытка скрыть просто усложняет вашу работу
Даже в языках, где есть личные атрибуты, вы можете получить к ним доступ через какую-то библиотеку отражения / самоанализа.И люди делают это много, в рамках и для решения насущных потребностей.Проблема состоит в том, что библиотеки самоанализа - это просто сложный способ сделать то, что вы могли бы сделать с открытыми атрибутами.
Поскольку Python - очень динамичный язык, добавление этого бремени к вашим классам просто контрпродуктивно.
Проблема не видна - требуется , требуется , чтобы увидеть
Для Pythonista инкапсуляция - это не неспособность видеть внутренности классов, а возможность избежать их просмотра. Я имею в виду, что инкапсуляция - это свойство компонента, которое позволяет использовать его, не заботясь о внутренних деталях пользователя. Если вы можете использовать компонент, не беспокоясь о его реализации, то он инкапсулирован (по мнению программиста Python).
Теперь, если вы написали свой класс таким образом, что вы можете использовать его, не думая о деталях реализации, не будет проблем, если вы захотите заглянуть внутрь класса по какой-то причине. Дело в том, что ваш API должен быть хорошим, а все остальное - подробности.
Гвидо так сказал
Ну, это не спорный: он так сказал, на самом деле . (Ищите «открытое кимоно».)
Это культура
Да, есть несколько причин, но нет критических. Это в основном культурный аспект программирования на Python. Честно говоря, это может быть и другой путь, но это не так. Кроме того, вы могли бы так же легко задать другой вопрос: почему некоторые языки по умолчанию используют закрытые атрибуты? По той же основной причине, что и для практики Python: потому что это культура этих языков, и каждый выбор имеет свои преимущества и недостатки.
Поскольку эта культура уже существует, вам рекомендуется следовать ей. В противном случае вы будете раздражены программистами Python, которые скажут вам удалить __
из вашего кода, когда вы зададите вопрос в переполнении стека:)