O que são "tuplas nomeadas" em Python?


907

Lendo as alterações no Python 3.1 , encontrei algo ... inesperado:

A tupla sys.version_info agora é uma tupla nomeada :

Eu nunca ouvi falar de tuplas nomeadas antes e pensei que os elementos pudessem ser indexados por números (como em tuplas e listas) ou por chaves (como em ditados). Eu nunca esperei que eles pudessem ser indexados nos dois sentidos.

Assim, minhas perguntas são:

  • O que são nomeadas tuplas?
  • Como usá-los?
  • Por que / quando devo usar tuplas nomeadas em vez de normais?
  • Por que / quando devo usar tuplas normais em vez de tuplas nomeadas?
  • Existe algum tipo de "lista nomeada" (uma versão mutável da tupla nomeada)?

Respostas:


1196

As tuplas nomeadas são basicamente tipos de objetos leves e fáceis de criar. As instâncias de tupla nomeadas podem ser referenciadas usando a desreferenciação de variável semelhante a objeto ou a sintaxe de tupla padrão. Eles podem ser usados ​​de maneira semelhante structou outros tipos de registros comuns, exceto que são imutáveis. Eles foram adicionados no Python 2.6 e Python 3.0, embora exista uma receita para implementação no Python 2.4 .

Por exemplo, é comum representar um ponto como uma tupla (x, y). Isso leva ao código como o seguinte:

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)

Usando uma tupla nomeada, ela se torna mais legível:

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)

No entanto, tuplas nomeadas ainda são compatíveis com versões anteriores, portanto, o seguinte ainda funcionará:

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

Portanto, você deve usar tuplas nomeadas em vez de tuplas em qualquer lugar que achar que a notação de objeto tornará seu código mais pitônico e mais facilmente legível . Pessoalmente, comecei a usá-los para representar tipos de valores muito simples, principalmente quando passá-los como parâmetros para funções. Torna as funções mais legíveis, sem ver o contexto da embalagem da tupla.

Além disso, você também pode substituir classes imutáveis comuns que não têm funções , apenas campos com elas. Você pode até usar seus tipos de tupla nomeados como classes base:

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

No entanto, como nas tuplas, os atributos nas tuplas nomeadas são imutáveis:

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

Se você deseja alterar os valores, precisa de outro tipo. Há uma receita útil para tipos de registros mutáveis que permitem definir novos valores para atributos.

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

No entanto, não conheço nenhuma forma de "lista nomeada" que permita adicionar novos campos. Você pode apenas querer usar um dicionário nessa situação. As tuplas nomeadas podem ser convertidas em dicionários usando pt1._asdict()quais retornos {'x': 1.0, 'y': 5.0}e podem ser operadas com todas as funções usuais do dicionário.

Como já observado, você deve verificar a documentação para obter mais informações a partir da qual esses exemplos foram construídos.


35
de python 3.7, considere também dataclasses como uma alternativa (backport disponível para 3.6, mas as versões não anteriores)
innov8

3
No caso de precisar tipo de registro mutável - uso classe simples com definido__slots__
madzohan

qual é a principal razão para usar rcdtype não dataclasses
Voyager

A alternativa ao dict é o dicionário de atributos stackoverflow.com/questions/4984647/…
mrgloom

Como esta é a resposta que você sempre encontra, vale a pena mencionar que agora também existe, o typing.NamedTupleque permite sugestões de tipo e é especialmente conveniente para subclassificar.
DerWeh

101

namedtuple é uma função de fábrica para criar uma classe de tupla. Com essa classe, podemos criar tuplas que podem ser chamadas pelo nome também.

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
parâmetros detalhados e renomear são padronizados como False por padrão, portanto, eles não precisam ser configurados para esse valor explicitamente.
Trismegistos

namedtuple is a factory function for making a tuple class.essa é provavelmente a única resposta correta aqui: P
Mr_and_Mrs_D

90

O que são nomeadas tuplas?

Uma tupla nomeada é uma tupla.

Faz tudo o que uma tupla pode.

Mas é mais do que apenas uma tupla.

É uma subclasse específica de uma tupla criada programaticamente para sua especificação, com campos nomeados e um comprimento fixo.

Isso, por exemplo, cria uma subclasse de tupla e, além de ter um comprimento fixo (neste caso, três), pode ser usado em qualquer lugar em que uma tupla seja usada sem quebrar. Isso é conhecido como substituibilidade de Liskov.

Novidade no Python 3.6 , podemos usar uma definição de classe comtyping.NamedTuplepara criar um nome nomeado:

from typing import NamedTuple

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

O acima é o mesmo que o abaixo, exceto que o acima tem adicionalmente anotações de tipo e uma sequência de caracteres. A seguir, está disponível no Python 2+:

>>> from collections import namedtuple
>>> class_name = 'ANamedTuple'
>>> fields = 'foo bar baz'
>>> ANamedTuple = namedtuple(class_name, fields)

Isso instancia:

>>> ant = ANamedTuple(1, 'bar', [])

Podemos inspecioná-lo e usar seus atributos:

>>> ant
ANamedTuple(foo=1, bar='bar', baz=[])
>>> ant.foo
1
>>> ant.bar
'bar'
>>> ant.baz.append('anything')
>>> ant.baz
['anything']

Explicação mais profunda

Para entender as tuplas nomeadas, primeiro você precisa saber o que é uma tupla. Uma tupla é essencialmente uma lista imutável (não pode ser alterada no local na memória).

Veja como você pode usar uma tupla regular:

>>> student_tuple = 'Lisa', 'Simpson', 'A'
>>> student_tuple
('Lisa', 'Simpson', 'A')
>>> student_tuple[0]
'Lisa'
>>> student_tuple[1]
'Simpson'
>>> student_tuple[2]
'A'

Você pode expandir uma tupla com a descompactação iterável:

>>> first, last, grade = student_tuple
>>> first
'Lisa'
>>> last
'Simpson'
>>> grade
'A'

Tuplas nomeadas são tuplas que permitem que seus elementos sejam acessados ​​por nome em vez de apenas índice!

Você faz um nomeado duplo como este:

>>> from collections import namedtuple
>>> Student = namedtuple('Student', ['first', 'last', 'grade'])

Você também pode usar uma única sequência com os nomes separados por espaços, um uso um pouco mais legível da API:

>>> Student = namedtuple('Student', 'first last grade')

Como usá-los?

Você pode fazer tudo o que as tuplas podem fazer (veja acima) e fazer o seguinte:

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

Um comentarista perguntou:

Em um script ou programa grande, onde geralmente se define uma tupla nomeada?

Os tipos que você cria com namedtuple são basicamente classes que você pode criar com taquigrafia fácil. Trate-os como aulas. Defina-os no nível do módulo, para que pickle e outros usuários possam encontrá-los.

O exemplo de trabalho, no nível global do módulo:

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

E isso demonstra a falha na pesquisa da definição:

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

Por que / quando devo usar tuplas nomeadas em vez de normais?

Use-os quando melhorar o seu código para que a semântica dos elementos da tupla seja expressa no seu código.

Você pode usá-los em vez de um objeto, caso contrário, use um objeto com atributos de dados imutáveis ​​e sem funcionalidade.

Você também pode subclassificá-los para adicionar funcionalidade, por exemplo :

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)

Por que / quando devo usar tuplas normais em vez de tuplas nomeadas?

Provavelmente seria uma regressão deixar de usar tuplas nomeadas para tuplas. A decisão inicial do projeto concentra-se em saber se o custo do código extra envolvido vale a legibilidade aprimorada quando a tupla é usada.

Não há memória extra usada por tuplas nomeadas versus tuplas.

Existe algum tipo de "lista nomeada" (uma versão mutável da tupla nomeada)?

Você está procurando um objeto com fenda que implemente toda a funcionalidade de uma lista com tamanho estatístico ou uma lista subclassificada que funcione como uma tupla nomeada (e que de alguma forma impeça a alteração de tamanho na lista).

Um exemplo agora expandido, e talvez até substituível de Liskov, do primeiro:

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

E, para usar, basta subclasse e defina __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

nomeduplos são um ótimo recurso, eles são um contêiner perfeito para dados. Quando você precisa "armazenar" dados, você usa tuplas ou dicionários, como:

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

ou:

user = ("John", 20)

A abordagem do dicionário é esmagadora, pois o dict é mutável e mais lento que as tuplas. Por outro lado, as tuplas são imutáveis ​​e leves, mas não têm legibilidade para um grande número de entradas nos campos de dados.

Os nomeados são o compromisso perfeito para as duas abordagens, com grande legibilidade, leveza e imutabilidade (além de serem polimórficos!).


9
Tenha em mente que namedtuples são a forma mais lenta do que dicts se você acessar seus atributos pelo nome: ntuple.foovs ntuple[1]o último é muito mais rápido. Mais sobre isso: stackoverflow.com/questions/2646157/…
Rotareti 19/07/2017

28

tuplas nomeadas permitem compatibilidade com versões anteriores com código que verifica a versão como esta

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

permitindo que o código futuro seja mais explícito usando esta sintaxe

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

12

nomeado

é uma das maneiras mais fáceis de limpar seu código e torná-lo mais legível. Ele auto-documenta o que está acontecendo na tupla. As instâncias de nomes nomeados são tão eficientes na memória quanto as tuplas regulares, pois não possuem dicionários por instância, tornando-os mais rápidos que os dicionários.

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"

Sem nomear cada elemento na tupla, ele seria assim:

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"

É muito mais difícil entender o que está acontecendo no primeiro exemplo. Com um nomeado duplo, cada campo tem um nome. E você acessa-o pelo nome, em vez de posição ou índice. Em vez de p[1], podemos chamá-lo de p.saturation. É mais fácil de entender. E parece mais limpo.

Criar uma instância do nome nomeado é mais fácil do que criar um dicionário.

# 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

Quando você pode usar o nomeado duplo

  1. Como acabamos de dizer, o duplo nomeado facilita o entendimento das tuplas. Portanto, se você precisar fazer referência aos itens da tupla, criá-los como nomes nomeados fará sentido.
  2. Além de ser mais leve que um dicionário, nomeado duplo também mantém a ordem diferente do dicionário.
  3. Como no exemplo acima, é mais simples criar uma instância de namedtuple do que dictionary. E a referência ao item na tupla nomeada parece mais limpa que um dicionário. p.hueao invés de p['hue'].

A sintaxe

collections.namedtuple(typename, field_names[, verbose=False][, rename=False])
  • namedtuple está na biblioteca de coleções.
  • typename: este é o nome da nova subclasse da tupla.
  • field_names: uma sequência de nomes para cada campo. Pode ser uma sequência como em uma lista ['x', 'y', 'z']ou string x y z(sem vírgulas, apenas espaço em branco) oux, y, z .
  • renomear: se renomear True, nomes de campo inválidos são substituídos automaticamente por nomes posicionais. Por exemplo, ['abc', 'def', 'ghi','abc']é convertido em ['abc', '_1', 'ghi', '_3'], eliminando a palavra-chave 'def'(já que é uma palavra reservada para definir funções) e o nome do campo duplicado'abc' .
  • verbose: se verbose for True, a definição da classe será impressa imediatamente antes de ser criada.

Você ainda pode acessar os nomeados por sua posição, se assim desejar. p[1] == p.saturation. Ele ainda é descompactado como uma tupla comum.

Métodos

Todos os métodos regulares de tupla são suportados. Ex: min (), max (), len (), in, não in, concatenação (+), índice, fatia, etc. E existem alguns adicionais para o nomeado duplo. Nota: todos eles começam com um sublinhado. _replace, _make, _asdict.

_replace Retorna uma nova instância da tupla nomeada, substituindo os campos especificados por novos valores.

A sintaxe

somenamedtuple._replace(kwargs)

Exemplo

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

Aviso : Os nomes dos campos não estão entre aspas; são palavras-chave aqui. Lembre - se : as tuplas são imutáveis ​​- mesmo que tenham nomes de nomeados e tenham o _replacemétodo. O _replaceproduz uma newinstância; não modifica o original nem substitui o valor antigo. Obviamente, você pode salvar o novo resultado na variável.p = p._replace(hue=169)

_make

Torna uma nova instância de uma sequência existente ou iterável.

A sintaxe

somenamedtuple._make(iterable)

Exemplo

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

O que aconteceu com o último? O item entre parênteses deve ser iterável. Portanto, uma lista ou tupla entre parênteses funciona, mas a sequência de valores sem incluir como iterável retorna um erro.

_asdict

Retorna um novo OrderedDict que mapeia os nomes dos campos para seus valores correspondentes.

A sintaxe

somenamedtuple._asdict()

Exemplo

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

Referência : https://www.reddit.com/r/Python/comments/38ee9d/intro_to_namedtuple/

Também existe uma lista nomeada, semelhante à tupla nomeada, mas mutável https://pypi.python.org/pypi/namedlist


Observe, porém, que, de acordo com o PEP8, um único sublinhado é considerado um indicador de "uso interno" fraco " com seu próprio comportamento. Cuidado ao usar as funções que começam com _!
Jens

8

O que é nomeado duplo?

Como o nome sugere, namedtuple é uma tupla com nome. Na tupla padrão, acessamos os elementos usando o índice, enquanto o namedtuple permite ao usuário definir o nome dos elementos. Isso é muito útil, especialmente o processamento de arquivos csv (valor separado por vírgula) e o trabalho com conjuntos de dados grandes e complexos, nos quais o código fica confuso com o uso de índices (não tão pitonicos).

Como usá-los?

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

Lendo

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

Cenário interessante no processamento de 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

No Python interno, existe um bom uso do contêiner chamado tupla nomeada, que pode ser usada para criar uma definição de classe e possui todos os recursos da tupla original.

O uso da tupla nomeada será aplicado diretamente ao modelo de classe padrão para gerar uma classe simples, esse método permite muito código para melhorar a legibilidade e também é muito conveniente ao definir uma classe.


2

Outra maneira (uma nova maneira) de usar tupla nomeada é usar NamedTuple ao digitar o pacote: Digite dicas no namedtuple

Vamos usar o exemplo da resposta principal neste post para ver como usá-lo.

(1) Antes de usar a tupla nomeada, o código é assim:

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) Agora usamos a tupla nomeada

from typing import NamedTuple, Number

herdar a classe NamedTuple e definir o nome da variável na nova classe. test é o nome da classe.

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

crie instâncias da classe e atribua valores a elas

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

use as variáveis ​​das instâncias para calcular

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

1

Tente o seguinte:

collections.namedtuple()

Basicamente, namedtuplessão fáceis de criar, tipos de objetos leves. Eles transformam tuplas em recipientes convenientes para tarefas simples. Comnamedtuples , você não precisa usar índices inteiros para acessar membros de uma tupla.

Exemplos:

Código 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

Código 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

Todo mundo já respondeu, mas acho que ainda tenho mais alguma coisa a acrescentar.

O nome nomeado pode ser considerado intuitivamente como um atalho para definir uma classe.

Veja uma maneira complicada e convencional de definir a 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'

Quanto a 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
Desculpe, mas isso está errado. A tupla nomeada também suporta estes: red_duck[0]ou len(red_duck)ou for x in red_duck: print(x). Além disso, as tuplas nomeadas são imutáveis, portanto, essas operações falharão: red_duck[0] = 2, red_duck.foo = 'bar'. Por serem imutáveis, as tuplas nomeadas podem ser usadas como dictchaves.
Denilson Sá Maia

Sim, é o básico.
Cálculo

1
@JawSaw Não, não é o "básico". As tuplas nomeadas suportam um conjunto de funcionalidades completamente diferente das classes regulares. Embora na essência as tuplas nomeadas sejam uma classe, isso não significa que as classes sejam nomeadas tuplas.
connectyourcharger
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.