Питон:Доступ к статическим переменным класса изнутри класса
-
12-12-2019 - |
Вопрос
Итак, я пытаюсь создать класс, расширяющий список, с дополнительной возможностью сопоставления определенных специальных атрибутов для ссылки на определенные части списка.С использованием эта страница документа Py3k, я создал следующий код.Идея состоит в том, что (скажем, у меня есть sequence
экземпляр этого класса) sequence.seq
должен действовать точно так же, как sequence[0]
, и sequence.index
должен действовать точно так же, как sequence[2]
, и т. д.
Кажется, это работает отлично, за исключением того, что я не могу получить доступ к атрибутам сопоставления переменных класса в списке.
я нашел это ТАК вопрос, но либо ответ там неправильный, либо внутри методов что-то другое.Я также мог бы использовать self.__class__.__map__
, но поскольку мне нужна переменная класса внутри __getattribute__
, это отправляет меня в бесконечный рекурсивный цикл.
>>> class Sequence(list):
... __map__ = {'seq': 0,
... 'size': 1,
... 'index': 2,
... 'fdbid': 3,
... 'guide': 4,
... 'factors': 5,
... 'clas': 6,
... 'sorttime': 7,
... 'time': 8,
... 'res': 9,
... 'driver': 10 }
...
... def __setattr__(self, name, value): # "Black magic" meta programming to make certain attributes access the list
... print('Setting atr', name, 'with val', value)
... try:
... self[__map__[name]] = value
... except KeyError:
... object.__setattr__(self, name, value)
...
... def __getattribute__(self, name):
... print('Getting atr', name)
... try:
... return self[__map__[name]]
... except KeyError:
... return object.__getattribute__(self, name)
...
... def __init__(self, seq=0, size=0, index=0, fdbid=0, guide=None, factors=None,
... sorttime=None, time=None):
... super().__init__([None for i in range(11)]) # Be sure the list has the necessary length
... self.seq = seq
... self.index = index
... self.size = size
... self.fdbid = fdbid
... self.guide = ''
... self.time = time
... self.sorttime = sorttime
... self.factors = factors
... self.res = ''
... self.driver = ''
...
>>> a = Sequence()
Setting atr seq with val 0
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 31, in __init__
File "<stdin>", line 17, in __setattr__
NameError: global name '__map__' is not defined
Решение
Поскольку ни один из методов не вызывается до тех пор, пока Sequence
полностью определен, вы можете обратиться к Sequence.__map__
без каких-либо проблем.Например:
def __setattr(self, name, value):
print('Setting atr', name, 'with val', value)
try:
self[Sequence.__map__[name]] = value
except KeyError:
object.__setattr__(self, name, value)
Кроме того, вот демонстрация того, что к атрибутам класса можно получить доступ через объекты, пока не существует атрибут экземпляра с таким же именем:
class Foo:
i = 3
def __init__(self, overwrite):
if overwrite:
self.i = 4
f = Foo(False)
id(f.i) == id(Foo.i) # Should be True
f = Foo(True)
id(f.i) == id(Foo.i) # Should be False
Другие советы
Вы получаете доступ к атрибутам с помощью точки (.
), не с []
.Python не позволяет вам опускать self
ссылку, поэтому вам нужно получить доступ к переменной класса с помощью self.__map__
.Итак, если вы хотите получить доступ к элементу в этой позиции, вам нужно self[self.__map__[name]]
.
Обратите внимание: не рекомендуется использовать имена с двойным подчеркиванием в своих целях.Даже двух символов подчеркивания в начале (которые искажают имена) обычно больше, чем вам нужно.Если вы просто хотите указать пользователям, что __map__
атрибут не является частью общедоступного API, назовите его _map
.