Вопрос

Как я могу сделать методы и элементы данных закрытыми в Python?Или Python не поддерживает закрытых участников?

Это было полезно?

Решение

9.6.Частные Переменные

“Частные” переменные экземпляра, к которым нельзя получить доступ, кроме как изнутри объекта, не существуют в Python.Однако существует соглашение, которому следует большая часть кода на Python:имя с префиксом подчеркивания (например_spam) следует рассматривать как непубличную часть API (будь то функция, метод или элемент data ).Это следует рассматривать как деталь реализации и подлежит изменению без предварительного уведомления.

Поскольку существует допустимый вариант использования для закрытых членов класса (а именно, чтобы избежать столкновения имен с именами определяется подклассами), существует ограниченная поддержка такого механизма, называемого искажением имен.Любой идентификатор вида __spam (не менее двух начальных подчеркиваний, не более одного завершающего подчеркивания) текстуально заменяется на _classname__spam, где classname - это текущее имя класса с зачеркнутыми начальными символами подчеркивания.Это искажение выполняется без учета синтаксической позиции идентификатора, если оно встречается в определении класса.

Итак, например,

class Test:
    def __private_symbol(self):
        pass
    def normal_symbol(self):
        pass

print dir(Test)

будет выводить:

['_Test__private_symbol', 
'__doc__', 
'__module__', 
'normal_symbol']

__private_symbol следует считать частным методом, но он все равно будет доступен через _Test__private_symbol.

Другие советы

Другие ответы содержат технические подробности.Я хотел бы подчеркнуть разницу в философии между Python, с одной стороны, и такими языками, как C++/Java (с которыми, судя по вашему вопросу, я полагаю, вы знакомы).

Общее отношение в Python (и Perl, если уж на то пошло) таково, что «конфиденциальность» атрибута — это запрос к программисту, а не забор из колючей проволоки со стороны компилятора/интерпретатора.Идея хорошо изложена в это письмо и его часто называют «Мы все взрослые люди по обоюдному согласию», поскольку он «предполагает», что программист достаточно ответственен, чтобы не вмешиваться во внутренние дела.Начальное подчеркивание служит вежливым сообщением о том, что атрибут является внутренним.

С другой стороны, если вы делать хотите получить доступ к внутренним компонентам некоторых приложений (ярким примером являются генераторы документации, такие как pydoc), вы можете это сделать.Ответственность лежит на вас, как на программисте, чтобы знать, что вы делаете, и делать это правильно, а не на том, чтобы язык заставлял вас что-то делать. его способ.

Нет private любых других механизмов защиты доступа в Python.Существует соглашение, задокументированное в Руководство по стилю Python для указания пользователям вашего класса, что им не следует обращаться к определенному атрибуту.

  • _single_leading_underscore:слабый показатель «внутреннего использования».Например. from M import * не импортирует объекты, имя которых начинается с подчеркивания.

  • single_trailing_underscore_:используется по соглашению, чтобы избежать конфликтов с ключевым словом Python, например. Tkinter.Toplevel(master, class_='ClassName')

  • __double_leading_underscore:при именовании атрибута класса вызывает искажение имени (внутри класса FooBar __boo становится _FooBar__boo;см. ниже).

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

Погрузитесь в Python

Python не поддерживает конфиденциальность напрямую .Программисту нужно знать, когда безопасно изменять атрибут извне, но в любом случае с помощью python вы можете добиться чего-то вроде private с помощью небольших хитростей.Теперь давайте посмотрим, может человек вкладывать в это что-то личное или нет.

class Person(object):

    def __priva(self):
        print "I am Private"

    def publ(self):
        print " I am public"

    def callpriva(self):
        self.__priva()

Теперь, когда мы выполним :

>>> p = Person()
>>> p.publ()
 I am public
>>> p.__priva()
Traceback (most recent call last):
  File "", line 1, in 
    p.__priva()
AttributeError: 'Person' object has no attribute '__priva'
​#Explanation   : You can see  here we are not able to fetch that private method directly.
>>> p.callpriva()
I am Private
#​Explanation  : Here we can access private method inside class​

​Тогда как кто - то может получить доступ к этой переменной???
Вы можете сделать следующее :

>>>p._Person__priva
I am Private

​вау, на самом деле, если python получает любую переменную, начинающуюся с двойного подчеркивания, они “переводятся” путем добавления одинарного подчеркивания и имени класса в начало:

Примечание : Если вы не хотите, чтобы это имя менялось, но вы все еще хотите послать сигнал другим объектам держаться подальше, вы можете использовать одно начальное подчеркивание имена с начальным подчеркиванием не импортируются с помощью импорта со звездочками (из модуля импорта *)
Пример :

#test.py
def hello():
    print "hello"
def _hello():
    print "Hello private"

#----------------------
#test2.py
from test import *
print hello()
print _hello()

результат ->

hello
Traceback (most recent call last):
  File "", line 1, in 
NameError: name '_hello' is not defined

Теперь , если мы вызовем _hello вручную .

#test2.py
from test import _hello , hello
print hello()
print _hello()

результат ->

hello
hello private

Наконец-то :В Python на самом деле не имеют эквивалента поддержки конфиденциальности, хотя один и дважды начальной подчеркивает делать в какой-то степени дать вам два уровня конфиденциальности

Это может сработать:

import sys, functools

def private(member):
    @functools.wraps(member)
    def wrapper(*function_args):
      myself = member.__name__
      caller = sys._getframe(1).f_code.co_name
      if (not caller in dir(function_args[0]) and not caller is myself):
         raise Exception("%s called by %s is private"%(myself,caller))
      return member(*function_args)
    return wrapper

class test:
   def public_method(self):
      print('public method called')

   @private
   def private_method(self):
      print('private method called')

t = test()
t.public_method()
t.private_method()

Это своего рода длинный ответ, но я думаю, что он затрагивает корень настоящей проблемы - масштаб видимости.Просто подожди, пока я продираюсь через это!

Простой импорт модуля не обязательно должен предоставлять разработчику приложения доступ ко всем его классам или методам;если я не могу ВИДЕТЬ исходный код модуля, как я узнаю, что доступно?Кто-то (или какая-то ВЕЩЬ) должен сказать мне, что я могу сделать, и объяснить, как использовать те функции, которые мне разрешено использовать, иначе все это для меня бесполезно.

Тем, кто разрабатывает абстракции более высокого уровня на основе фундаментальных классов и методов с помощью импортированных модулей, предоставляется ДОКУМЕНТ спецификации, а НЕ реальный исходный код.

Спецификация модуля описывает все функции, которые должны быть видны разработчику клиента.При работе с крупными проектами и командами разработчиков программного обеспечения фактическая реализация модуля ВСЕГДА должна оставаться скрытой от тех, кто его использует — это черный ящик с интерфейсом для внешнего мира.Я считаю, что для пуристов ООД техническими терминами являются «развязка» и «когерентность».Пользователю модуля достаточно знать только методы интерфейса, не обременяя его деталями реализации.

Модуль НИКОГДА не следует изменять без предварительного изменения лежащего в его основе документа спецификации, который может потребовать проверки/утверждения в некоторых организациях перед изменением кода.

Как программист-любитель (сейчас на пенсии), я начинаю новый модуль со спецификацией, фактически записанной в виде огромного блока комментариев в верхней части модуля. Это будет та часть, которую пользователь фактически увидит в библиотеке спецификаций.Поскольку это только я, мне еще предстоит настроить библиотеку, но это будет достаточно легко сделать.

Затем я начинаю кодирование с написания различных классов и методов, но без функциональных тел — только пустые операторы печати, такие как «print()», — ровно настолько, чтобы модуль мог скомпилироваться без синтаксических ошибок.Когда этот шаг завершен, я компилирую готовый нулевой модуль — это моя спецификация.Если бы я работал в проектной команде, я бы представил эту спецификацию/интерфейс на рассмотрение и комментарии, прежде чем приступить к доработке тела.

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

В реальной команде разработчиков блок комментариев к спецификации также появится в библиотеке управления документами, но это уже другая история.Дело в том:вы, как клиент модуля, видите только эту спецификацию, а НЕ исходный код.

ПС:задолго до начала времен я работал в оборонном аэрокосмическом сообществе, и мы делали некоторые довольно крутые вещи, но такие вещи, как проприетарные алгоритмы и логика управления чувствительными системами, были надежно запрятаны и зашифрованы в сверхнадежных библиотеках программного обеспечения.У нас был доступ к интерфейсам модулей/пакетов, но НЕ к телам реализации черного ящика.Был инструмент управления документами, который обрабатывал все проекты системного уровня, спецификации программного обеспечения, исходный код и записи испытаний — все это было синхронизировано вместе.Правительство предъявляло строгие требования к стандартам обеспечения качества программного обеспечения.Кто-нибудь помнит язык под названием «Ада»?Вот сколько мне лет!

Я использую Python 2.7 и 3.5.Я написал этот код:

class MyOBject(object):
    def __init__(self):
        self.__private_field = 10


my_object = MyOBject()
print(my_object.__private_field)

запустил и получил:

Ошибка атрибута:Объект MyOBject не имеет атрибута __private_field.

Пожалуйста, посмотри:https://www.tutorialsteacher.com/python/private-and-protected-access-modifiers-in-python

если вы хотите сделать методы или элементы данных закрытыми в Python, используйте __setattr __

class Number:
    def __init__(self,value):
        self.my_private = value

    def __setattr__(self, my_private, value):
        # the default behavior
        # self.__dict__[my_private] = value
        raise Exception("can't access private member-my_private")


def main():
    n = Number(2)
    print(n.my_private)

if __name__ == '__main__': 
    main()
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top