範囲関数はどのようにして次のいずれかを取ることができますか: 単一の引数、、range(stop)
またはrange(start, stop)
、またはrange(start, stop, step)
。variadic
引数を収集するような引数を使用して*arg
から、一連の if ステートメントを使用して、指定された引数の数に応じて正しい値を割り当てますか? 本質的に、range()
引数が 1 つある場合は停止引数として設定するか、2 つある場合はstart
、およびstop
、または 3 つある場合はそれらをそれぞれstop
、start
、およびとして設定することを指定しstep
ますか? 純粋な CPython で範囲を記述する場合、これをどのように行うかを知りたいです。
4 に答える
範囲は、1、2、または3つの引数を取ります。これは、、および明示的なコードを使用して実装しdef range(*args)
、0個または3個を超える引数を取得したときに例外を発生させることができます。
デフォルトの後にデフォルト以外の値を設定することはできないため、デフォルトの引数を使用して実装することはできませんでしたdef range(start=0, stop, step=1)
。これは基本的に、Pythonが各呼び出しの意味を理解する必要があるためです。したがって、2つの引数を使用して呼び出す場合、Pythonは、オーバーライドするデフォルトの引数を理解するためのルールが必要になります。そのようなルールを持つ代わりに、それは単に許可されていません。
デフォルトの引数を使用したい場合は、次のようにすることができます。def range(start=0, stop=object(), step=1)
そして、のタイプを明示的にチェックしstop
ます。
オープンソース ソフトウェアの優れた点は、ソースで調べるだけで済むことです。
(TL;DR: はい、可変引数を使用します)
if (PyTuple_Size(args) <= 1) {
if (!PyArg_UnpackTuple(args, "range", 1, 1, &stop))
return NULL;
stop = PyNumber_Index(stop);
if (!stop)
return NULL;
start = PyLong_FromLong(0);
if (!start) {
Py_DECREF(stop);
return NULL;
}
step = PyLong_FromLong(1);
if (!step) {
Py_DECREF(stop);
Py_DECREF(start);
return NULL;
}
}
else {
if (!PyArg_UnpackTuple(args, "range", 2, 3,
&start, &stop, &step))
return NULL;
/* Convert borrowed refs to owned refs */
start = PyNumber_Index(start);
if (!start)
return NULL;
stop = PyNumber_Index(stop);
if (!stop) {
Py_DECREF(start);
return NULL;
}
step = validate_step(step); /* Caution, this can clear exceptions */
if (!step) {
Py_DECREF(start);
Py_DECREF(stop);
return NULL;
}
}
lqc の回答は、C での実装方法を示しています。Python の組み込み関数が Python で記述されている場合、 がrange
どのように実装されるかについてまだ興味があるかもしれません。range
PyPy のソース コードを読んで確認できます。からpypy/module/__builtin__/functional.py
:
def range_int(space, w_x, w_y=NoneNotWrapped, w_step=1):
"""Return a list of integers in arithmetic position from start (defaults
to zero) to stop - 1 by step (defaults to 1). Use a negative step to
get a list in decending order."""
if w_y is None:
w_start = space.wrap(0)
w_stop = w_x
else:
w_start = w_x
w_stop = w_y
最初の引数 はspace
、私が見たすべての組み込み関数の引数として表示されるためself
、ユーザーが直接指定しないという点で似ていると思います。残りの 3 つの引数のうち、2 つにはデフォルト値があります。range
そのため、1 つ、2 つ、または 3 つの引数で呼び出すことができます。各引数がどのように解釈されるかは、指定された引数の数によって異なります。