튜플이란?
명명 된 튜플은 튜플입니다.
튜플이 할 수있는 모든 작업을 수행합니다.
그러나 그것은 단순한 튜플 이상입니다.
명명 된 필드와 고정 길이를 사용하여 사양에 따라 프로그래밍 방식으로 생성 된 튜플의 특정 하위 클래스입니다.
예를 들어, 이것은 튜플의 서브 클래스를 작성하며 고정 길이 (이 경우에는 3 개)를 제외하고 튜플이 중단없이 사용되는 모든 곳에서 사용될 수 있습니다. 이것은 Liskov 대체 가능성으로 알려져 있습니다.
Python 3.6의 새로운 기능으로 클래스 정의typing.NamedTuple
를 사용하여 namedtuple을 만들수 있습니다.
from typing import NamedTuple
class ANamedTuple(NamedTuple):
"""a docstring"""
foo: int
bar: str
baz: list
위의 유형 주석과 docstring이 추가로 있다는 점을 제외하면 위와 동일합니다. 아래는 Python 2 이상에서 사용할 수 있습니다.
>>> from collections import namedtuple
>>> class_name = 'ANamedTuple'
>>> fields = 'foo bar baz'
>>> ANamedTuple = namedtuple(class_name, fields)
이것은 그것을 인스턴스화합니다.
>>> ant = ANamedTuple(1, 'bar', [])
우리는 그것을 검사하고 그 속성을 사용할 수 있습니다 :
>>> ant
ANamedTuple(foo=1, bar='bar', baz=[])
>>> ant.foo
1
>>> ant.bar
'bar'
>>> ant.baz.append('anything')
>>> ant.baz
['anything']
더 깊은 설명
명명 된 튜플을 이해하려면 먼저 튜플이 무엇인지 알아야합니다. 튜플은 본질적으로 불변 (메모리 내에서 변경할 수 없음) 목록입니다.
정규 튜플을 사용하는 방법은 다음과 같습니다.
>>> student_tuple = 'Lisa', 'Simpson', 'A'
>>> student_tuple
('Lisa', 'Simpson', 'A')
>>> student_tuple[0]
'Lisa'
>>> student_tuple[1]
'Simpson'
>>> student_tuple[2]
'A'
반복 가능한 언 패킹으로 튜플을 확장 할 수 있습니다.
>>> first, last, grade = student_tuple
>>> first
'Lisa'
>>> last
'Simpson'
>>> grade
'A'
명명 된 튜플은 색인 대신 이름으로 요소에 액세스 할 수있는 튜플입니다!
다음과 같이 명명 된 튜플을 만듭니다.
>>> from collections import namedtuple
>>> Student = namedtuple('Student', ['first', 'last', 'grade'])
이름을 공백으로 구분하여 단일 문자열을 사용할 수 있으며 API를 약간 더 읽기 쉽게 사용할 수 있습니다.
>>> Student = namedtuple('Student', 'first last grade')
그것들을 사용하는 방법?
튜플이 할 수있는 모든 작업 (위 참조)을 수행하고 다음을 수행 할 수 있습니다.
>>> named_student_tuple = Student('Lisa', 'Simpson', 'A')
>>> named_student_tuple.first
'Lisa'
>>> named_student_tuple.last
'Simpson'
>>> named_student_tuple.grade
'A'
>>> named_student_tuple._asdict()
OrderedDict([('first', 'Lisa'), ('last', 'Simpson'), ('grade', 'A')])
>>> vars(named_student_tuple)
OrderedDict([('first', 'Lisa'), ('last', 'Simpson'), ('grade', 'A')])
>>> new_named_student_tuple = named_student_tuple._replace(first='Bart', grade='C')
>>> new_named_student_tuple
Student(first='Bart', last='Simpson', grade='C')
논평자가 물었다 :
큰 스크립트 나 프로그램에서 일반적으로 명명 된 튜플을 어디에 정의합니까?
당신이 만드는 유형 namedtuple
은 기본적으로 쉬운 속기로 만들 수있는 클래스입니다. 수업처럼 취급하십시오. 피클과 다른 사용자가 찾을 수 있도록 모듈 수준에서 정의하십시오.
글로벌 모듈 레벨의 실제 예제 :
>>> from collections import namedtuple
>>> NT = namedtuple('NT', 'foo bar')
>>> nt = NT('foo', 'bar')
>>> import pickle
>>> pickle.loads(pickle.dumps(nt))
NT(foo='foo', bar='bar')
그리고 이것은 정의를 찾지 못했음을 보여줍니다.
>>> def foo():
... LocalNT = namedtuple('LocalNT', 'foo bar')
... return LocalNT('foo', 'bar')
...
>>> pickle.loads(pickle.dumps(foo()))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
_pickle.PicklingError: Can't pickle <class '__main__.LocalNT'>: attribute lookup LocalNT on __main__ failed
왜 / 언제 일반 튜플 대신 명명 된 튜플을 사용해야합니까?
코드에 튜플 요소의 의미가 표현되도록 코드를 향상시킬 때 사용하십시오.
데이터 속성이 변경되지 않고 기능이없는 객체를 사용하려는 경우 객체 대신 객체를 사용할 수 있습니다.
서브 클래스로 기능을 추가 할 수도 있습니다 ( 예 :
class Point(namedtuple('Point', 'x y')):
"""adding functionality to a named tuple"""
__slots__ = ()
@property
def hypot(self):
return (self.x ** 2 + self.y ** 2) ** 0.5
def __str__(self):
return 'Point: x=%6.3f y=%6.3f hypot=%6.3f' % (self.x, self.y, self.hypot)
왜 명명 된 튜플 대신 일반 튜플을 사용해야합니까?
명명 된 튜플 사용에서 튜플로 전환하는 것은 아마도 회귀 일 것입니다. 선행 설계 결정은 튜플을 사용할 때 관련된 추가 코드의 비용이 가독성을 향상시킬 가치가 있는지 여부를 중심으로합니다.
명명 된 튜플 대 튜플에서 사용하는 추가 메모리는 없습니다.
어떤 종류의 "명명 된 목록"(명명 된 튜플의 변경 가능한 버전)이 있습니까?
정적 크기 목록의 모든 기능을 구현하는 슬롯 객체 또는 명명 된 튜플처럼 작동하는 하위 클래스 목록을 찾고 (어쨌든 목록의 크기가 변경되는 것을 차단합니다)
이제는 확장되었으며 아마도 Liskov로 대체 가능하며 첫 번째 예입니다.
from collections import Sequence
class MutableTuple(Sequence):
"""Abstract Base Class for objects that work like mutable
namedtuples. Subclass and define your named fields with
__slots__ and away you go.
"""
__slots__ = ()
def __init__(self, *args):
for slot, arg in zip(self.__slots__, args):
setattr(self, slot, arg)
def __repr__(self):
return type(self).__name__ + repr(tuple(self))
# more direct __iter__ than Sequence's
def __iter__(self):
for name in self.__slots__:
yield getattr(self, name)
# Sequence requires __getitem__ & __len__:
def __getitem__(self, index):
return getattr(self, self.__slots__[index])
def __len__(self):
return len(self.__slots__)
그리고 서브 클래스를 정의하고 사용하려면 다음을 수행하십시오 __slots__
.
class Student(MutableTuple):
__slots__ = 'first', 'last', 'grade' # customize
>>> student = Student('Lisa', 'Simpson', 'A')
>>> student
Student('Lisa', 'Simpson', 'A')
>>> first, last, grade = student
>>> first
'Lisa'
>>> last
'Simpson'
>>> grade
'A'
>>> student[0]
'Lisa'
>>> student[2]
'A'
>>> len(student)
3
>>> 'Lisa' in student
True
>>> 'Bart' in student
False
>>> student.first = 'Bart'
>>> for i in student: print(i)
...
Bart
Simpson
A