Как получить доступ к закрытой переменной модуля Python из класса

В Python 3 префикс переменной класса делает его закрытым для моего искажения имени в классе. Как мне получить доступ к переменной модуля внутри класса?

Например, следующие два способа не работают:

__a = 3
class B:
    def __init__(self):
        self.a = __a
b = B()

результаты в:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in __init__
NameError: name '_B__a' is not defined

С помощью global тоже не помогает

__a = 3
class B:
    def __init__(self):
        global __a
        self.a = __a
b = B()

результаты в:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 4, in __init__
NameError: name '_B__a' is not defined

Бег locals() показывает, что переменная __a существует без изменений:

>>> locals()
{'__package__': None, '__name__': '__main__',
 '__loader__': <class '_frozen_importlib.BuiltinImporter'>,
 '__doc__': None, '__a': 3, 'B': <class '__main__.B'>,
 '__builtins__': <module 'builtins' (built-in)>, '__spec__': None}

[Новые строки добавлены для удобочитаемости]

Запуск одного и того же кода в модуле (в отличие от интерпретатора) приводит к точно такому же поведению. Использование Анаконды Python 3.5.1 :: Continuum Analytics, Inc.,

4 ответа

Решение

Это некрасиво, но Вы можете получить доступ к глобалам:

__a = 3
class B:
    def __init__(self):
        self.a = globals()["__a"]
b = B()

Вы также можете поместить это в диктовку:

__a = 3

d = {"__a": __a}

class B:
    def __init__(self):
        self.a = d["__a"]
b = B()

Или список, кортеж и т. Д. И индекс:

__a = 3

l = [__a]

class B:
    def __init__(self):
        self.a = l[0]
b = B()

Видимо, "официальный" ответ - не использовать двойные подчеркивания вне класса. Это подразумевается в документации здесь: https://docs.python.org/2/tutorial/classes.html. Кроме того, следующий (неудачный) отчет об ошибкеэтот ответ) делают его явным.

Вы создаете экземпляр класса, передавая переменную, которая не определена. размещение __a вне класса не будет работать, так как класс не увидит эту переменную. Что вы должны сделать вместо этого:

__a = 3
class B:
def __init__(self, __a):
   self.a = __a
b = B(__a)

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

Если вы собираетесь искажать имена так, как вы пытаетесь это сделать, я отсылаю вас к этой статье: http://shahriar.svbtle.com/underscores-in-python

Таким образом, мое решение того, что вы пытаетесь сделать, заключается в следующем:`

class R:
    global _R__a
    _R__a = 3
    def __init__(self):
        pass

class B:    
    global _R__a    
    def __init__(self):     
        self.a = _R__a
b = B()
print b.a
#3`

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

Другие вопросы по тегам