Python 3.1 での変更点を読むと、何かが見つかりました...予期しない:
Sys.version_info Tupleは、 Tuple という名前になりました。
名前付きタプルについてはこれまで一度も聞いたことがありませんでしたが、要素は数字で(タプルやリストのように)、またはキーで索引付け(dictsのように)できると思いました。それらが両方向で索引付けされるとは思わなかった。
したがって、私の質問は次のとおりです。
名前付きタプルは、基本的に作成が簡単な軽量のオブジェクト型です。名前付きタプルインスタンスは、オブジェクトのような変数の逆参照または標準のタプル構文を使用して参照できます。これらは、不変であることを除き、struct
または他の一般的なレコードタイプと同様に使用できます。これらはPython 2.6およびPython 3.0で追加されましたが、 Python 2.4での実装のレシピ があります。
たとえば、ポイントをTuple (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的で読みやすくなると思われる場合は、タプルの代わりに名前付きタプルを使用する必要があります。私は個人的に、特に関数にパラメーターとして渡すときに、非常に単純な値型を表すためにそれらを使用し始めました。 Tupleパッキングのコンテキストを見ることなく、関数をより読みやすくします。
さらに、関数を持たない通常のimmutableクラス、フィールドのみを置き換えることもできます。名前付きTuple型を基本クラスとして使用することもできます。
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()
を使用して辞書に変換でき、通常のすべての辞書関数で操作できます。
すでに述べたように、これらの例が作成された詳細については、 ドキュメントを確認 する必要があります。
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)
タプルとは何ですか?
名前付きタプルはタプルです。
それはタプルができるすべてのことをします。
しかしそれは単なるタプル以上のものです。
これはTupleの特定のサブクラスで、名前付きフィールドと固定長で、プログラム的にあなたの仕様に合わせて作成されています。
たとえば、これはTupleのサブクラスを作成し、固定長(この場合は3)であることを除けば、Tupleが使用されている場所ならどこでも使用できます。これはLiskovの代用性として知られています。
>>> 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']
名前付きタプルを理解するには、最初にタプルとは何かを知る必要があります。 Tupleは本質的に不変の(メモリ内でその場で変更することはできません)リストです。
これが通常のTupleの使い方です。
>>> student_Tuple = 'Lisa', 'Simpson', 'A'
>>> student_Tuple
('Lisa', 'Simpson', 'A')
>>> student_Tuple[0]
'Lisa'
>>> student_Tuple[1]
'Simpson'
>>> student_Tuple[2]
'A'
繰り返し解凍してTupleを拡張できます。
>>> 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
通常のタプルの代わりに名前付きタプルを使用すべきなのはなぜですか?
コード内で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)
なぜ、いつ、私は名前付きタプルの代わりに通常のタプルを使用すべきですか?
名前付きタプルの使用からタプルへの切り替えは、おそらく回帰です。追加のコードによるコストが、Tupleを使用した場合の読みやすさの向上に見合うだけの価値があるかどうかを中心に、設計の最前線で決定します。
名前付きタプルとタプルで使用される追加のメモリはありません。
「名前付きリスト」(名前付き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).__+ 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
namedtuplesは素晴らしい機能です、彼らはデータのための完全なコンテナです。データを「保存」する必要がある場合は、次のようにタプルまたは辞書を使用します。
user = dict(name="John", age=20)
または
user = ("John", 20)
辞書はミュータブルでタプルより遅いので、辞書によるアプローチは圧倒的です。一方、タプルは不変かつ軽量ですが、データフィールド内の多数のエントリに対する読みやすさに欠けます。
namedtuplesは、2つのアプローチ、優れた読みやすさ、軽量さ、および不変性を兼ね備えた完璧な妥協策です(さらに、それらは多態性です)。
名前付きタプルは、このようなバージョンをチェックするコードとの下位互換性を可能にします。
>>> sys.version_info[0:2]
(3, 1)
この構文を使用して将来のコードをより明確にすることができます。
>>> sys.version_info.major
3
>>> sys.version_info.minor
1
コードを整理して読みやすくするための最も簡単な方法の1つです。タプルで起こっていることを自己文書化します。 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"
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"
最初の例で何が起こっているのかを理解するのはもっと難しいです。名前付きタプルを使用すると、各フィールドに名前が付きます。そしてあなたは位置やインデックスではなく名前でそれにアクセスします。 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
p.hue
ではなくp['hue']
。構文
collections.namedtuple(typename, field_names[, verbose=False][, rename=False])
['x', 'y', 'z']
、文字列x y z
(コンマなし、空白のみ)、またはx, y, z
のようなシーケンスにすることができます。True
の場合、無効なフィールド名は自動的に定位置名に置き換えられます。たとえば、['abc', 'def', 'ghi','abc']
は['abc', '_1', 'ghi', '_3']
に変換され、キーワード'def'
(これは関数を定義するための予約語です)と重複するフィールド名'abc'
を削除します。True
の場合、クラス定義は構築される直前に表示されます。必要に応じて、名前付きタプルにその位置からアクセスできます。 p[1] == p.saturation
。それはまだ通常のタプルのように開梱します。
通常のTupleメソッド がすべてサポートされています。例:min()、max()、len()、in、not in、連結(+)、インデックス、スライスなど。そして、namedtupleにはいくつか追加のものがあります。注:これらはすべてアンダースコアで始まります。 _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)
注意 :フィールド名は引用符で囲まないでください。それらはここのキーワードです。 覚えておいてください :タプルはtupleという名前で_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
最後のもので何が起こりましたか?括弧内の項目は反復可能であるべきです。そのため、かっこ内のリストまたはTupleは機能しますが、反復可能変数として囲むことなく値のシーケンスを実行するとエラーが返されます。
_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
Tupleとは何ですか?
名前が示すように、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)
内部のPythonでは、Tupleという名前のコンテナをうまく利用できます。これはクラスの定義を作成するために使用でき、元のTupleのすべての機能を備えています。
名前付きTupleを使用すると、デフォルトのクラステンプレートに直接適用されて単純なクラスが生成されます。この方法では、読みやすさを向上させるために多くのコードを使用できます。
これを試して:
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
名前付きTupleを使用するもう1つの方法(新しい方法)は、パッケージの入力からNamedTupleを使用することです。 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, 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)