Частные члены в Python
Как я могу сделать методы и члены данных частными в Python? Или не поддерживает ли Python частных членов?
Ответы
Ответ 1
9.6. Частные переменные
"Private" переменные экземпляра, которые невозможно получить доступ, кроме как изнутри объект, не существует в Python. Однако существует конвенция, которая за которым следует большинство кода Python: имя с префиксом подчеркивания (например, _spam) следует рассматривать как непубличную часть API (будь то это функция, метод или данные членом). Его следует рассматривать как детализации реализации и изменить без уведомления.
Поскольку существует допустимый прецедент для члены класса-частного лица (а именно, чтобы избежать имена конфликтов имен с именами определяется подклассами), существует ограниченная поддержка такого механизма, так называемое название mangling. Любой идентификатор формы __spam (не менее двух ведущие подчеркивания, не более нижнее подчеркивание) является текстовым заменяется на _classname__spam
, где classname - это имя текущего класса с лидирующим подчеркиванием (s). Это манипулирование выполняется безотносительно к синтаксическому положению идентификатор, если это происходит в определении класса.
Итак, например,
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
.
Ответ 2
Другие ответы содержат технические детали. Я хотел бы подчеркнуть разницу в философии между Python, с одной стороны, и такими языками, как С++/Java (что, я полагаю, вы знакомы с вашим вопросом).
Общее отношение к Python (и Perl в этом отношении) заключается в том, что "конфиденциальность" атрибута - это запрос программисту, а не колючая проволока за счет компилятора/интерпретатора. Идея хорошо обобщается в этой почтой и часто упоминается как "Мы все соглашаемся с взрослыми", поскольку она "предполагает", что программист достаточно ответственны, чтобы не вмешиваться во внутренние дела. Ведущие подчеркивания служат вежливым сообщением о том, что атрибут является внутренним.
С другой стороны, если вы хотите получить доступ к внутренним компонентам для некоторых приложений (примечательным примером являются генераторы документации, такие как pydoc), вы можете это сделать. Онус на вас, как программист, знает, что вы делаете, и делайте это правильно, а не на языке, чтобы заставить вас делать это так.
Ответ 3
Если имя функции Python, метод класса или атрибут начинается с (но не заканчивается) двумя подчеркивает, это частное; все другое открыто. Python не имеет понятия методов защищенного класса (доступный только в своем классе и потомке классы). Методы класса частные (доступны только в их собственных класса) или общественности (доступный из в любом месте).
Погружение в Python
Ответ 4
В Python нет никаких private
механизмов защиты доступа. В руководстве по стилю Python задокументировано соглашение, указывающее пользователям вашего класса, что им не следует обращаться к определенным атрибутам.
-
_single_leading_underscore: слабый индикатор "внутреннего использования". Например, from M import *
не импортируются объекты, имя которых начинается с подчеркивания.
-
single_trailing_underscore_: используется по соглашению, чтобы избежать конфликтов с ключевым словом Python, например, Tkinter.Toplevel(master, class_='ClassName')
-
__double_leading_underscore: при именовании атрибута класса вызывает искажение имени (внутри класса FooBar __boo становится _FooBar__boo; см. ниже).
Ответ 5
Python не поддерживает конфиденциальность напрямую. Программисту необходимо знать, когда безопасно изменять атрибут снаружи, но в любом случае с помощью python вы можете добиться чего-то вроде частного с небольшими трюками.
Теперь давайте увидим, что человек может положить что-то личное в него или нет.
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
wow, на самом деле, если 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 действительно не имеет эквивалентной поддержки конфиденциальности, хотя single
и двойные начальные подчеркивания в определенной степени дают вам два уровня конфиденциальности
Ответ 6
Это может сработать:
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()
Ответ 7
Это своего рода ответ l-o-n-g, но я думаю, что он попадает в корень настоящей проблемы - область видимости. Просто повесьте там, пока я прокручу это!
Простое импортирование модуля необязательно должно дать разработчику приложения доступ ко всем его классам или методам; если я не могу ПОСМОТРЕТЬ исходный код модуля, как я узнаю, что доступно? Кто-то (или какой-то THING) должен сказать мне, что я могу сделать, и объяснить, как использовать те функции, которые мне разрешено использовать, иначе все это бесполезно для меня.
Те, кто разрабатывает абстракции более высокого уровня, основанные на фундаментальных классах и методах с помощью импортированных модулей, представлены спецификацией DOCUMENT - НЕ фактическим исходным кодом.
Спецификация модуля описывает все функции, которые должны быть видны разработчику клиента. При работе с крупными проектами и проектами программного обеспечения фактическая реализация модуля должна ВСЕГДА оставаться скрытой от тех, кто ее использует - это черный ящик с интерфейсом к внешнему миру. Для пуристов OOD, я считаю, что термины techie являются "развязкой" и "связностью". Пользователь модуля должен знать только методы интерфейса, не нагружая подробностями реализации.
Модуль НИКОГДА не должен изменяться без предварительного изменения его базового документа спецификации, который может потребовать пересмотра/утверждения в некоторых организациях до изменения кода.
Как программист по хобби (теперь ушел в отставку), я запустил новый модуль, в котором специфицированный документ фактически выписан как гигантский блок комментариев в верхней части модуля, это будет та часть, которую пользователь действительно видит в библиотеке спецификаций. Поскольку это только я, я еще не создал библиотеку, но это было бы достаточно легко сделать.
Затем я начинаю кодирование, записывая различные классы и методы, но без функциональных тел - просто нулевые утверждения печати, такие как "print()", - достаточно, чтобы модуль мог компилироваться без синтаксических ошибок. Когда этот шаг завершен, я компилирую завершенный нуль-модуль - это моя спецификация. Если бы я работал над командой проекта, я бы представил эту спецификацию/интерфейс для обзора и комментариев, прежде чем приступать к фишированию тела.
Я формирую тела каждого метода по одному и компилирую соответственно, гарантируя, что синтаксические ошибки фиксируются немедленно на лету. Это также хорошее время, чтобы начать запись временного "основного" этапа выполнения внизу, чтобы протестировать каждый метод по мере его кодирования. Когда кодирование/тестирование завершено, весь тестовый код закомментирован до тех пор, пока он не понадобится, если обновления станут необходимыми.
В реальной команде разработчиков блок комментариев комментариев также появится в библиотеке управления документами, но это еще одна история. Дело в том, что вы, как клиент модуля, видите только эту спецификацию и НЕ исходный код.
PS: задолго до начала работы, я работал в оборонном аэрокосмическом сообществе, и мы сделали довольно классные вещи, но такие вещи, как запатентованные алгоритмы и логика управления чувствительными системами, были жестко собраны и зашифрованы в супер-пуперных защищенных программных библиотеках. У нас был доступ к интерфейсам модулей/пакетов, но не к областям реализации черных ящиков. Был инструмент управления документами, который обрабатывал все проекции на системном уровне, спецификации программного обеспечения, исходный код и тестовые записи - все было синхронизировано вместе. У правительства были строгие требования к стандартам обеспечения качества программного обеспечения. Кто-нибудь помнит язык под названием "Ада"? Вот, сколько мне лет!
Ответ 8
Я использую Python 2.7 и 3.5. Я написал этот код:
class MyOBject(object):
def __init__(self):
self.__private_field = 10
my_object = MyOBject()
print(my_object.__private_field)
запустил его и получил:
AttributeError: у объекта 'MyOBject' нет атрибута '__private_field'
Пожалуйста, смотрите: https://www.tutorialsteacher.com/python/private-and-protected-access-modifiers-in-python
Ответ 9
если вы хотите, чтобы методы или члены данных были приватными в 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()