リストの要素数を取得するにはどうすればよいですか?


1938

以下を検討してください。

items = []
items.append("apple")
items.append("orange")
items.append("banana")

# FAKE METHOD:
items.amount()  # Should return 3

リスト内の要素の数を取得するにはどうすればよいitemsですか?


23
あなたは明らかにリストの要素の数を求めています。メモリ内のオブジェクトのサイズを検索するサーチャーがここに来る場合、これは実際に質問と回答です。Pythonでオブジェクトのサイズを確認するにはどうすればよいですか?
アーロンホール

回答:


2640

このlen()関数は、Pythonのいくつかの異なる型(組み込み型とライブラリ型の両方)で使用できます。例えば:

>>> len([1,2,3])
3

公式2.xのドキュメントはこちら: 公式3.xのドキュメントはこちら:len()
len()


239

リストのサイズを取得する方法は?

リストのサイズを調べるには、組み込み関数を使用しますlen

items = []
items.append("apple")
items.append("orange")
items.append("banana")

そしていま:

len(items)

3を返します。

説明

Pythonのすべては、リストを含むオブジェクトです。Cの実装では、すべてのオブジェクトに何らかのヘッダーがあります。

特に、Pythonで「サイズ」が指定されているリストやその他の類似の組み込みオブジェクトには、という属性ob_sizeがあり、オブジェクト内の要素の数がキャッシュされます。したがって、リスト内のオブジェクト数のチェックは非常に高速です。

ただし、リストのサイズがゼロかどうかを確認する場合は使用しないでください。len代わりに、リストをブール値のコンテキスト入れてください空の場合はFalse、それ以外の場合はTrueとして扱われます

ドキュメントから

len(s)

オブジェクトの長さ(アイテム数)を返します。引数は、シーケンス(文字列、バイト、タプル、リスト、範囲など)またはコレクション(辞書、セット、フリーズセットなど)のいずれかです。

lenで実装されている__len__、データモデルドキュメントから

object.__len__(self)

組み込み関数を実装するために呼び出されますlen()。オブジェクトの長さ、0以上の整数を返す必要があります。また、__nonzero__()[Python 2または__bool__()Python 3では]メソッドを定義せず、__len__()メソッドがゼロを返すオブジェクトは、ブール値のコンテキストではfalseと見なされます。

また、それが__len__リストのメソッドであることがわかります。

items.__len__()

3を返します。

len(長さ)を取得できる組み込み型

そして実際には、説明されているすべてのタイプについてこの情報を取得できることがわかります。

>>> all(hasattr(cls, '__len__') for cls in (str, bytes, tuple, list, 
                                            xrange, dict, set, frozenset))
True

len空または空でないリストのテストに使用しないでください

もちろん、特定の長さをテストするには、単純に等しいかどうかをテストします。

if len(items) == required_length:
    ...

ただし、長さゼロのリストまたはその逆をテストするための特別なケースがあります。その場合、等価性をテストしないでください。

また、次のことは行わないでください。

if len(items): 
    ...

代わりに、単に次のようにします。

if items:     # Then we have some items, not empty!
    ...

または

if not items: # Then we have an empty list!
    ...

私はなぜここに説明したが、短い中で、if itemsまたはif not itemsその両方より読みやすく、よりパフォーマンスです。


75

これは「すぐに使える」機能としてはるかに理にかなっているため、役に立たないかもしれませんが、かなり単純なハックは、lengthプロパティを持つクラスを構築することです。

class slist(list):
    @property
    def length(self):
        return len(self)

次のように使用できます。

>>> l = slist(range(10))
>>> l.length
10
>>> print l
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

基本的に、リストオブジェクトとまったく同じですが、OOPと相性の良いlengthプロパティがあるという利点もあります。

いつものように、あなたの走行距離は異なる場合があります。


19
あなたが知っているように、あなたはただlength = property(len)1行のラッパー関数を実行してスキップし、lenあなたのプロパティでドキュメント/イントロスペクションを保持することができます。
Tadhg McDonald-Jensen 2016

17

それに加えlenoperator.length_hint、Python 3.4以降が必要です。通常の場合、listどちらも同等ですがlength_hint、リスト反復子の長さを取得することができます。これは、特定の状況で役立ちます。

>>> from operator import length_hint
>>> l = ["apple", "orange", "banana"]
>>> len(l)
3
>>> length_hint(l)
3

>>> list_iterator = iter(l)
>>> len(list_iterator)
TypeError: object of type 'list_iterator' has no len()
>>> length_hint(list_iterator)
3

しかしlength_hint、定義上は「ヒント」にすぎないため、ほとんどの場合lenはより優れています。

へのアクセスを提案するいくつかの回答を見てきました__len__。これはlist、のような組み込みクラスを処理する場合は問題ありませんが、len(およびlength_hint)安全チェックを実装しているため、カスタムクラスで問題が発生する可能性があります。たとえば、どちらも負の長さまたは特定の値(sys.maxsize値)を超える長さを許可しません。したがってlen__len__メソッドの代わりに関数を使用する方が常に安全です。


8

以前に与えられた例としてあなたの質問に答える:

items = []
items.append("apple")
items.append("orange")
items.append("banana")

print items.__len__()

15
Pythonでは、アンダースコアで始まる名前は意味的に非公開のメソッドであり、ユーザーが使用することはできません。
アーロンホール

2
1.:__foo__これは単なる慣例であり、Pythonシステムがユーザー名と競合しない名前を使用する方法です。2.:_fooこれは単なる慣例であり、プログラマーが変数がプライベートであることを示すための方法です(Pythonでそれが意味するものは何でも)。3.:__fooこれには本当の意味があります。インタプリタは、この名前を_classname__foo別のクラスの類似の名前と重複しないようにするために、この名前をに置き換えます。* Pythonの世界では、他の形式のアンダースコアは意味を持ちません。*これらの規則では、クラス、変数、グローバルなどに違いはありません。
Shai Alon、

4
このQ&Aでは、特別なメソッドをユーザーとして直接使用してはいけない理由を説明しています。stackoverflow.com/ q / 40272161/541136
アーロンホール

@AaronHallですが、len関数の場合はほとんど同じです。非常に大きな変数の方が速い場合があります。ただし、私はあなたの要点を理解し、obj .__ len __()ではなくlen(obj)を使用する必要があります。
Shai Alon 2017

7

また、完全性(主に教育的)のために、len()関数を使用しなくても可能です。私はこれを良いオプションとして容認しません。PYTHONでこれをプログラムしないでください。ただし、これはアルゴリズムを学習するための目的に役立ちます。

def count(list):
    item_count = 0
    for item in list[:]:
        item_count += 1
    return item_count

count([1,2,3,4,5])

(コロンlist[:]は暗黙的であるため、オプションです。)

新しいプログラマのためのここでの教訓は、次のとおりです。ある時点でそれらを数えることなく、リスト内の項目の数を取得することはできません。問題は次のとおりです。それらをカウントするのに適したタイミングはいつですか たとえば、ソケットの接続システムコール(Cで記述)のような高性能コードは、connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);要素の長さを計算しません(呼び出しコードにその責任を与えます)。最初に長さを数えるステップを節約するために、アドレスの長さが渡されることに注意してください。別のオプション:計算上、渡すオブジェクト内に項目を追加するときに、項目の数を追跡することは意味があるかもしれません。これはメモリ内でより多くのスペースを占有することに注意してください。Naftuli Kayの回答を参照してください。

メモリーをより多く使用しながらパフォーマンスを改善するために長さを追跡する例。長さが追跡されるため、len()関数を使用しないことに注意してください。

class MyList(object):
    def __init__(self):
        self._data = []
        self.length = 0 # length tracker that takes up memory but makes length op O(1) time


        # the implicit iterator in a list class
    def __iter__(self):
        for elem in self._data:
            yield elem

    def add(self, elem):
        self._data.append(elem)
        self.length += 1

    def remove(self, elem):
        self._data.remove(elem)
        self.length -= 1

mylist = MyList()
mylist.add(1)
mylist.add(2)
mylist.add(3)
print(mylist.length) # 3
mylist.remove(3)
print(mylist.length) # 2

なんでfor item in list[:]:?なんでfor item in list:?また、+= 1インクリメントにも使用します。
Granny Aching

@GrannyAchingオプションのコロン(範囲指定子)を明示的に言及しました。私は教育目的でそこに範囲指定子を残しました-それが暗示されていることを知ることは有益です。リストタイプ[]も推論されます。これは、私のコードと同等です。また、インクリメント演算子は、既存の変数に1を追加することと同じですが、すべての場合で短くなります。したがって、それがあなたの推論である場合は、それを使用する必要があることに同意します。このコードは、とにかくどこでも本番環境に配置しないでください(プログラミングを学ぶ場合を除く)。
ジョナサンコマー

0

len()実際にどのように機能するかという点で、これはそのC実装です。

static PyObject *
builtin_len(PyObject *module, PyObject *obj)
/*[clinic end generated code: output=fa7a270d314dfb6c input=bc55598da9e9c9b5]*/
{
    Py_ssize_t res;

    res = PyObject_Size(obj);
    if (res < 0) {
        assert(PyErr_Occurred());
        return NULL;
    }
    return PyLong_FromSsize_t(res);
}

Py_ssize_tオブジェクトが持つことができる最大長です。PyObject_Size()オブジェクトのサイズを返す関数です。オブジェクトのサイズを判別できない場合は、-1を返します。その場合、このコードブロックが実行されます。

if (res < 0) {
        assert(PyErr_Occurred());
        return NULL;
    }

その結果、例外が発生します。それ以外の場合、このコードブロックが実行されます。

return PyLong_FromSsize_t(res);

resこれはC整数で、Pythonに変換されてlong返されます。すべてのPython整数はlongsPython 3以降と同じように保存されます。


3
Cの実装について知っている、または知っていることがなぜ重要なのですか?
cs95

この質問はCPythonに固有のものではないため、この回答は誤解を招く可能性があります。PyPy、IronPythonなどは、異なる方法で実装できます。
MSeifert
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.