Этот фрагмент может приблизить вас, но это не то же самое. Z
подклассы a list
и определяет __get__
для работы в качестве дескриптора.
class X(object):
def __init__(self, value):
self.value = value
def __get__(self, obj, objtype):
return self.value
def __repr__(self):
return "X(%r)" % self.value
class Z(list):
def __get__(self, obj, objtype):
return self
def __getitem__(self, index):
"""override brackets operator, suggested by Azat Ibrakov"""
list_item = super(Z, self).__getitem__(index)
try:
return list_item.value
except AttributeError:
return list_item
class _LiteralForContainerDescriptorZ(object):
def __getitem__(self, keys):
"""override brackets operator, basing on https://stackoverflow.com/a/37259917/2823074"""
if not isinstance(keys, tuple):
keys = (keys,)
assert not any(isinstance(key, slice) for key in keys) # avoid e.g. ZL[11:value, key:23, key2:value2]
return Z(keys)
ZL = _LiteralForContainerDescriptorZ()
Использование _LiteralForContainerDescriptorZ
необязательно, это дает немного более приятный синтаксис.
class Y(object):
a = X(1)
b = X(2)
c = Z([X(3.14), X(4)]) # define 'c' using constructor of Z class inherited from list
d = ZL[X(3.14), X(4)] # define 'd' using custom literal
y = Y()
for statement_to_print in [
"y.a", "y.b", "y.c","y.d", "y.c[0]", "y.c[1]", "y.d[0]",
]:
value = eval(statement_to_print)
print("{st:9} = {ev:<16} # type: {tp}".format(
st=statement_to_print, ev=value, tp=type(value).__name__))
Вызывая его, распечатки:
y.a = 1 # type: int
y.b = 2 # type: int
y.c = [X(3.14), X(4)] # type: Z
y.d = [X(3.14), X(4)] # type: Z
y.c[0] = 3.14 # type: float
y.c[1] = 4 # type: int
y.d[0] = 3.14 # type: float