以下を検討してください。
items = []
items.append("apple")
items.append("orange")
items.append("banana")
# FAKE METHOD:
items.amount() # Should return 3
リスト内の要素の数を取得するにはどうすればよいitems
ですか?
以下を検討してください。
items = []
items.append("apple")
items.append("orange")
items.append("banana")
# FAKE METHOD:
items.amount() # Should return 3
リスト内の要素の数を取得するにはどうすればよいitems
ですか?
回答:
リストのサイズを取得する方法は?
リストのサイズを調べるには、組み込み関数を使用します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
その両方より読みやすく、よりパフォーマンスです。
これは「すぐに使える」機能としてはるかに理にかなっているため、役に立たないかもしれませんが、かなり単純なハックは、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
プロパティがあるという利点もあります。
いつものように、あなたの走行距離は異なる場合があります。
length = property(len)
1行のラッパー関数を実行してスキップし、len
あなたのプロパティでドキュメント/イントロスペクションを保持することができます。
それに加えlen
てoperator.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__
メソッドの代わりに関数を使用する方が常に安全です。
以前に与えられた例としてあなたの質問に答える:
items = []
items.append("apple")
items.append("orange")
items.append("banana")
print items.__len__()
__foo__
これは単なる慣例であり、Pythonシステムがユーザー名と競合しない名前を使用する方法です。2.:_foo
これは単なる慣例であり、プログラマーが変数がプライベートであることを示すための方法です(Pythonでそれが意味するものは何でも)。3.:__foo
これには本当の意味があります。インタプリタは、この名前を_classname__foo
別のクラスの類似の名前と重複しないようにするために、この名前をに置き換えます。* Pythonの世界では、他の形式のアンダースコアは意味を持ちません。*これらの規則では、クラス、変数、グローバルなどに違いはありません。
また、完全性(主に教育的)のために、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
インクリメントにも使用します。
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整数はlongs
Python 3以降と同じように保存されます。