Определение функций частного модуля в python
Согласно http://www.faqs.org/docs/diveintopython/fileinfo_private.html:
Как и большинство языков, Python имеет концепция частных элементов:
- Частный функции, которые не могут быть вызваны из вне их модуля
Однако, если я определяю два файла:
#a.py
__num=1
и
#b.py
import a
print a.__num
когда я запускаю b.py
, он выводит 1
без каких-либо исключений. Является ли diveintopython неправильным, или я что-то неправильно понял? И есть ли способ сделать определить функцию модуля как конфиденциальную?
Ответы
Ответ 1
В Python "конфиденциальность" зависит от уровня согласия "согласных взрослых" - вы не можете заставить его (больше, чем вы можете в реальной жизни;-). Единственное подчеркивание означает, что вы не предположили для доступа к нему "извне" - два ведущих подчеркивания (без подчеркивания подчеркивания) переносят сообщение еще более убедительно... но, в конце концов, это все еще зависит от социальной конвенции и консенсуса: интроспекция Python достаточно сильная, чтобы вы не могли наручники всех других программистов в мире уважать ваши пожелания.
((Btw, хотя он тесно связан с секретом, то же самое имеет место для С++: с большинством компиляторов простая строка #define private public
до #include
в вашем файле .h
- все, что нужно, чтобы коварные кодеры хэш вашей "конфиденциальности"...! -))
Ответ 2
Может возникнуть путаница между class privates и модулем privates.
Закрытый модуль начинается с одного подчеркивания
Такой элемент не копируется при использовании формы from <module_name> import *
команды import; он импортируется, если используется синтаксис import <moudule_name>
(см. ответ Бен Вильгельма)
Просто удалите одно подчеркивание из a.__ num примера вопроса, и оно не будет отображаться в модулях, которые импортируют a.py с помощью синтаксиса from a import *
.
Класс private начинается с двух подчеркиваний (aka dunder i.e. d-ouble under-score)
Такая переменная имеет свое имя "mangled", чтобы включить имя класса и т.д.
Его все равно можно получить за пределами логики класса, через искаженное имя.
Хотя название mangling может служить в качестве устройства для предотвращения несанкционированного доступа, его основная цель - предотвратить возможные столкновения имен с членами класса предков.
См. Alex Martelli, смешную, но точную ссылку на соглашающихся взрослых, поскольку он описывает соглашение, используемое в отношении этих переменных.
>>> class Foo(object):
... __bar = 99
... def PrintBar(self):
... print(self.__bar)
...
>>> myFoo = Foo()
>>> myFoo.__bar #direct attempt no go
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Foo' object has no attribute '__bar'
>>> myFoo.PrintBar() # the class itself of course can access it
99
>>> dir(Foo) # yet can see it
['PrintBar', '_Foo__bar', '__class__', '__delattr__', '__dict__', '__doc__', '__
format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__',
'__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__
', '__subclasshook__', '__weakref__']
>>> myFoo._Foo__bar #and get to it by its mangled name ! (but I shouldn't!!!)
99
>>>
Ответ 3
Этот вопрос не получил полного ответа, поскольку конфиденциальность модуля не является чисто условной, и поскольку использование import может или не может распознавать конфиденциальность модуля, в зависимости от того, как он используется.
Если вы определяете личные имена в модуле, те имена будут импортированы в любой script, который использует синтаксис, 'import module_name'. Таким образом, предполагая, что вы правильно определили в своем примере модуль private, _num, в a.py, вот так..
#a.py
_num=1
.. вы могли бы получить к нему доступ в b.py с символом имени модуля:
#b.py
import a
...
foo = a._num # 1
Чтобы импортировать только не-приватных из a.py, вы должны использовать синтаксис от:
#b.py
from a import *
...
foo = _num # throws NameError: name '_num' is not defined
Для ясности, однако, лучше быть явным при импорте имен из модулей, а не импортировать их все с помощью "*":
#b.py
from a import name1
from a import name2
...
Ответ 4
Python позволяет частным членам класса с двойным префиксом подчеркивания. Этот метод не работает на уровне модуля, поэтому я думаю, что это ошибка в Dive Into Python.
Вот пример функций частного класса:
class foo():
def bar(self): pass
def __bar(self): pass
f = foo()
f.bar() # this call succeeds
f.__bar() # this call fails
Ответ 5
Вы можете добавить внутреннюю функцию:
def public(self, args):
def private(self.root, data):
if (self.root != None):
pass #do something with data
Нечто подобное, если вам действительно нужен такой уровень конфиденциальности.
Ответ 6
Это древний вопрос, но в стандартной документации теперь рассматриваются как частные, так и частные символы (одно подчеркивание) и класс-частный (два символа подчеркивания):
Учебник Python " Classes "Частные переменные
Ответ 7
встроенный с замыканиями или функциями является одним из способов. Это часто встречается в JS, но не требуется для не браузерных платформ или работников браузеров.
В Python это кажется немного странным, но если что-то действительно нужно скрыть, это может быть способом. Более конкретно, использование Python API и хранение вещей, которые должны быть скрыты в C (или другом языке), возможно, лучший способ. В противном случае я бы пошел, чтобы поместить код в функцию, вызвать ее и заставить возвращать элементы, которые вы хотите экспортировать.
Ответ 8
Python имеет три режима через., закрытый, общедоступный и защищенный. При этом доступен доступ только к общедоступному режиму. Частные и защищенные модули нельзя вызывать из-за пределов модуля, то есть при импорте.