Oto inne podejście.
""" Subclass of tuple with named fields """
from operator import itemgetter
from inspect import signature
class MetaTuple(type):
""" metaclass for NamedTuple """
def __new__(mcs, name, bases, namespace):
cls = type.__new__(mcs, name, bases, namespace)
names = signature(cls._signature).parameters.keys()
for i, key in enumerate(names):
setattr(cls, key, property(itemgetter(i)))
return cls
class NamedTuple(tuple, metaclass=MetaTuple):
""" Subclass of tuple with named fields """
@staticmethod
def _signature():
" Override in subclass "
def __new__(cls, *args):
new = super().__new__(cls, *args)
if len(new) == len(signature(cls._signature).parameters):
return new
return new._signature(*new)
if __name__ == '__main__':
class Point(NamedTuple):
" Simple test "
@staticmethod
def _signature(x, y, z): # pylint: disable=arguments-differ
" Three coordinates "
print(Point((1, 2, 4)))
Jeśli to podejście ma jakąkolwiek zaletę, jest to prostota. Byłoby prostsze, ale bez numeru NamedTuple.__new__
, który służy tylko do wymuszania liczby elementów. Bez tego szczęśliwie dopuszcza dodatkowe anonimowe elementy poza nazwane, a podstawowym efektem pominięcia elementów jest IndexError
dla pominiętych elementów podczas uzyskiwania dostępu do nich po nazwie (przy niewielkiej pracy, którą można przetłumaczyć na AttributeError
). Komunikat o błędzie niepoprawnego liczenia elementów jest nieco dziwny, ale ma to decydujące znaczenie. Nie spodziewałbym się, że to zadziała z Pythonem 2.
Jest miejsce na dalsze komplikacje, takie jak metoda __repr__
. Nie mam pojęcia, jak porównanie wydajności z innymi implementacjami (może pomóc buforowanie długości podpisu), ale zdecydowanie preferuję konwencję wywoływania w porównaniu z implementacją natywną namedtuple
.
hmmm. to na pewno na ogół odpowiada na pytanie, ale chciałbym wiedzieć, jakie są te niespodziewane problemy. w zależności od tego, czym były, problemy mogą dotyczyć samych metaclasses, w którym to przypadku mogą one zostać naprawione. Wydaje się również, że odpowiedź na ten komentarz 2,5 roku później wywołuje pewne realne problemy, które niektórzy mogą mieć. w każdym razie, dzięki za link - dużo informacji. –
Nigdy tak naprawdę nie kupiłem tego. Zawsze wydawało mi się, że odpowiedź brzmi: "ponieważ Raymond Hettinger jest w porządku z użyciem dziwnych hacków". – BrenBarn
jako osoba, która się uczy, to naprawdę daje mi pauzę, aby zobaczyć coś takiego w standardowej bibliotece. założyłem, że standardowa biblioteka będzie dobrym miejscem do sprawdzenia, jak powinien wyglądać "dobry kod". ale użycie 'exec' w taki sposób wydaje się, jak powiedział komentator powyżej, jak włamanie i jest to trochę rozczarowujące. metaclasses są całkiem niesamowite, ale jeśli standardowa biblioteka sama używa ich w tak oczywistej sytuacji, jaki jest sens ich posiadania? –