Как изменить методы в Python, чтобы сделать их приватными? - PullRequest
0 голосов
/ 02 ноября 2011

Я знаю, что в Python нет такой вещи, как истинная приватность, потому что иногда вам нужно следующее:

  • запрещают людям вызывать некоторые методы или предупреждают их, когда они делают , но позволяют им вызываться из других модулей
  • определяет, где используются эти методы и выдает предупреждение на консоли или даже исключение, это позволит вам начать помечать методы как приватные, не нарушая существующий код.
  • скрыть приватные методы от автозаполнения IDE (необязательно) - возможно, с использованием одного подчеркивания перед его именем. Теперь мне интересно, нашел ли кто-нибудь прекрасный способ получить такое поведение, может быть, тот, который использует annotations?

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

Последний пункт почти решен, вопрос только в том, стоит ли мне использовать одно или два подчеркивания?

Ответы [ 4 ]

7 голосов
/ 02 ноября 2011

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

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

Ваша IDE должна иметь настраиваемое автозаполнение.Если нет, используйте Emacs:)

1 голос
/ 02 ноября 2011

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

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

Вы можете использовать двойные подчеркивания перед именем метода;это вызовет искажение имени.

Подробнее см. 9.7 на этой странице: http://docs.python.org/tutorial/classes.htm.

Но это все еще не приватно;это можно назвать.

Что касается вызывающих исключений, изучите информацию об объекте и кадре.Есть тонна д и как на этом сайте об этом.

tl; dr Вы не можете сделать что-нибудь личное, но вы можете усложнить поиск

0 голосов
/ 02 ноября 2011

Вы можете украсить закрытые методы с помощью вызова warnings.warn.

Я не уверен, что вы имеете в виду, говоря о людях, но позволяя модулям вызывать методы.Различие заключается в том, что одно происходит в интерактивном режиме, а другое нет?Если это так, вы можете проверить, запускается ли python из интерактивного приглашения, проверив значение sys.path[0].

Когда python запускает скрипт, sys.path[0] равняется каталогу скрипта.Когда python запускает интерактивный сеанс, sys.path[0] устанавливается в пустую строку ''.Таким образом, чтобы предупредить людей, но не сценарии, вы можете сделать

import warnings
import functools

def warn_private(func):
    if not sys.path[0]:
        @functools.wraps(func)
        def wrapper(self,*args,**kwargs):
            warnings.warn('{f} is private'.format(f=func.__name__))
            return func(self,*args,**kwargs)
        return wrapper
    else:
        return func

class Foo(object):
    @warn_private
    def _bar(self):
        pass
0 голосов
/ 02 ноября 2011

Возможно, определите ваши приватные методы во внутреннем классе и получите к нему внутренний доступ, используя self._private.method:

class PublicObject(object):

    class PrivateObject(object):
        def __init__(self, public):
            self.public = public

        def private1(self):
            print "a private method, not visible outside the public wrapper on", id(self.public)

    def __init__(self):
        self._private = self.PrivateObject(self)

    def public1(self):
        print "a public method, which invokes a private one"
        return self._private.private1()

a = PublicObject()

print dir(a) # only shows public1, not private1; won't show private1 in most IDEs autocomplete

a.public1()
a.private1() # raises an exception
a._private.private1() # still possible to call private methods, but obvious when you are doing so

Если вы хотите, чтобы ProtectedObject имел видимость в цепочке наследования, создайте аналогичный атрибут _protected ииспользуйте __getattr__ для доступа к атрибутам и методам super(PublicObject,self.public)._protected.

Кстати, то, что вы спрашиваете, действительно выходит за рамки философии Python, и добавление этого косвенного обращения через составной объект приведет к понести расходы на исполнение.

...