@AlexBoss

В чем смысл одинарного и двойного подчеркивания перед переменной или методом при определении класса?

День добрый. Никак не могу понять, смысл одинарного подчеркивания.
Пишут, что добавляет приватность, но я все равно могу обратиться ко всем объектам:
_internal_name = 'one_nodule' # private variable
_internal_version = '1.0' # private variable

class _Base: # private class
_hidden_factor = 2 # private variable
def __init__(self, price):
self._price = price
def _double_price(self): # private method
return self._price * self._hidden_factor
def get_double_price(self):
return self._double_price()

По поводу двойного, могли бы разъяснить. Понял, что декарируются _ИмяКласса__метод, но как это выглядит на практике не совсем понимаю
Заранее спасибо
  • Вопрос задан
  • 1170 просмотров
Решения вопроса 4
yarkov
@yarkov
Проект "Жизнь после смерти" - lifeafterdeath.ru
Пример
Попытка вызвать приватный метод приводит к ошибке.

но я все равно могу обратиться ко всем объектам

5ccff785271f7736875241.png
Ответ написан
@deliro
Агрессивное программирование
Нет в питоне приватных атрибутов. Об этом уже на каждом заборе написали. Подчёркивания — соглашение о том, что программисту не стоит использовать эти атрибуты как интерфейс. Двойное подчёркивание тоже не добавляет приватности.

5ccffe45cca5d170551109.png
Ответ написан
@kova1ev
По поводу двойного, могли бы разъяснить. Понял, что декарируются _ИмяКласса__метод, но как это выглядит на практике не совсем понимаю


class Base:
    def __init__(self, price):
        self.__price = price

obj = Base(99)
print(obj.__price) #ошибка
print(obj._Base__price) #выведет значение атрибута __price

если создать объект Base и попробовать обратиться к атрибуту __price - будет ошибка. То есть он вроде как приватный. Но на самом деле, если очень хочется, можно обратиться к нему через конструкцию obj._Base__price, ну и изменить тоже можно
Ответ написан
aRegius
@aRegius
Python Enthusiast
Ключевое отличие между этими вариантами в том, что в случае участия (явного, либо предположительного) вашего класса в механизме наследования, лучше использовать вариант с двумя подчеркиваниями, что позволит избежать возможной нежелательной перезаписи значения атрибута в противном случае (использование публичного, либо псевдо-приватного с одинарным подчеркиванием):
>>> class A:
	      def __init__(self, value):
		         self._value = value
	      def meth_a(self):
		         print('Class A Method with value {}...'.format(self._value))
		
>>> class B(A):	
	      def meth_b(self, value):
		         self._value = value
		         print('Class B Method with value {}...'.format(self._value))
		
>>> x = B(100)
>>> x.meth_a()
Class A Method with value 100...
>>> x.meth_b(40)
Class B Method with value 40...
>>> x.meth_a()
Class A Method with value 40...  # Значение атрибута объекта класса А изменилось !

>>> class A:
	      def __init__(self, value):
		         self.__value = value
	      def meth_a(self):
		         print('Class A Method with value {}...'.format(self.__value))
		
>>> class B(A):	
	      def meth_b(self, value):
		         self.__value = value
		         print('Class B Method with value {}...'.format(self.__value))
		
>>> x = B(100)
>>> x.meth_a()
Class A Method with value 100...
>>> x.meth_b(40)
Class B Method with value 40...
>>> x.meth_a()
Class A Method with value 100...   # Значение атрибута объекта класса А осталось неизменным !

Происходит это по причине, о которой вам уже написали - обращение Python к подобным атрибутам/методам (с двумя начальными подчеркиваниями) через имя соответствующего Класса (при одинаковых явных атрибутах self.__value в обоих классах, мы имеем на самом деле два разных: self._A__value и self._B__value).
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы