【问题标题】:What are "named tuples" in Python?Python中的“命名元组”是什么?
【发布时间】:2011-02-27 13:48:29
【问题描述】:

阅读changes in Python 3.1,我发现了一些……意想不到的东西:

sys.version_info 元组现在是一个命名元组

我以前从未听说过命名元组,我认为元素可以通过数字(如在元组和列表中)或键(如在 dicts 中)来索引。我从没想过它们会被双向索引。

因此,我的问题是:

  • 什么是命名元组?
  • 如何使用它们?
  • 为什么/何时应该使用命名元组而不是普通元组?
  • 为什么/何时应该使用普通元组而不是命名元组?
  • 是否有任何类型的“命名列表”(命名元组的可变版本)?

【问题讨论】:

    标签: python tuples namedtuple


    【解决方案1】:

    命名元组基本上是易于创建的轻量级对象类型。命名元组实例可以使用类似对象的变量解引用或标准元组语法来引用。它们可以与struct 或其他常见记录类型类似地使用,除了它们是不可变的。它们是在 Python 2.6 和 Python 3.0 中添加的,尽管有一个 recipe for implementation in Python 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)
    

    使用命名元组它变得更具可读性:

    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)
    

    但是,命名元组仍然向后兼容普通元组,因此以下方法仍然有效:

    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
    

    因此,您应该在任何您认为对象表示法会使您的代码更 Python 且更易于阅读的地方使用命名元组而不是元组。我个人已经开始使用它们来表示非常简单的值类型,尤其是在将它们作为参数传递给函数时。它使函数更具可读性,而无需查看元组打包的上下​​文。

    此外,您还可以用它们替换没有函数的普通不可变,只有字段。您甚至可以将命名元组类型用作基类:

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

    但是,与元组一样,命名元组中的属性是不可变的:

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

    如果您希望能够更改值,则需要另一种类型。 mutable recordtypes 有一个方便的配方,可让您为属性设置新值。

    >>> 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
    

    但是,我不知道有任何形式的“命名列表”可以让您添加新字段。在这种情况下,您可能只想使用字典。命名元组可以使用返回{'x': 1.0, 'y': 5.0}pt1._asdict() 转换为字典,并且可以使用所有常用的字典函数对其进行操作。

    如前所述,您应该check the documentation 了解更多关于构建这些示例的信息。

    【讨论】:

      【解决方案2】:

      什么是命名元组?

      命名元组是一个元组。

      它完成了元组所能做的一切。

      但它不仅仅是一个元组。

      它是元组的一个特定子类,它是按照您的规范以编程方式创建的,具有命名字段和固定长度。

      例如,这创建了一个元组的子类,除了具有固定长度(在本例中为三个)之外,它可以在任何使用元组的地方使用而不会中断。这称为 Liskov 可替代性。

      New in Python 3.6,我们可以使用带有typing.NamedTuple 的类定义来创建命名元组:

      from typing import NamedTuple
      
      class ANamedTuple(NamedTuple):
          """a docstring"""
          foo: int
          bar: str
          baz: list
      

      上面和下面一样,只是上面多了一个类型注释和一个文档字符串。以下内容在 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 创建的类型基本上是您可以用简单的速记方式创建的类。像对待班级一样对待他们。在模块级别定义它们,以便 pickle 和其他用户可以找到它们。

      工作示例,在全局模块级别:

      >>> 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
      

      为什么/何时应该使用命名元组而不是普通元组?

      当它改进您的代码以在您的代码中表达元组元素的语义时使用它们。

      如果您要使用具有不变数据属性且没有功能的对象,则可以使用它们代替对象。

      你也可以subclass them to add functionality, for example:

      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
      

      【讨论】:

        【解决方案3】:

        namedtuple 是用于制作元组类的工厂函数。使用该类,我们可以创建也可以按名称调用的元组。

        import collections
        
        #Create a namedtuple class with names "a" "b" "c"
        Row = collections.namedtuple("Row", ["a", "b", "c"])   
        
        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)
        

        【讨论】:

          【解决方案4】:

          namedtuple 是一个很棒的功能,它们是数据的完美容器。当您必须“存储”数据时,您将使用元组或字典,例如:

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

          或:

          user = ("John", 20)
          

          字典方法是压倒性的,因为 dict 是可变的并且比元组慢。另一方面,元组是不可变且轻量级的,但对于数据字段中的大量条目缺乏可读性。

          namedtuple 是这两种方法的完美折衷方案,它们具有出色的可读性、轻量级和不变性(而且它们是多态的!)。

          【讨论】:

          【解决方案5】:

          命名元组允许与像这样检查版本的代码向后兼容

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

          同时通过使用这种语法让未来的代码更加明确

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

          【讨论】:

            【解决方案6】:

            namedtuple

            是清理代码并使其更具可读性的最简单方法之一。它自我记录元组中发生的事情。 Namedtuples 实例与常规元组一样具有内存效率,因为它们没有每个实例的字典,这使得它们比字典更快。

            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"
            

            如果不命名元组中的每个元素,它将如下所示:

            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"
            

            要理解第一个示例中发生的事情要困难得多。使用命名元组,每个字段都有一个名称。您可以通过名称而不是位置或索引来访问它。我们可以将其称为 p.saturation,而不是 p[1]。更容易理解。而且看起来更干净。

            创建命名元组的实例比创建字典更容易。

            # 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
            

            什么时候可以使用命名元组

            1. 如前所述,namedtuple 使理解元组变得非常重要 更轻松。因此,如果您需要引用元组中的项目,那么 将它们创建为命名元组才有意义。
            2. 除了比字典更轻量之外,namedtuple 还 保持与字典不同的顺序。
            3. 和上面的例子一样,创建一个实例更简单 namedtuple 比字典。并引用命名中的项目 tuple 看起来比字典更干净。 p.hue 而不是 p['hue']

            语法

            collections.namedtuple(typename, field_names[, verbose=False][, rename=False])
            
            • namedtuple 在集合库中。
            • typename:这是新元组子类的名称。
            • field_names:每个字段的名称序列。它可以是一个序列 如列表['x', 'y', 'z'] 或字符串x y z(不带逗号,只需 空格)或x, y, z
            • rename:如果rename为True,则自动生成无效的字段名 替换为位置名称。例如,['abc', 'def', 'ghi','abc'] 转换为 ['abc', '_1', 'ghi', '_3'],消除了 关键字'def'(因为这是定义函数的保留字) 和重复的字段名'abc'
            • verbose:如果verbose为True,则只打印类定义 在建造之前。

            如果您愿意,您仍然可以按位置访问命名元组。 p[1] == p.saturation。它仍然像常规元组一样解包。

            方法

            支持所有regular tuple methods。例如:min()、max()、len()、in、not in、连接 (+)、index、slice 等。还有一些用于 namedtuple。注意:这些都以下划线开头。 _replace, _make, _asdict.

            _replace 返回命名元组的新实例,用新值替换指定字段。

            语法

            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)
            

            注意:字段名不用引号;它们是这里的关键字。 记住:元组是不可变的——即使它们被命名为元组并且具有_replace 方法。 _replace 产生一个 new 实例;它不会修改原始值或替换旧值。您当然可以将新结果保存到变量中。 p = p._replace(hue=169)

            _make

            根据现有序列或可迭代创建一个新实例。

            语法

            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
            

            最后一个是怎么回事?括号内的项目应该是可迭代的。所以括号内的列表或元组可以工作,但是没有作为可迭代对象括起来的值序列会返回错误。

            _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/

            还有一个与命名元组类似但可变的命名列表 https://pypi.python.org/pypi/namedlist

            【讨论】:

            • 请注意,根据PEP8,单个下划线被视为具有其自身行为的“弱“内部使用”指示符”。使用以_! 开头的函数时要小心!
            【解决方案7】:

            什么是命名元组?

            顾名思义,namedtuple 是一个有名字的元组。在标准元组中,我们使用索引访问元素,而 namedtuple 允许用户为元素定义名称。这非常方便,尤其是处理 csv(逗号分隔值)文件和处理复杂且大型的数据集,其中代码因使用索引而变得混乱(不是 Python 风格)。

            如何使用它们?

            >>>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)
            

            【讨论】:

              【解决方案8】:
              • 它们是元组的子类,并添加一个层以将属性名称分配给位置元素

              • 位于集合标准库模块中

                  from collections import namedtuple
                

              'namedtuple' 是一个生成新类的函数,该类继承自“元组”,但也提供“命名属性”来访问元组的元素。

              生成命名元组类

              “namedtuple”是一个类工厂。生成类需要一些东西

              • 我们要使用的类名

              • 我们要分配的字段名称序列,按照元组中元素的顺序。字段名称可以是任何有效的变量名称,但不能以“下划线”开头。

              • 调用“namedtuple”的返回值将是一个类。我们需要将该类分配给代码中的变量名,以便我们可以使用它来构造实例。通常,我们使用与生成的类的名称相同的名称。

                Coords = namedtuple('Coords', ['x', 'y'])

              • 现在我们可以创建坐标实例了:

                pt=Coords(10,20)
                
              • 我们可以通过多种方式将字段名称列表提供给 namedtuple 函数。

                • 字符串列表

                     namedtuple('Coords',['x','y'])
                  
                • 字符串元组

                     namedtuple('Coords',('x','y'))
                  
                • 字段名称由空格或逗号分隔的单个字符串

                     namedtuple('Coords','x, y'])
                  

              实例化命名元组

              创建命名元组类后,我们可以像普通类一样实例化它们。实际上,生成类的__new__方法使用我们提供的字段名作为参数名。

              Coords = namedtuple('Coords', ['x', 'y'])
              coord=Coords(10,20) 
              

              访问命名元组中的数据:

              由于命名元组只是元组,我们仍然可以像处理任何其他元组一样处理它们:按索引、切片、迭代

              Coords = namedtuple('Coords', ['x', 'y'])
              coord=Coords(10,20)       isinstance(coord,tuple) --> True # namedtuple is subclass of tuple
              
              x,y=coord  # Unpacking
              x=coord[0] # by index
              for e in coord:
                  print(e)
              
              • 现在我们还可以使用我们对类所做的字段名称来访问数据。

                   coord.x --> 10
                   coord.y --> 20
                
              • 由于namedtuple是继承自tuple生成的类,我们可以这样写:

                 class Coord(tuple):
                      ....
                
              • “coord”是一个元组,因此是不可变的

              namedtuple 的“重命名”关键字 arg

              字段名称不能以下划线开头

                Coords = namedtuple('Coords', ['x', '_y']) # does not work
              

              namedtuple 有一个仅关键字参数 rename(默认为 False),它将自动重命名任何无效的字段名称。

              Coords = namedtuple('Coords', ['x', '_y'], rename=True)
              

              字段名称“x”不会更改,但“_y”将更改为 _1。 1是字段名的索引。

              自省

              我们可以很容易地找出命名元组中的字段名称是否生成类。

                   Coords = namedtuple('Coords', ['x', '_y'])
                   Coords._fields -> ("x","_1")  # returns tuple
              

              如果您使用的python 版本低于3-3.7,我们实际上可以看到该类的代码是什么,使用类属性_source。由于实现该属性的内存使用可能存在一些问题,因此自 v3.7 起已将其删除

              将命名元组值提取到字典中

              Coords = namedtuple('Coords', ['x', 'y'])
              coord=Coords(10,20)
              coord._asdict()
                 {'x': 10, 'y': 20}
              

              我们为什么要使用命名元组

              如果你有这个课程:

              class Stock:
                  def __init__(self, symbol, year, month, day, open, high, low, close):
                      self.symbol = symbol
                      self.year = year
                      self.month = month
                      self.day = day
                      self.open = open 
                      self.high = high
                      self.low = low
                      self.close = close
              

              类方法 - vs - 元组方法

              djia.symbol              djia[0]     
              djia.open                djia[4]
              djia.close               djia[7]
              djia.high – djia.low     djia[5] – djia[6]
              

              如您所见,元组方法不可读。集合中的 namedtuple function 允许我们创建一个元组,该元组还具有附加到每个字段或属性的名称。这可以方便地通过“名称”引用元组结构中的数据,而不仅仅是依赖位置。但请记住,元组是不可变的,所以如果你想要可变性,请坚持使用类

              • 由于 namedtuple 是可迭代的,您可以使用可迭代的方法。例如,如果您将“坐标”作为类实例,则无法查找最大坐标。但是使用命名元组,您可以。

              【讨论】:

                【解决方案9】:

                在Python里面有一个很好用的容器叫做命名元组,它可以用来创建类的定义,并且具有原始元组的所有特性。

                使用命名元组将直接应用到默认的类模板生成一个简单的类,这种方法允许大量代码提高可读性,在定义类时也很方便。

                【讨论】:

                  【解决方案10】:

                  我认为值得使用类型提示添加有关 NamedTuples 的信息:

                  # dependencies
                  from typing import NamedTuple, Optional
                  
                  # definition
                  class MyNamedTuple(NamedTuple):
                      an_attribute: str
                      my_attribute: Optional[str] = None
                      next_attribute: int = 1
                  
                  # instantiation
                  my_named_tuple = MyNamedTuple("abc", "def")
                  # or more explicitly:
                  other_tuple = MyNamedTuple(an_attribute="abc", my_attribute="def")
                  
                  # access
                  assert "abc" == my_named_tuple.an_attribute
                  assert 1 == other_tuple.next_attribute
                  

                  【讨论】:

                    【解决方案11】:

                    使用命名元组的另一种方式(一种新方式)是使用来自打字包的 NamedTuple:Type hints in namedtuple

                    我们以本帖顶答案的例子来看看如何使用吧。

                    (1)在使用命名元组之前,代码是这样的:

                    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) 现在我们使用命名元组

                    from typing import NamedTuple
                    

                    继承 NamedTuple 类并在新类中定义变量名。 test 是类的名称。

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

                    从类中创建实例并为其赋值

                    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)
                    

                    【讨论】:

                      【解决方案12】:

                      试试这个:

                      collections.namedtuple()
                      

                      基本上,namedtuples 是易于创建的轻量级对象类型。 他们将元组变成方便的容器来完成简单的任务。 使用namedtuples,您不必使用整数索引来访问元组的成员。

                      例子:

                      代码 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
                      

                      【讨论】:

                        【解决方案13】:

                        其他人都已经回答过了,但我想我还有点要补充的。

                        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'
                        

                        【讨论】:

                        • 对不起,这是错误的。命名元组也支持这些:red_duck[0]len(red_duck)for x in red_duck: print(x)。此外,命名元组是不可变的,因此这些操作将失败:red_duck[0] = 2red_duck.foo = 'bar'。由于它们是不可变的,命名元组可以用作dict 键。
                        • 是的,这是基础。
                        • @JawSaw 不,这不是“基础”。命名元组支持与常规类完全不同的功能集。虽然命名元组本质上是一个类,但这并不意味着类是命名元组。
                        猜你喜欢
                        • 2021-06-02
                        • 2012-08-23
                        • 2020-12-17
                        • 2011-04-24
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        相关资源
                        最近更新 更多