สิ่งอันดับชื่ออะไร
tuple ที่มีชื่อคือ tuple
มันทำทุกอย่างที่ tuple ทำได้
แต่มันเป็นมากกว่าแค่สิ่งอันดับ
มันเป็นคลาสย่อยที่เฉพาะเจาะจงของสิ่งอันดับที่ถูกสร้างโดยทางโปรแกรมตามข้อกำหนดของคุณโดยมีฟิลด์ที่มีชื่อและความยาวคงที่
ยกตัวอย่างเช่นนี้สร้างคลาสย่อยของ tuple และนอกเหนือจากความยาวคงที่ (ในกรณีนี้คือสาม) มันสามารถใช้งานได้ทุกที่ที่ใช้ tuple โดยไม่ทำลาย สิ่งนี้เรียกว่าการทดแทน 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']
คำอธิบายที่ลึก
เพื่อให้เข้าใจ tuples ที่มีชื่อคุณต้องทราบว่า tuple คืออะไร tuple นั้นเป็นรายการที่ไม่เปลี่ยนรูปแบบ (ไม่สามารถเปลี่ยนได้ในหน่วยความจำ)
นี่คือวิธีที่คุณอาจใช้ tuple ปกติ:
>>> 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'
tuples ที่มีชื่อเป็นสิ่งอันดับที่อนุญาตให้องค์ประกอบของพวกเขาสามารถเข้าถึงได้โดยใช้ชื่อแทนที่จะเป็นเพียงดัชนี!
คุณสร้าง tuple แบบนี้:
>>> 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')
ผู้วิจารณ์ถามว่า:
ในสคริปต์หรือโปรแกรมขนาดใหญ่มักจะกำหนด tuple ที่ตั้งชื่อไว้ที่ไหน
ประเภทที่คุณสร้างขึ้น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
ทำไม / เมื่อใดฉันจึงควรใช้สิ่งอันดับชื่อแทนที่จะเป็นอันดับอันดับปกติ
ใช้เมื่อปรับปรุงโค้ดของคุณเพื่อให้ซีแมนทิกส์ขององค์ประกอบ tuple แสดงในรหัสของคุณ
คุณสามารถใช้พวกเขาแทนวัตถุถ้าคุณจะใช้วัตถุที่มีคุณสมบัติข้อมูลไม่เปลี่ยนแปลงและไม่มีฟังก์ชั่น
คุณยังสามารถคลาสย่อยเหล่านั้นเพื่อเพิ่มฟังก์ชันการทำงานตัวอย่างเช่น :
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)
ทำไม / เมื่อใดฉันจึงควรใช้สิ่งอันดับทั่วไปแทนที่จะเป็นสิ่งอันดับ?
มันอาจจะเป็นการถดถอยที่จะเปลี่ยนจากการใช้ tuples ที่มีชื่อเป็น tuples การตัดสินใจการออกแบบตรงไปตรงมารอบ ๆ ว่าค่าใช้จ่ายจากรหัสพิเศษที่เกี่ยวข้องมีมูลค่าการปรับปรุงการอ่านเมื่อใช้ tuple
ไม่มีหน่วยความจำเพิ่มเติมที่ใช้โดยชื่อ tuples กับ tuples
มี "รายการที่ระบุชื่อ" (รุ่นที่ไม่แน่นอนของ tuple ที่มีชื่อ) หรือไม่?
คุณกำลังมองหาวัตถุที่มีช่องเสียบซึ่งใช้ฟังก์ชั่นทั้งหมดของรายการที่มีขนาดคงที่หรือรายการที่มีคลาสย่อยซึ่งทำงานเหมือนกับ tuple ที่มีชื่อ
ตัวอย่างที่ขยายในขณะนี้และอาจแทน 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__)
และเพื่อใช้เพียง subclass และกำหนด__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