Python any
とall
関数はどのように機能しますか?
any
そしてall
、イテラブルを取りTrue
、要素のいずれかおよびすべてが(それぞれ)である場合は返しますTrue
。
>>> any([0, 0.0, False, (), '0']), all([1, 0.0001, True, (False,)])
(True, True) # ^^^-- truthy non-empty string
>>> any([0, 0.0, False, (), '']), all([1, 0.0001, True, (False,), {}])
(False, False) # ^^-- falsey
イテラブルが空の場合、をany
返しFalse
、をall
返しますTrue
。
>>> any([]), all([])
(False, True)
今日は、クラスの生徒にデモall
をany
行っていました。空のイテラブルの戻り値について、ほとんど混乱していました。このように説明すると、多くの電球が点灯しました。
ショートカット動作
彼らany
とall
はどちらも、評価を停止できる条件を探します。私が最初に挙げた例では、リスト全体の各要素のブール値を評価する必要がありました。
(リストリテラル自体は遅延評価されないことに注意してください- イテレーターでそれを取得できますが、これは単なる説明目的です。)
以下は、あらゆるもののPython実装です。
def any(iterable):
for i in iterable:
if i:
return True
return False # for an empty iterable, any returns False!
def all(iterable):
for i in iterable:
if not i:
return False
return True # for an empty iterable, all returns True!
もちろん、実際の実装はCで記述されており、はるかに高いパフォーマンスを発揮しますが、上記のコードを置き換えると、この(またはその他の)回答のコードに対して同じ結果を得ることができます。
all
all
要素がであるかどうかを確認しFalse
(それが返される可能性があるFalse
)、要素がないTrue
場合はを返しますFalse
。
>>> all([1, 2, 3, 4]) # has to test to the end!
True
>>> all([0, 1, 2, 3, 4]) # 0 is False in a boolean context!
False # ^--stops here!
>>> all([])
True # gets to end, so True!
any
any
動作する方法は、要素があるかどうかをチェックすることですTrue
(そのため、True), then it returns
False if none of them were
True` を返すことができます)。
>>> any([0, 0.0, '', (), [], {}]) # has to test to the end!
False
>>> any([1, 0, 0.0, '', (), [], {}]) # 1 is True in a boolean context!
True # ^--stops here!
>>> any([])
False # gets to end, so False!
近道の行動を覚えておけば、真理値表を参照しなくても直感的に理解できると思います。
証拠all
とany
ショートカット:
まず、noisy_iteratorを作成します。
def noisy_iterator(iterable):
for i in iterable:
print('yielding ' + repr(i))
yield i
次に、例を使用して、リストを騒々しく反復します。
>>> all(noisy_iterator([1, 2, 3, 4]))
yielding 1
yielding 2
yielding 3
yielding 4
True
>>> all(noisy_iterator([0, 1, 2, 3, 4]))
yielding 0
False
私たちは見ることができますall
最初はFalseブールチェックの停止を。
そしてany
最初の真のブールチェックで停止します:
>>> any(noisy_iterator([0, 0.0, '', (), [], {}]))
yielding 0
yielding 0.0
yielding ''
yielding ()
yielding []
yielding {}
False
>>> any(noisy_iterator([1, 0, 0.0, '', (), [], {}]))
yielding 1
True
起源
上記を確認するためにソースを見てみましょう。
ここにソースがありany
ます:
static PyObject *
builtin_any(PyObject *module, PyObject *iterable)
{
PyObject *it, *item;
PyObject *(*iternext)(PyObject *);
int cmp;
it = PyObject_GetIter(iterable);
if (it == NULL)
return NULL;
iternext = *Py_TYPE(it)->tp_iternext;
for (;;) {
item = iternext(it);
if (item == NULL)
break;
cmp = PyObject_IsTrue(item);
Py_DECREF(item);
if (cmp < 0) {
Py_DECREF(it);
return NULL;
}
if (cmp > 0) {
Py_DECREF(it);
Py_RETURN_TRUE;
}
}
Py_DECREF(it);
if (PyErr_Occurred()) {
if (PyErr_ExceptionMatches(PyExc_StopIteration))
PyErr_Clear();
else
return NULL;
}
Py_RETURN_FALSE;
}
そしてここにソースがありall
ます:
static PyObject *
builtin_all(PyObject *module, PyObject *iterable)
{
PyObject *it, *item;
PyObject *(*iternext)(PyObject *);
int cmp;
it = PyObject_GetIter(iterable);
if (it == NULL)
return NULL;
iternext = *Py_TYPE(it)->tp_iternext;
for (;;) {
item = iternext(it);
if (item == NULL)
break;
cmp = PyObject_IsTrue(item);
Py_DECREF(item);
if (cmp < 0) {
Py_DECREF(it);
return NULL;
}
if (cmp == 0) {
Py_DECREF(it);
Py_RETURN_FALSE;
}
}
Py_DECREF(it);
if (PyErr_Occurred()) {
if (PyErr_ExceptionMatches(PyExc_StopIteration))
PyErr_Clear();
else
return NULL;
}
Py_RETURN_TRUE;
}