Как получить доступ к закрытой переменной модуля 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`
Таким образом, вы также будете более конкретны в отношении переменной, которую вы вызываете, без особого места для ее изменения позже. Надеюсь, это работает.