Определение частных функций модуля в 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 неправильно, или я что-то неправильно понял? И есть ли какой-то способ сделать определить функцию модуля как частный?

8 174

8 ответов:

в Python "конфиденциальность" зависит от уровня согласия" согласных взрослых " - вы не можете силу он (больше, чем вы можете в реальной жизни;-). Одно начальное подчеркивание означает, что вы не должно чтобы получить доступ к нему "извне"-- два начальные подчеркивания (без конечных подчеркиваний) несут сообщение еще более сильно... но, в конце концов, это все еще зависит от социальной конвенции и консенсуса: самоанализ Python достаточно силен, чтобы вы не могу наручники каждый другой программист в мире, чтобы уважать ваши пожелания.

((кстати, хотя это очень секретно, почти то же самое относится и к C++: с большинством компиляторов простой #define private public строка перед #includeваша .h файл-это все, что нужно для хитрых кодеров, чтобы сделать хэш вашей "конфиденциальности"...!- ))

может быть путаница между класс приваты и модуль рядового.

A модуль частного начинается с один символ подчеркивания
Такой элемент не копируется вместе при использовании from <module_name> import * форма команды импорта; однако она импортируется при использовании import <moudule_name> синтаксис ( смотрите ответ Бена Вильгельма)
Просто удалите один символ подчеркивания из a.__num пример вопроса, и он не будет отображаться в модулях, которые импортируют a.py используя from a import * синтаксис.

A класс private начинается с два подчеркивания (Дандер ака например, двойного под-счет)
Такая переменная имеет свое имя "mangled", чтобы включить имя класса и т. д.
Он все еще может быть доступен вне логики класса, через искаженное имя.
Хотя имя mangling может служить как слабый прибор предохранения против несанкционированного доступа, свое основная цель состоит в том, чтобы предотвратить возможные столкновения имен с членами класса классов-предков. Смотрите забавную, но точную ссылку Алекса Мартелли на взрослые как он описывает соглашение, используемое в отношении этих переменных.

>>> 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
>>>

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

если вы определяете частные имена в модуле, эти имена будет импортируется в любой скрипт, который использует синтаксис, 'import module_name'. Таким образом, предполагая, что вы правильно определили в своем примере модуль private, _num, in 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
...

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

вот пример частных функций класса:

class foo():
    def bar(self): pass
    def __bar(self): pass

f = foo()
f.bar()   # this call succeeds
f.__bar() # this call fails

Это древний вопрос, но как частные модули (одно подчеркивание), так и частные классы (два подчеркивания) искаженные переменные теперь рассматриваются в стандартной документации:

Учебник По Python"классы"Частные Переменные

вы можете добавить внутреннюю функцию:

def public(self, args):
   def private(self.root, data):
       if (self.root != None):
          pass #do something with data

что-то вроде этого, если вам действительно нужен такой уровень конфиденциальности.

врезанный с закрытиями или функциями один путь. Это распространено в JS, хотя и не требуется для не-браузерных платформ или рабочих браузеров.

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

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