อะไรคือ "ชื่อ tuples" ใน Python?


906

การอ่านการเปลี่ยนแปลงใน Python 3.1ฉันพบบางสิ่ง ... ที่ไม่คาดคิด:

tuple sys.version_info เป็นtuple ชื่อ :

ฉันไม่เคยได้ยินชื่อ tuples มาก่อนและฉันคิดว่าองค์ประกอบต่างๆสามารถจัดทำดัชนีโดยตัวเลข (เช่นใน tuples และรายการ) หรือโดยคีย์ (เช่นใน dicts) ฉันไม่เคยคาดหวังว่าพวกเขาจะได้รับการจัดทำดัชนีทั้งสองวิธี

ดังนั้นคำถามของฉันคือ:

  • สิ่งอันดับชื่ออะไร
  • วิธีใช้งาน
  • ทำไม / เมื่อใดฉันจึงควรใช้สิ่งอันดับชื่อแทนที่จะเป็นอันดับอันดับปกติ
  • ทำไม / เมื่อใดฉันจึงควรใช้สิ่งอันดับทั่วไปแทนที่จะเป็นสิ่งอันดับ?
  • มี "รายการที่ระบุชื่อ" (รุ่นที่ไม่แน่นอนของ tuple ที่มีชื่อ) หรือไม่?

คำตอบ:


1196

tuples ที่มีชื่อนั้นเป็นวัตถุประเภทที่เบาและง่ายต่อการสร้าง อินสแตนซ์ tuple ที่ระบุชื่อสามารถอ้างอิงได้โดยใช้การอ้างอิงตัวแปรคล้ายอ็อบเจ็กต์หรือไวยากรณ์ tuple มาตรฐาน พวกเขาสามารถนำมาใช้ในทำนองเดียวกันstructหรือประเภทบันทึกทั่วไปอื่น ๆ ยกเว้นว่าพวกเขาจะไม่เปลี่ยนรูป พวกเขาจะถูกเพิ่มเข้ามาใน Python 2.6 และ Python 3.0 แม้ว่าจะมีสูตรสำหรับการดำเนินงานในหลาม 2.4

(x, y)ยกตัวอย่างเช่นมันเป็นเรื่องธรรมดาที่จะเป็นตัวแทนของจุดที่เป็นขอบเขตของ สิ่งนี้นำไปสู่รหัสดังนี้:

pt1 = (1.0, 5.0)
pt2 = (2.5, 1.5)

from math import sqrt
line_length = sqrt((pt1[0]-pt2[0])**2 + (pt1[1]-pt2[1])**2)

การใช้ tuple ที่มีชื่อจะสามารถอ่านได้มากขึ้น:

from collections import namedtuple
Point = namedtuple('Point', 'x y')
pt1 = Point(1.0, 5.0)
pt2 = Point(2.5, 1.5)

from math import sqrt
line_length = sqrt((pt1.x-pt2.x)**2 + (pt1.y-pt2.y)**2)

อย่างไรก็ตาม tuples ที่ชื่อยังคงสามารถใช้งานร่วมกับ tuples ปกติได้ดังนั้นสิ่งต่อไปนี้จะยังคงใช้งานได้:

Point = namedtuple('Point', 'x y')
pt1 = Point(1.0, 5.0)
pt2 = Point(2.5, 1.5)

from math import sqrt
# use index referencing
line_length = sqrt((pt1[0]-pt2[0])**2 + (pt1[1]-pt2[1])**2)
 # use tuple unpacking
x1, y1 = pt1

ดังนั้นคุณควรใช้ tuples ที่มีชื่อแทนสิ่งอันดับที่ใดก็ตามที่คุณคิดว่าการจัดเรียงวัตถุจะทำให้โค้ดของคุณไพทอนและอ่านง่ายขึ้น โดยส่วนตัวแล้วฉันได้เริ่มใช้มันเพื่อเป็นตัวแทนของประเภทค่าที่ง่ายมากโดยเฉพาะอย่างยิ่งเมื่อส่งให้เป็นพารามิเตอร์ของฟังก์ชัน มันทำให้ฟังก์ชั่นอ่านง่ายขึ้นโดยไม่เห็นบริบทของการบรรจุสิ่งอันดับ

นอกจากนี้คุณยังสามารถแทนที่คลาสที่ไม่เปลี่ยนรูปแบบสามัญที่ไม่มีฟังก์ชันมีเฉพาะฟิลด์ที่มีเท่านั้น คุณสามารถใช้ประเภท tuple ที่มีชื่อของคุณเป็นคลาสพื้นฐาน:

class Point(namedtuple('Point', 'x y')):
    [...]

อย่างไรก็ตามเช่นเดียวกับ tuples คุณลักษณะใน tuples ที่ตั้งชื่อไว้จะไม่เปลี่ยนรูป:

>>> Point = namedtuple('Point', 'x y')
>>> pt1 = Point(1.0, 5.0)
>>> pt1.x = 2.0
AttributeError: can't set attribute

หากคุณต้องการเปลี่ยนค่าคุณต้องมีประเภทอื่น มีสูตรอาหารที่สะดวกสำหรับประเภทบันทึกที่ไม่แน่นอนซึ่งช่วยให้คุณสามารถตั้งค่าใหม่เป็นแอตทริบิวต์ได้

>>> from rcdtype import *
>>> Point = recordtype('Point', 'x y')
>>> pt1 = Point(1.0, 5.0)
>>> pt1 = Point(1.0, 5.0)
>>> pt1.x = 2.0
>>> print(pt1[0])
    2.0

ฉันไม่ทราบว่ามี "รายการที่กำหนดชื่อ" รูปแบบใดที่ช่วยให้คุณเพิ่มฟิลด์ใหม่ได้ คุณอาจต้องการใช้พจนานุกรมในสถานการณ์นี้ tuples ที่มีชื่อสามารถแปลงเป็นพจนานุกรมโดยใช้pt1._asdict()ซึ่งส่งคืน{'x': 1.0, 'y': 5.0}และสามารถดำเนินการกับฟังก์ชันพจนานุกรมปกติทั้งหมด

ตามที่ระบุไว้แล้วคุณควรตรวจสอบเอกสารประกอบสำหรับข้อมูลเพิ่มเติมจากตัวอย่างเหล่านี้ถูกสร้าง


35
จาก python 3.7, พิจารณาว่าดาต้าคลาสเป็นทางเลือก (backport มีให้ 3.6, แต่ไม่ใช่เวอร์ชั่นก่อนหน้า)
innov8

3
ในกรณีที่คุณต้องการประเภทบันทึกที่ไม่แน่นอน - ใช้คลาสที่เรียบง่ายพร้อมคำจำกัดความ__slots__
madzohan

เหตุผลหลักในการใช้ rcdtype ไม่ใช่ dataclasses คืออะไร
Voyager

ทางเลือกในการเขียนเป็นพจนานุกรมแอตทริบิวต์stackoverflow.com/questions/4984647/…
mrgloom

เนื่องจากนี่เป็นคำตอบที่คุณมักจะพบว่ามันอาจคุ้มค่าที่จะกล่าวถึงว่าขณะนี้ยังมีtyping.NamedTupleคำแนะนำประเภทและสะดวกสำหรับการทำคลาสย่อย
DerWeh

101

namedtupleเป็นฟังก์ชันจากโรงงานสำหรับการสร้างคลาส tuple ด้วยคลาสนั้นเราสามารถสร้างสิ่งอันดับที่เรียกชื่อได้เช่นกัน

import collections

#Create a namedtuple class with names "a" "b" "c"
Row = collections.namedtuple("Row", ["a", "b", "c"], verbose=False, rename=False)   

row = Row(a=1,b=2,c=3) #Make a namedtuple from the Row class we created

print row    #Prints: Row(a=1, b=2, c=3)
print row.a  #Prints: 1
print row[0] #Prints: 1

row = Row._make([2, 3, 4]) #Make a namedtuple from a list of values

print row   #Prints: Row(a=2, b=3, c=4)

5
พารามิเตอร์ verbose และเปลี่ยนชื่อถูกตั้งค่าเริ่มต้นเป็นเท็จโดยค่าเริ่มต้นดังนั้นพวกเขาไม่จำเป็นต้องตั้งค่านี้อย่างชัดเจน
Trismegistos

namedtuple is a factory function for making a tuple class.นั่นอาจเป็นคำตอบเดียวที่ถูกต้องในที่นี่: P
Mr_and_Mrs_D

90

สิ่งอันดับชื่ออะไร

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

44

namedtuples เป็นคุณสมบัติที่ยอดเยี่ยมมันเป็นคอนเทนเนอร์ที่สมบูรณ์แบบสำหรับข้อมูล เมื่อคุณต้อง "เก็บ" ข้อมูลคุณจะใช้สิ่งอันดับหรือพจนานุกรมเช่น:

user = dict(name="John", age=20)

หรือ:

user = ("John", 20)

วิธีการในพจนานุกรมกำลังครอบงำเนื่องจาก dict นั้นไม่แน่นอนและช้ากว่า tuples ในทางตรงกันข้าม tuples นั้นไม่เปลี่ยนรูปและมีน้ำหนักเบา แต่ขาดความสามารถในการอ่านสำหรับข้อมูลจำนวนมากในเขตข้อมูล

ชื่อว่า tuples เป็นการประนีประนอมที่สมบูรณ์แบบสำหรับสองวิธีที่มีความสามารถในการอ่านได้ดีมีน้ำหนักเบาและไม่เปลี่ยนรูป


9
โปรดทราบว่าชื่อ tuples ช้ากว่า dicts หากคุณเข้าถึงแอตทริบิวต์ของชื่อ: ntuple.foovs ntuple[1]ตัวหลังนั้นเร็วกว่ามาก เพิ่มเติมเกี่ยวกับมัน: stackoverflow.com/questions/2646157/…
Rotareti

28

ชื่อ tuples อนุญาตให้ใช้งานร่วมกันได้กับโค้ดที่ตรวจสอบรุ่นเช่นนี้

>>> sys.version_info[0:2]
(3, 1)

ในขณะที่อนุญาตให้โค้ดในอนาคตมีความชัดเจนมากขึ้นโดยใช้ไวยากรณ์นี้

>>> sys.version_info.major
3
>>> sys.version_info.minor
1

12

namedtuple

เป็นวิธีที่ง่ายที่สุดวิธีหนึ่งในการล้างรหัสของคุณและทำให้อ่านง่ายขึ้น มันบันทึกสิ่งที่เกิดขึ้นในทูเพิลด้วยตนเอง อินสแตนซ์ของ Namedtuples นั้นมีประสิทธิภาพเท่ากับหน่วยความจำเหมือนกับ tuples ทั่วไปเนื่องจากไม่มีพจนานุกรมต่ออินสแตนซ์ทำให้เร็วกว่าพจนานุกรม

from collections import namedtuple

Color = namedtuple('Color', ['hue', 'saturation', 'luminosity'])

 p = Color(170, 0.1, 0.6)
 if p.saturation >= 0.5:
     print "Whew, that is bright!"
 if p.luminosity >= 0.5:
     print "Wow, that is light"

โดยไม่มีการตั้งชื่อองค์ประกอบใน tuple มันจะอ่านดังนี้:

p = (170, 0.1, 0.6)
if p[1] >= 0.5:
    print "Whew, that is bright!"
if p[2]>= 0.5:
   print "Wow, that is light"

มันยากมากที่จะเข้าใจสิ่งที่เกิดขึ้นในตัวอย่างแรก ด้วย tuple ที่มีชื่อแต่ละฟิลด์จะมีชื่อ และคุณเข้าถึงได้โดยใช้ชื่อแทนตำแหน่งหรือดัชนี แทนการp[1]ที่เราสามารถเรียกมัน p.saturation ง่ายต่อการเข้าใจ และดูสะอาดตา

การสร้างอินสแตนซ์ของ namedtuple นั้นง่ายกว่าการสร้างพจนานุกรม

# dictionary
>>>p = dict(hue = 170, saturation = 0.1, luminosity = 0.6)
>>>p['hue']
170

#nametuple
>>>from collections import namedtuple
>>>Color = namedtuple('Color', ['hue', 'saturation', 'luminosity'])
>>>p = Color(170, 0.1, 0.6)
>>>p.hue
170

เมื่อใดที่คุณอาจใช้ namedtuple

  1. ตามที่ระบุไว้เพียง tuple ชื่อทำให้เข้าใจ tuples ง่ายขึ้นมาก ดังนั้นหากคุณต้องการอ้างอิงรายการใน tuple ให้สร้างเป็น tuple ที่มีชื่อ
  2. นอกจากการเบากว่าพจนานุกรมชื่อทูเปิลยังรักษาลำดับไม่เหมือนพจนานุกรม
  3. ดังในตัวอย่างข้างต้นมันง่ายกว่าที่จะสร้างอินสแตนซ์ของชื่อว่า tuple มากกว่าพจนานุกรม และการอ้างอิงรายการใน tuple ที่ตั้งชื่อนั้นดูสะอาดกว่าพจนานุกรม มากกว่าp.hue p['hue']

ไวยากรณ์

collections.namedtuple(typename, field_names[, verbose=False][, rename=False])
  • namedtuple อยู่ในไลบรารีคอลเล็กชัน
  • typename: นี่คือชื่อของคลาสย่อย tuple ใหม่
  • field_names: ลำดับของชื่อสำหรับแต่ละฟิลด์ มันอาจจะเป็นลำดับเช่นเดียวกับในรายการ['x', 'y', 'z']หรือสตริงx y z(ไม่มีเครื่องหมายจุลภาคเพียงช่องว่าง) x, y, zหรือ
  • เปลี่ยนชื่อ: หากเปลี่ยนชื่อเป็นชื่อTrueฟิลด์ที่ไม่ถูกต้องจะถูกแทนที่โดยอัตโนมัติด้วยชื่อตำแหน่ง ยกตัวอย่างเช่น['abc', 'def', 'ghi','abc']จะถูกแปลงเป็น['abc', '_1', 'ghi', '_3']กำจัดคำหลัก'def'(นับว่าเป็นคำสงวนสำหรับการกำหนดฟังก์ชั่น) และ 'abc'fieldname
  • verbose: ถ้า verbose คือTrueคำจำกัดความของคลาสจะถูกพิมพ์ก่อนที่จะถูกสร้างขึ้น

คุณยังคงสามารถเข้าถึงชื่อที่ตั้งชื่อตามตำแหน่งของพวกเขาหากคุณเลือก p[1] == p.saturation. มันยังคงคลายตัวเหมือนทูเปิลทั่วไป

วิธีการ

ทุกวิธี tuple ปกติได้รับการสนับสนุน เช่น min (), max (), len (), in, ไม่เข้า,, concatenation (+), index, slice, และอื่น ๆ อีกสองสามชื่อสำหรับ tuple หมายเหตุ: ทั้งหมดนี้เริ่มต้นด้วยการขีดเส้นใต้ _replace, ,_make_asdict

_replace ส่งคืนอินสแตนซ์ใหม่ของ tuple ที่มีชื่อแทนที่ฟิลด์ที่ระบุด้วยค่าใหม่

ไวยากรณ์

somenamedtuple._replace(kwargs)

ตัวอย่าง

>>>from collections import namedtuple

>>>Color = namedtuple('Color', ['hue', 'saturation', 'luminosity'])
>>>p = Color(170, 0.1, 0.6)

>>>p._replace(hue=87)
Color(87, 0.1, 0.6)

>>>p._replace(hue=87, saturation=0.2)
Color(87, 0.2, 0.6)

ประกาศ : ชื่อฟิลด์ไม่อยู่ในเครื่องหมายคำพูด พวกเขาเป็นคำหลักที่นี่ ข้อควรจำ : Tuples นั้นไม่เปลี่ยนรูป - แม้ว่าพวกมันจะชื่อ Tuples และมี_replaceวิธีการก็ตาม _replaceผลิตnewเช่น; มันไม่ได้ปรับเปลี่ยนต้นฉบับหรือเปลี่ยนค่าเดิม แน่นอนคุณสามารถบันทึกผลลัพธ์ใหม่ให้กับตัวแปรp = p._replace(hue=169)

_make

ทำให้อินสแตนซ์ใหม่จากลำดับที่มีอยู่หรือ iterable

ไวยากรณ์

somenamedtuple._make(iterable)

ตัวอย่าง

 >>>data = (170, 0.1, 0.6)
 >>>Color._make(data)
Color(hue=170, saturation=0.1, luminosity=0.6)

>>>Color._make([170, 0.1, 0.6])  #the list is an iterable
Color(hue=170, saturation=0.1, luminosity=0.6)

>>>Color._make((170, 0.1, 0.6))  #the tuple is an iterable
Color(hue=170, saturation=0.1, luminosity=0.6)

>>>Color._make(170, 0.1, 0.6) 
Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    File "<string>", line 15, in _make
TypeError: 'float' object is not callable

เกิดอะไรขึ้นกับอันสุดท้าย? รายการในวงเล็บควรเป็น iterable ดังนั้นรายการหรือทูเปิลในวงเล็บจึงทำงานได้ แต่ลำดับของค่าโดยไม่ต้องล้อมรอบในขณะที่การทำซ้ำส่งคืนข้อผิดพลาด

_asdict

ส่งคืนOrderedDictใหม่ซึ่งจับคู่ชื่อฟิลด์กับค่าที่เกี่ยวข้อง

ไวยากรณ์

somenamedtuple._asdict()

ตัวอย่าง

 >>>p._asdict()
OrderedDict([('hue', 169), ('saturation', 0.1), ('luminosity', 0.6)])

การอ้างอิง : https://www.reddit.com/r/Python/comments/38ee9d/intro_to_namedtuple/

นอกจากนี้ยังมีรายการชื่อซึ่งคล้ายกับชื่อ tuple แต่ไม่แน่นอน https://pypi.python.org/pypi/namedlist


โปรดสังเกตว่าว่าตามPEP8ขีดล่างเดียวถือว่าเป็นตัวบ่งชี้ "อ่อนแอ" ใช้ภายใน "กับพฤติกรรมของตัวเอง ระมัดระวังเมื่อใช้งานฟังก์ชั่นที่ขึ้นต้นด้วย_!
Jens

8

ทูเปิลชื่ออะไร

ตามชื่อที่แนะนำ namedtuple เป็น tuple ที่มีชื่อ ใน tuple มาตรฐานเราเข้าถึงองค์ประกอบโดยใช้ดัชนีในขณะที่ namedtuple อนุญาตให้ผู้ใช้กำหนดชื่อสำหรับองค์ประกอบ สิ่งนี้มีประโยชน์มากโดยเฉพาะอย่างยิ่งการประมวลผลไฟล์ csv (ค่าที่คั่นด้วยเครื่องหมายจุลภาค) และทำงานกับชุดข้อมูลที่ซับซ้อนและมีขนาดใหญ่ซึ่งรหัสจะยุ่งเหยิงกับการใช้ดัชนี (ไม่ใช่ pythonic)

วิธีใช้งาน

>>>from collections import namedtuple
>>>saleRecord = namedtuple('saleRecord','shopId saleDate salesAmout totalCustomers')
>>>
>>>
>>>#Assign values to a named tuple 
>>>shop11=saleRecord(11,'2015-01-01',2300,150) 
>>>shop12=saleRecord(shopId=22,saleDate="2015-01-01",saleAmout=1512,totalCustomers=125)

การอ่าน

>>>#Reading as a namedtuple
>>>print("Shop Id =",shop12.shopId)
12
>>>print("Sale Date=",shop12.saleDate)
2015-01-01
>>>print("Sales Amount =",shop12.salesAmount)
1512
>>>print("Total Customers =",shop12.totalCustomers)
125

ภาพจำลองที่น่าสนใจในการประมวลผล CSV:

from csv import reader
from collections import namedtuple

saleRecord = namedtuple('saleRecord','shopId saleDate totalSales totalCustomers')
fileHandle = open("salesRecord.csv","r")
csvFieldsList=csv.reader(fileHandle)
for fieldsList in csvFieldsList:
    shopRec = saleRecord._make(fieldsList)
    overAllSales += shopRec.totalSales;

print("Total Sales of The Retail Chain =",overAllSales)

5

ใน Python ข้างในมีการใช้คอนเทนเนอร์ที่เรียกว่า tuple ที่มีชื่อมันสามารถใช้เพื่อสร้างนิยามของคลาสและมีคุณสมบัติทั้งหมดของ tuple ดั้งเดิม

การใช้ tuple ที่มีชื่อจะถูกนำไปใช้โดยตรงกับเทมเพลตคลาสเริ่มต้นเพื่อสร้างคลาสที่เรียบง่ายวิธีนี้ช่วยให้โค้ดจำนวนมากในการปรับปรุงความสามารถในการอ่านและสะดวกในการกำหนดคลาส


2

อีกวิธีหนึ่ง (วิธีใหม่) ในการใช้ชื่อ tuple คือการใช้ NamedTuple จากแพ็คเกจการพิมพ์: พิมพ์คำแนะนำใน namedupuple

ลองใช้ตัวอย่างคำตอบที่ดีที่สุดในโพสต์นี้เพื่อดูวิธีใช้

(1) ก่อนใช้ tuple ที่มีชื่อรหัสจะเป็นดังนี้:

pt1 = (1.0, 5.0)
pt2 = (2.5, 1.5)

from math import sqrt
line_length = sqrt((pt1[0]-pt2[0])**2 + (pt1[1]-pt2[1])**2)
print(line_length)

(2) ตอนนี้เราใช้ tuple ที่มีชื่อ

from typing import NamedTuple, Number

สืบทอดคลาส NamedTuple และกำหนดชื่อตัวแปรในคลาสใหม่ test เป็นชื่อของคลาส

class test(NamedTuple):
x: Number
y: Number

สร้างอินสแตนซ์จากคลาสและกำหนดค่าให้กับพวกเขา

pt1 = test(1.0, 5.0)   # x is 1.0, and y is 5.0. The order matters
pt2 = test(2.5, 1.5)

ใช้ตัวแปรจากอินสแตนซ์ในการคำนวณ

line_length = sqrt((pt1.x-pt2.x)**2 + (pt1.y-pt2.y)**2)
print(line_length)

1

ลองสิ่งนี้:

collections.namedtuple()

โดยทั่วไปnamedtuplesง่ายต่อการสร้างและประเภทวัตถุที่มีน้ำหนักเบา พวกมันเปลี่ยนสิ่งอันดับเป็นภาชนะที่สะดวกสำหรับงานง่าย ๆ ด้วยnamedtuplesคุณไม่จำเป็นต้องใช้ดัชนีจำนวนเต็มในการเข้าถึงสมาชิกของ tuple

ตัวอย่าง:

รหัส 1:

>>> from collections import namedtuple

>>> Point = namedtuple('Point','x,y')

>>> pt1 = Point(1,2)

>>> pt2 = Point(3,4)

>>> dot_product = ( pt1.x * pt2.x ) +( pt1.y * pt2.y )

>>> print dot_product
11

รหัส 2:

>>> from collections import namedtuple

>>> Car = namedtuple('Car','Price Mileage Colour Class')

>>> xyz = Car(Price = 100000, Mileage = 30, Colour = 'Cyan', Class = 'Y')

>>> print xyz

Car(Price=100000, Mileage=30, Colour='Cyan', Class='Y')
>>> print xyz.Class
Y

-1

คนอื่น ๆ ได้ตอบไปแล้ว แต่ฉันคิดว่าฉันยังมีอย่างอื่นที่จะเพิ่ม

Namedtuple อาจถูกมองว่าเป็นทางลัดในการกำหนดคลาส

classดูยุ่งยากและวิธีเดิมในการกำหนด

class Duck:
    def __init__(self, color, weight):
        self.color = color
        self.weight = weight
red_duck = Duck('red', '10')

    In [50]: red_duck
    Out[50]: <__main__.Duck at 0x1068e4e10>
    In [51]: red_duck.color
    Out[51]: 'red'

ส่วน namedtuple

from collections import namedtuple
Duck = namedtuple('Duck', ['color', 'weight'])
red_duck = Duck('red', '10')

In [54]: red_duck
Out[54]: Duck(color='red', weight='10')
In [55]: red_duck.color
Out[55]: 'red'

2
ขออภัยมีข้อผิดพลาด ชื่อ tuple ยังสนับสนุนเหล่านี้: red_duck[0]หรือหรือlen(red_duck) for x in red_duck: print(x)นอกจากนี้ชื่อ tuples จะไม่เปลี่ยนรูปเพื่อดำเนินการเหล่านี้จะล้มเหลว: ,red_duck[0] = 2 red_duck.foo = 'bar'เนื่องจากสิ่งเหล่านี้ไม่เปลี่ยนรูปทำให้สิ่งอันดับที่มีชื่อสามารถใช้เป็นdictกุญแจได้
Denilson Sá Maia

ใช่มันเป็นพื้นฐาน
แคลคูลัส

1
@ JawSaw ไม่ไม่ใช่ "พื้นฐาน" tuples ที่มีชื่อรองรับชุดการทำงานที่แตกต่างอย่างสิ้นเชิงจากคลาสปกติ ในขณะที่แก่นแท้ที่เรียกว่า tuples เป็นคลาส แต่นั่นไม่ได้หมายความว่าคลาสนั้นมีชื่อว่า tuples
connectyourcharger
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.