Python lặp qua phạm vi số nguyên

Phần phụ trợ @Unacademy • Dữ liệu @Amazon • Nền tảng @Practo. Viết về Ngôn ngữ bên trong và Toán học trong Khoa học Máy tính

Làm cho số nguyên Python có thể lặp lại

Xuất bản ngày 14 tháng 6 năm 2020Cập nhật lần cuối ngày 10 tháng 12 năm 2020

Iterables trong Python là các đối tượng và vùng chứa có thể được chuyển qua từng mục một, thường sử dụng vòng lặp

# The range(0, 7, 1) will iterate through values 0 to 6 and every time
# it will increment the current value by 1 i.e. the step.
>>> for x in range(0, 7, 1): print(x, end=" ")
0 1 2 3 4 5 6
0. Chẳng hạn, không phải tất cả các đối tượng đều có thể được lặp lại - chúng ta không thể lặp lại một số nguyên, đó là một giá trị số ít. Điều tốt nhất chúng ta có thể làm ở đây là lặp trên một dải số nguyên bằng cách sử dụng loại
# The range(0, 7, 1) will iterate through values 0 to 6 and every time
# it will increment the current value by 1 i.e. the step.
>>> for x in range(0, 7, 1): print(x, end=" ")
0 1 2 3 4 5 6
1 giúp chúng ta lặp qua tất cả các số nguyên trong dải
# The range(0, 7, 1) will iterate through values 0 to 6 and every time
# it will increment the current value by 1 i.e. the step.
>>> for x in range(0, 7, 1): print(x, end=" ")
0 1 2 3 4 5 6
2

Vì các số nguyên, về mặt cá nhân, không thể lặp lại, nên khi chúng tôi cố gắng thực hiện một

# The range(0, 7, 1) will iterate through values 0 to 6 and every time
# it will increment the current value by 1 i.e. the step.
>>> for x in range(0, 7, 1): print(x, end=" ")
0 1 2 3 4 5 6
3, nó sẽ đưa ra một ngoại lệ cho biết
# The range(0, 7, 1) will iterate through values 0 to 6 and every time
# it will increment the current value by 1 i.e. the step.
>>> for x in range(0, 7, 1): print(x, end=" ")
0 1 2 3 4 5 6
4. Vậy điều gì sẽ xảy ra nếu chúng ta thay đổi mã nguồn của Python và làm cho các số nguyên có thể lặp lại, chẳng hạn như mỗi lần chúng ta thực hiện một __________3, thay vì đưa ra một ngoại lệ, nó thực sự lặp lại các giá trị ____0_______6. Trong bài tiểu luận này, chúng ta sẽ đi qua chính xác điều đó, và toàn bộ chương trình nghị sự là

  • Python có thể lặp lại là gì?
  • Giao thức lặp là gì?
  • Thay đổi mã nguồn của Python và làm cho các số nguyên có thể lặp lại được và
  • Tại sao nó có thể là một ý tưởng tồi để làm như vậy?
Python Iterables

Bất kỳ đối tượng nào có thể lặp lại đều là Iterable trong Python. Danh sách này phải là danh sách có thể lặp lại phổ biến nhất hiện có và nó được sử dụng trong hầu hết mọi ứng dụng Python đơn lẻ - trực tiếp hoặc gián tiếp. Ngay cả trước khi lệnh người dùng đầu tiên được thực thi, trình thông dịch Python, trong khi khởi động, đã tạo danh sách

# The range(0, 7, 1) will iterate through values 0 to 6 and every time
# it will increment the current value by 1 i.e. the step.
>>> for x in range(0, 7, 1): print(x, end=" ")
0 1 2 3 4 5 6
7, để sử dụng nội bộ

Trong ví dụ bên dưới, chúng ta thấy cách một danh sách

# The range(0, 7, 1) will iterate through values 0 to 6 and every time
# it will increment the current value by 1 i.e. the step.
>>> for x in range(0, 7, 1): print(x, end=" ")
0 1 2 3 4 5 6
8 được lặp lại thông qua việc sử dụng vòng lặp
# The range(0, 7, 1) will iterate through values 0 to 6 and every time
# it will increment the current value by 1 i.e. the step.
>>> for x in range(0, 7, 1): print(x, end=" ")
0 1 2 3 4 5 6
0 và mỗi phần tử có thể được truy cập thông qua biến
PyObject * tp_iter(PyObject *);
0

>>> a = [2, 3, 5, 7, 11, 13]
>>> for x in a: print(x, end=" ")
2 3 5 7 11 13

Tương tự như

PyObject * tp_iter(PyObject *);
1,
# The range(0, 7, 1) will iterate through values 0 to 6 and every time
# it will increment the current value by 1 i.e. the step.
>>> for x in range(0, 7, 1): print(x, end=" ")
0 1 2 3 4 5 6
1 là một loại python cho phép chúng ta lặp lại các giá trị số nguyên bắt đầu bằng giá trị
PyObject * tp_iter(PyObject *);
3 và đi đến
PyObject * tp_iter(PyObject *);
4 trong khi bước qua các giá trị
PyObject * tp_iter(PyObject *);
5 mỗi lần.
# The range(0, 7, 1) will iterate through values 0 to 6 and every time
# it will increment the current value by 1 i.e. the step.
>>> for x in range(0, 7, 1): print(x, end=" ")
0 1 2 3 4 5 6
1 được sử dụng phổ biến nhất để triển khai vòng lặp
PyObject * tp_iter(PyObject *);
7 giống như C trong Python. Trong ví dụ dưới đây, vòng lặp
PyObject * tp_iter(PyObject *);
7 lặp lại trên một
# The range(0, 7, 1) will iterate through values 0 to 6 and every time
# it will increment the current value by 1 i.e. the step.
>>> for x in range(0, 7, 1): print(x, end=" ")
0 1 2 3 4 5 6
1 bắt đầu từ
PyTypeObject PyLong_Type = {
    ...

    "int",                                      /* tp_name */
    offsetof(PyLongObject, ob_digit),           /* tp_basicsize */
    sizeof(digit),                              /* tp_itemsize */
    ...
    0,                                          /* tp_iter */
    ...
};
0, đi đến
PyTypeObject PyLong_Type = {
    ...

    "int",                                      /* tp_name */
    offsetof(PyLongObject, ob_digit),           /* tp_basicsize */
    sizeof(digit),                              /* tp_itemsize */
    ...
    0,                                          /* tp_iter */
    ...
};
1 với một bước là
PyTypeObject PyLong_Type = {
    ...

    "int",                                      /* tp_name */
    offsetof(PyLongObject, ob_digit),           /* tp_basicsize */
    sizeof(digit),                              /* tp_itemsize */
    ...
    0,                                          /* tp_iter */
    ...
};
2 - tạo ra chuỗi
# The range(0, 7, 1) will iterate through values 0 to 6 and every time
# it will increment the current value by 1 i.e. the step.
>>> for x in range(0, 7, 1): print(x, end=" ")
0 1 2 3 4 5 6
6

# The range(0, 7, 1) will iterate through values 0 to 6 and every time
# it will increment the current value by 1 i.e. the step.
>>> for x in range(0, 7, 1): print(x, end=" ")
0 1 2 3 4 5 6

Ngoài

PyObject * tp_iter(PyObject *);
1 và
# The range(0, 7, 1) will iterate through values 0 to 6 and every time
# it will increment the current value by 1 i.e. the step.
>>> for x in range(0, 7, 1): print(x, end=" ")
0 1 2 3 4 5 6
1, những người khác là -
PyTypeObject PyLong_Type = {
    ...

    "int",                                      /* tp_name */
    offsetof(PyLongObject, ob_digit),           /* tp_basicsize */
    sizeof(digit),                              /* tp_itemsize */
    ...
    0,                                          /* tp_iter */
    ...
};
6,
PyTypeObject PyLong_Type = {
    ...

    "int",                                      /* tp_name */
    offsetof(PyLongObject, ob_digit),           /* tp_basicsize */
    sizeof(digit),                              /* tp_itemsize */
    ...
    0,                                          /* tp_iter */
    ...
};
7,
PyTypeObject PyLong_Type = {
    ...

    "int",                                      /* tp_name */
    offsetof(PyLongObject, ob_digit),           /* tp_basicsize */
    sizeof(digit),                              /* tp_itemsize */
    ...
    0,                                          /* tp_iter */
    ...
};
8,
PyTypeObject PyLong_Type = {
    ...

    "int",                                      /* tp_name */
    offsetof(PyLongObject, ob_digit),           /* tp_basicsize */
    sizeof(digit),                              /* tp_itemsize */
    ...
    0,                                          /* tp_iter */
    ...
};
9,
/*
 *  PyLongRangeIter_ZeroToN creates and returns a range iterator on long
 *  iterating on values in the range [0, n).
 *
 *  The function creates and returns a range iterator from 0 till the
 *  provided long value.
 */
PyObject *
PyLongRangeIter_ZeroToN(PyObject *long_obj)
{
    // creating a new instance of longrangeiterobject
    longrangeiterobject *it;
    it = PyObject_New(longrangeiterobject, &PyLongRangeIter_Type);

    // if unable to allocate memoty to it, return NULL.
    if (it == NULL)
        return NULL;

    // we set the start to 0
    it->start = _PyLong_Zero;

    // we set the step to 1
    it->step = _PyLong_One;

    // we set the index to 0, since we want to always start from the first
    // element of the iteration
    it->index = _PyLong_Zero;

    // we set the total length of iteration to be equal to the provided value
    it->len = long_obj;

    // we increment the reference count for each of the values referenced
    Py_INCREF(it->start);
    Py_INCREF(it->step);
    Py_INCREF(it->len);
    Py_INCREF(it->index);

    // downcast the iterator instance to PyObject and return
    return (PyObject *)it;
}
0,
/*
 *  PyLongRangeIter_ZeroToN creates and returns a range iterator on long
 *  iterating on values in the range [0, n).
 *
 *  The function creates and returns a range iterator from 0 till the
 *  provided long value.
 */
PyObject *
PyLongRangeIter_ZeroToN(PyObject *long_obj)
{
    // creating a new instance of longrangeiterobject
    longrangeiterobject *it;
    it = PyObject_New(longrangeiterobject, &PyLongRangeIter_Type);

    // if unable to allocate memoty to it, return NULL.
    if (it == NULL)
        return NULL;

    // we set the start to 0
    it->start = _PyLong_Zero;

    // we set the step to 1
    it->step = _PyLong_One;

    // we set the index to 0, since we want to always start from the first
    // element of the iteration
    it->index = _PyLong_Zero;

    // we set the total length of iteration to be equal to the provided value
    it->len = long_obj;

    // we increment the reference count for each of the values referenced
    Py_INCREF(it->start);
    Py_INCREF(it->step);
    Py_INCREF(it->len);
    Py_INCREF(it->index);

    // downcast the iterator instance to PyObject and return
    return (PyObject *)it;
}
1,
/*
 *  PyLongRangeIter_ZeroToN creates and returns a range iterator on long
 *  iterating on values in the range [0, n).
 *
 *  The function creates and returns a range iterator from 0 till the
 *  provided long value.
 */
PyObject *
PyLongRangeIter_ZeroToN(PyObject *long_obj)
{
    // creating a new instance of longrangeiterobject
    longrangeiterobject *it;
    it = PyObject_New(longrangeiterobject, &PyLongRangeIter_Type);

    // if unable to allocate memoty to it, return NULL.
    if (it == NULL)
        return NULL;

    // we set the start to 0
    it->start = _PyLong_Zero;

    // we set the step to 1
    it->step = _PyLong_One;

    // we set the index to 0, since we want to always start from the first
    // element of the iteration
    it->index = _PyLong_Zero;

    // we set the total length of iteration to be equal to the provided value
    it->len = long_obj;

    // we increment the reference count for each of the values referenced
    Py_INCREF(it->start);
    Py_INCREF(it->step);
    Py_INCREF(it->len);
    Py_INCREF(it->index);

    // downcast the iterator instance to PyObject and return
    return (PyObject *)it;
}
2 và
/*
 *  PyLongRangeIter_ZeroToN creates and returns a range iterator on long
 *  iterating on values in the range [0, n).
 *
 *  The function creates and returns a range iterator from 0 till the
 *  provided long value.
 */
PyObject *
PyLongRangeIter_ZeroToN(PyObject *long_obj)
{
    // creating a new instance of longrangeiterobject
    longrangeiterobject *it;
    it = PyObject_New(longrangeiterobject, &PyLongRangeIter_Type);

    // if unable to allocate memoty to it, return NULL.
    if (it == NULL)
        return NULL;

    // we set the start to 0
    it->start = _PyLong_Zero;

    // we set the step to 1
    it->step = _PyLong_One;

    // we set the index to 0, since we want to always start from the first
    // element of the iteration
    it->index = _PyLong_Zero;

    // we set the total length of iteration to be equal to the provided value
    it->len = long_obj;

    // we increment the reference count for each of the values referenced
    Py_INCREF(it->start);
    Py_INCREF(it->step);
    Py_INCREF(it->len);
    Py_INCREF(it->index);

    // downcast the iterator instance to PyObject and return
    return (PyObject *)it;
}
3. Python cũng cho phép chúng tôi tạo các lần lặp tùy chỉnh bằng cách tạo các đối tượng và kiểu tuân theo Giao thức Iterator

Iterator và giao thức Iterator

Python, giữ mọi thứ đơn giản, định nghĩa iterable là bất kỳ đối tượng nào tuân theo Giao thức Iterator;

  • /*
     *  PyLongRangeIter_ZeroToN creates and returns a range iterator on long
     *  iterating on values in the range [0, n).
     *
     *  The function creates and returns a range iterator from 0 till the
     *  provided long value.
     */
    PyObject *
    PyLongRangeIter_ZeroToN(PyObject *long_obj)
    {
        // creating a new instance of longrangeiterobject
        longrangeiterobject *it;
        it = PyObject_New(longrangeiterobject, &PyLongRangeIter_Type);
    
        // if unable to allocate memoty to it, return NULL.
        if (it == NULL)
            return NULL;
    
        // we set the start to 0
        it->start = _PyLong_Zero;
    
        // we set the step to 1
        it->step = _PyLong_One;
    
        // we set the index to 0, since we want to always start from the first
        // element of the iteration
        it->index = _PyLong_Zero;
    
        // we set the total length of iteration to be equal to the provided value
        it->len = long_obj;
    
        // we increment the reference count for each of the values referenced
        Py_INCREF(it->start);
        Py_INCREF(it->step);
        Py_INCREF(it->len);
        Py_INCREF(it->index);
    
        // downcast the iterator instance to PyObject and return
        return (PyObject *)it;
    }
    
    4 sẽ trả về một đối tượng lặp đã triển khai phương thức
    /*
     *  PyLongRangeIter_ZeroToN creates and returns a range iterator on long
     *  iterating on values in the range [0, n).
     *
     *  The function creates and returns a range iterator from 0 till the
     *  provided long value.
     */
    PyObject *
    PyLongRangeIter_ZeroToN(PyObject *long_obj)
    {
        // creating a new instance of longrangeiterobject
        longrangeiterobject *it;
        it = PyObject_New(longrangeiterobject, &PyLongRangeIter_Type);
    
        // if unable to allocate memoty to it, return NULL.
        if (it == NULL)
            return NULL;
    
        // we set the start to 0
        it->start = _PyLong_Zero;
    
        // we set the step to 1
        it->step = _PyLong_One;
    
        // we set the index to 0, since we want to always start from the first
        // element of the iteration
        it->index = _PyLong_Zero;
    
        // we set the total length of iteration to be equal to the provided value
        it->len = long_obj;
    
        // we increment the reference count for each of the values referenced
        Py_INCREF(it->start);
        Py_INCREF(it->step);
        Py_INCREF(it->len);
        Py_INCREF(it->index);
    
        // downcast the iterator instance to PyObject and return
        return (PyObject *)it;
    }
    
    5
  • /*
     *  PyLongRangeIter_ZeroToN creates and returns a range iterator on long
     *  iterating on values in the range [0, n).
     *
     *  The function creates and returns a range iterator from 0 till the
     *  provided long value.
     */
    PyObject *
    PyLongRangeIter_ZeroToN(PyObject *long_obj)
    {
        // creating a new instance of longrangeiterobject
        longrangeiterobject *it;
        it = PyObject_New(longrangeiterobject, &PyLongRangeIter_Type);
    
        // if unable to allocate memoty to it, return NULL.
        if (it == NULL)
            return NULL;
    
        // we set the start to 0
        it->start = _PyLong_Zero;
    
        // we set the step to 1
        it->step = _PyLong_One;
    
        // we set the index to 0, since we want to always start from the first
        // element of the iteration
        it->index = _PyLong_Zero;
    
        // we set the total length of iteration to be equal to the provided value
        it->len = long_obj;
    
        // we increment the reference count for each of the values referenced
        Py_INCREF(it->start);
        Py_INCREF(it->step);
        Py_INCREF(it->len);
        Py_INCREF(it->index);
    
        // downcast the iterator instance to PyObject and return
        return (PyObject *)it;
    }
    
    5 sẽ trả lại mục tiếp theo của lần lặp lại và nếu các mục đã hết thì hãy tăng ngoại lệ
    /*
     *  PyLongRangeIter_ZeroToN creates and returns a range iterator on long
     *  iterating on values in the range [0, n).
     *
     *  The function creates and returns a range iterator from 0 till the
     *  provided long value.
     */
    PyObject *
    PyLongRangeIter_ZeroToN(PyObject *long_obj)
    {
        // creating a new instance of longrangeiterobject
        longrangeiterobject *it;
        it = PyObject_New(longrangeiterobject, &PyLongRangeIter_Type);
    
        // if unable to allocate memoty to it, return NULL.
        if (it == NULL)
            return NULL;
    
        // we set the start to 0
        it->start = _PyLong_Zero;
    
        // we set the step to 1
        it->step = _PyLong_One;
    
        // we set the index to 0, since we want to always start from the first
        // element of the iteration
        it->index = _PyLong_Zero;
    
        // we set the total length of iteration to be equal to the provided value
        it->len = long_obj;
    
        // we increment the reference count for each of the values referenced
        Py_INCREF(it->start);
        Py_INCREF(it->step);
        Py_INCREF(it->len);
        Py_INCREF(it->index);
    
        // downcast the iterator instance to PyObject and return
        return (PyObject *)it;
    }
    
    7

Vì vậy, trong một ý chính,

/*
 *  PyLongRangeIter_ZeroToN creates and returns a range iterator on long
 *  iterating on values in the range [0, n).
 *
 *  The function creates and returns a range iterator from 0 till the
 *  provided long value.
 */
PyObject *
PyLongRangeIter_ZeroToN(PyObject *long_obj)
{
    // creating a new instance of longrangeiterobject
    longrangeiterobject *it;
    it = PyObject_New(longrangeiterobject, &PyLongRangeIter_Type);

    // if unable to allocate memoty to it, return NULL.
    if (it == NULL)
        return NULL;

    // we set the start to 0
    it->start = _PyLong_Zero;

    // we set the step to 1
    it->step = _PyLong_One;

    // we set the index to 0, since we want to always start from the first
    // element of the iteration
    it->index = _PyLong_Zero;

    // we set the total length of iteration to be equal to the provided value
    it->len = long_obj;

    // we increment the reference count for each of the values referenced
    Py_INCREF(it->start);
    Py_INCREF(it->step);
    Py_INCREF(it->len);
    Py_INCREF(it->index);

    // downcast the iterator instance to PyObject and return
    return (PyObject *)it;
}
4 là thứ làm cho bất kỳ đối tượng python nào có thể lặp lại được;

Có thể lặp lại trong Python

Việc triển khai Python nổi tiếng và được sử dụng rộng rãi nhất là CPython trong đó lõi được triển khai bằng C thuần túy. Vì chúng tôi cần thay đổi một trong các kiểu dữ liệu cốt lõi của Python, nên chúng tôi sẽ sửa đổi CPython, thêm hàm

/*
 *  PyLongRangeIter_ZeroToN creates and returns a range iterator on long
 *  iterating on values in the range [0, n).
 *
 *  The function creates and returns a range iterator from 0 till the
 *  provided long value.
 */
PyObject *
PyLongRangeIter_ZeroToN(PyObject *long_obj)
{
    // creating a new instance of longrangeiterobject
    longrangeiterobject *it;
    it = PyObject_New(longrangeiterobject, &PyLongRangeIter_Type);

    // if unable to allocate memoty to it, return NULL.
    if (it == NULL)
        return NULL;

    // we set the start to 0
    it->start = _PyLong_Zero;

    // we set the step to 1
    it->step = _PyLong_One;

    // we set the index to 0, since we want to always start from the first
    // element of the iteration
    it->index = _PyLong_Zero;

    // we set the total length of iteration to be equal to the provided value
    it->len = long_obj;

    // we increment the reference count for each of the values referenced
    Py_INCREF(it->start);
    Py_INCREF(it->step);
    Py_INCREF(it->len);
    Py_INCREF(it->index);

    // downcast the iterator instance to PyObject and return
    return (PyObject *)it;
}
4 vào kiểu Số nguyên và xây dựng lại tệp nhị phân. Nhưng trước khi bắt tay vào thực hiện, điều quan trọng là phải hiểu một số nguyên tắc cơ bản

PyAPI_FUNC(PyObject *) PyLongRangeIter_ZeroToN(PyObject *); 1

Mỗi đối tượng trong Python được liên kết với một loại và mỗi đối tượng là một thể hiện của cấu trúc có tên là PyTypeObject. Một thể hiện mới của cấu trúc này thực sự là một kiểu mới trong python. Cấu trúc này chứa một vài thông tin meta và một loạt các con trỏ hàm C - mỗi con trỏ thực hiện một phân đoạn nhỏ của chức năng của loại. Hầu hết các "khe" này trong cấu trúc là tùy chọn có thể được lấp đầy bằng cách đặt các con trỏ hàm thích hợp và điều khiển chức năng tương ứng

Khe cắm PyAPI_FUNC(PyObject *) PyLongRangeIter_ZeroToN(PyObject *); 2

Trong số tất cả các vị trí có sẵn, vị trí mà chúng tôi quan tâm là vị trí

PyAPI_FUNC(PyObject *)   PyLongRangeIter_ZeroToN(PyObject *);
2 có thể chứa một con trỏ tới một hàm trả về một đối tượng lặp. Vị trí này tương ứng với chức năng
/*
 *  PyLongRangeIter_ZeroToN creates and returns a range iterator on long
 *  iterating on values in the range [0, n).
 *
 *  The function creates and returns a range iterator from 0 till the
 *  provided long value.
 */
PyObject *
PyLongRangeIter_ZeroToN(PyObject *long_obj)
{
    // creating a new instance of longrangeiterobject
    longrangeiterobject *it;
    it = PyObject_New(longrangeiterobject, &PyLongRangeIter_Type);

    // if unable to allocate memoty to it, return NULL.
    if (it == NULL)
        return NULL;

    // we set the start to 0
    it->start = _PyLong_Zero;

    // we set the step to 1
    it->step = _PyLong_One;

    // we set the index to 0, since we want to always start from the first
    // element of the iteration
    it->index = _PyLong_Zero;

    // we set the total length of iteration to be equal to the provided value
    it->len = long_obj;

    // we increment the reference count for each of the values referenced
    Py_INCREF(it->start);
    Py_INCREF(it->step);
    Py_INCREF(it->len);
    Py_INCREF(it->index);

    // downcast the iterator instance to PyObject and return
    return (PyObject *)it;
}
4 làm cho đối tượng có thể lặp lại một cách hiệu quả. Giá trị không phải là
PyAPI_FUNC(PyObject *)   PyLongRangeIter_ZeroToN(PyObject *);
5 của vị trí này biểu thị khả năng lặp lại.
PyAPI_FUNC(PyObject *)   PyLongRangeIter_ZeroToN(PyObject *);
2 giữ chức năng với chữ ký sau

PyObject * tp_iter(PyObject *);

Số nguyên trong Python không có kích thước cố định; . Cách Python triển khai các số nguyên siêu dài là một câu chuyện của riêng nó nhưng việc triển khai cốt lõi có thể được tìm thấy tại longobject. c. Phiên bản của

PyAPI_FUNC(PyObject *)   PyLongRangeIter_ZeroToN(PyObject *);
1 xác định kiểu số nguyên/dài là
PyAPI_FUNC(PyObject *)   PyLongRangeIter_ZeroToN(PyObject *);
8 và có vị trí
PyAPI_FUNC(PyObject *)   PyLongRangeIter_ZeroToN(PyObject *);
2 của nó được đặt thành
PyTypeObject PyLong_Type = {
    ...

    "int",                                      /* tp_name */
    offsetof(PyLongObject, ob_digit),           /* tp_basicsize */
    sizeof(digit),                              /* tp_itemsize */
    ...
    0,                                          /* tp_iter */
    ...
};
0 i. e.
PyAPI_FUNC(PyObject *)   PyLongRangeIter_ZeroToN(PyObject *);
5 khẳng định thực tế là Số nguyên trong python không thể lặp lại

PyTypeObject PyLong_Type = {
    ...

    "int",                                      /* tp_name */
    offsetof(PyLongObject, ob_digit),           /* tp_basicsize */
    sizeof(digit),                              /* tp_itemsize */
    ...
    0,                                          /* tp_iter */
    ...
};

Giá trị

PyAPI_FUNC(PyObject *)   PyLongRangeIter_ZeroToN(PyObject *);
5 cho
PyAPI_FUNC(PyObject *)   PyLongRangeIter_ZeroToN(PyObject *);
2 làm cho đối tượng
/*
 *  long_iter creates an instance of range iterator using PyLongRangeIter_ZeroToN
 *  and returns the iterator instance.
 *
 *  The argument to the `tp_iter` is the `self` object and since we are trying to
 *  iterate an integer here, the input argument to `long_iter` will be the
 *  PyObject of type PyLong_Type, holding the integer value.
 */
static PyObject * long_iter(PyObject *long_obj)
{
    return PyLongRangeIter_ZeroToN(long_obj);
}
4 không thể lặp lại và do đó nếu vị trí này bị chiếm bởi một con trỏ hàm thích hợp với chữ ký đã nói ở trên, thì điều này cũng có thể làm cho bất kỳ số nguyên nào cũng có thể lặp lại

Thực hiện
/*
 *  long_iter creates an instance of range iterator using PyLongRangeIter_ZeroToN
 *  and returns the iterator instance.
 *
 *  The argument to the `tp_iter` is the `self` object and since we are trying to
 *  iterate an integer here, the input argument to `long_iter` will be the
 *  PyObject of type PyLong_Type, holding the integer value.
 */
static PyObject * long_iter(PyObject *long_obj)
{
    return PyLongRangeIter_ZeroToN(long_obj);
}
5

Bây giờ chúng ta triển khai hàm

PyAPI_FUNC(PyObject *)   PyLongRangeIter_ZeroToN(PyObject *);
2 trên kiểu số nguyên, đặt tên là
/*
 *  long_iter creates an instance of range iterator using PyLongRangeIter_ZeroToN
 *  and returns the iterator instance.
 *
 *  The argument to the `tp_iter` is the `self` object and since we are trying to
 *  iterate an integer here, the input argument to `long_iter` will be the
 *  PyObject of type PyLong_Type, holding the integer value.
 */
static PyObject * long_iter(PyObject *long_obj)
{
    return PyLongRangeIter_ZeroToN(long_obj);
}
5, hàm này trả về một đối tượng lặp, theo yêu cầu của quy ước. Chức năng cốt lõi mà chúng tôi đang tìm cách triển khai ở đây là - khi một số nguyên
/*
 *  long_iter creates an instance of range iterator using PyLongRangeIter_ZeroToN
 *  and returns the iterator instance.
 *
 *  The argument to the `tp_iter` is the `self` object and since we are trying to
 *  iterate an integer here, the input argument to `long_iter` will be the
 *  PyObject of type PyLong_Type, holding the integer value.
 */
static PyObject * long_iter(PyObject *long_obj)
{
    return PyLongRangeIter_ZeroToN(long_obj);
}
8 được lặp, nó sẽ lặp qua chuỗi
# The range(0, 7, 1) will iterate through values 0 to 6 and every time
# it will increment the current value by 1 i.e. the step.
>>> for x in range(0, 7, 1): print(x, end=" ")
0 1 2 3 4 5 6
2 với bước
PyTypeObject PyLong_Type = {
    ...

    "int",                                      /* tp_name */
    offsetof(PyLongObject, ob_digit),           /* tp_basicsize */
    sizeof(digit),                              /* tp_itemsize */
    ...
    0,                                          /* tp_iter */
    ...
};
2. Hành vi này rất gần với loại
# The range(0, 7, 1) will iterate through values 0 to 6 and every time
# it will increment the current value by 1 i.e. the step.
>>> for x in range(0, 7, 1): print(x, end=" ")
0 1 2 3 4 5 6
1 được xác định trước, lặp lại trên một phạm vi giá trị số nguyên, cụ thể hơn là một
# The range(0, 7, 1) will iterate through values 0 to 6 and every time
# it will increment the current value by 1 i.e. the step.
>>> for x in range(0, 7, 1): print(x, end=" ")
0 1 2 3 4 5 6
1 bắt đầu từ
PyTypeObject PyLong_Type = {
    ...

    "int",                                      /* tp_name */
    offsetof(PyLongObject, ob_digit),           /* tp_basicsize */
    sizeof(digit),                              /* tp_itemsize */
    ...
    0,                                          /* tp_iter */
    ...
};
0, đi đến
/*
 *  long_iter creates an instance of range iterator using PyLongRangeIter_ZeroToN
 *  and returns the iterator instance.
 *
 *  The argument to the `tp_iter` is the `self` object and since we are trying to
 *  iterate an integer here, the input argument to `long_iter` will be the
 *  PyObject of type PyLong_Type, holding the integer value.
 */
static PyObject * long_iter(PyObject *long_obj)
{
    return PyLongRangeIter_ZeroToN(long_obj);
}
8 với một bước là
PyTypeObject PyLong_Type = {
    ...

    "int",                                      /* tp_name */
    offsetof(PyLongObject, ob_digit),           /* tp_basicsize */
    sizeof(digit),                              /* tp_itemsize */
    ...
    0,                                          /* tp_iter */
    ...
};
2

Chúng tôi xác định một hàm tiện ích trong

PyTypeObject PyLong_Type = {
    ...

    "int",                                      /* tp_name */
    offsetof(PyLongObject, ob_digit),           /* tp_basicsize */
    sizeof(digit),                              /* tp_itemsize */
    ...
    long_iter,                                  /* tp_iter */
    ...
};
6, được cung cấp một số nguyên python, trả về một phiên bản của
PyTypeObject PyLong_Type = {
    ...

    "int",                                      /* tp_name */
    offsetof(PyLongObject, ob_digit),           /* tp_basicsize */
    sizeof(digit),                              /* tp_itemsize */
    ...
    long_iter,                                  /* tp_iter */
    ...
};
7 theo thông số kỹ thuật của chúng tôi. Hàm tiện ích này sẽ khởi tạo
PyTypeObject PyLong_Type = {
    ...

    "int",                                      /* tp_name */
    offsetof(PyLongObject, ob_digit),           /* tp_basicsize */
    sizeof(digit),                              /* tp_itemsize */
    ...
    long_iter,                                  /* tp_iter */
    ...
};
7 với bắt đầu là
PyTypeObject PyLong_Type = {
    ...

    "int",                                      /* tp_name */
    offsetof(PyLongObject, ob_digit),           /* tp_basicsize */
    sizeof(digit),                              /* tp_itemsize */
    ...
    0,                                          /* tp_iter */
    ...
};
0, kết thúc ở giá trị dài được đưa ra trong đối số và bước là
PyTypeObject PyLong_Type = {
    ...

    "int",                                      /* tp_name */
    offsetof(PyLongObject, ob_digit),           /* tp_basicsize */
    sizeof(digit),                              /* tp_itemsize */
    ...
    0,                                          /* tp_iter */
    ...
};
2. Chức năng tiện ích như minh họa bên dưới

/*
 *  PyLongRangeIter_ZeroToN creates and returns a range iterator on long
 *  iterating on values in the range [0, n).
 *
 *  The function creates and returns a range iterator from 0 till the
 *  provided long value.
 */
PyObject *
PyLongRangeIter_ZeroToN(PyObject *long_obj)
{
    // creating a new instance of longrangeiterobject
    longrangeiterobject *it;
    it = PyObject_New(longrangeiterobject, &PyLongRangeIter_Type);

    // if unable to allocate memoty to it, return NULL.
    if (it == NULL)
        return NULL;

    // we set the start to 0
    it->start = _PyLong_Zero;

    // we set the step to 1
    it->step = _PyLong_One;

    // we set the index to 0, since we want to always start from the first
    // element of the iteration
    it->index = _PyLong_Zero;

    // we set the total length of iteration to be equal to the provided value
    it->len = long_obj;

    // we increment the reference count for each of the values referenced
    Py_INCREF(it->start);
    Py_INCREF(it->step);
    Py_INCREF(it->len);
    Py_INCREF(it->index);

    // downcast the iterator instance to PyObject and return
    return (PyObject *)it;
}

Hàm tiện ích

>>> for i in 7: print(i, end=" ");
0 1 2 3 4 5 6

# Since integers are now iterable, we can create a list of [0, 7) using `list`
# Internally `list` tries to iterate on the given object i.e. `7`
# now that the iteration is defined as [0, 7) we get the list from
# from iteration, instead of an exception
>>> list(7)
[0, 1, 2, 3, 4, 5, 6]
1 được định nghĩa trong
PyTypeObject PyLong_Type = {
    ...

    "int",                                      /* tp_name */
    offsetof(PyLongObject, ob_digit),           /* tp_basicsize */
    sizeof(digit),                              /* tp_itemsize */
    ...
    long_iter,                                  /* tp_iter */
    ...
};
6 và sẽ được khai báo trong
>>> for i in 7: print(i, end=" ");
0 1 2 3 4 5 6

# Since integers are now iterable, we can create a list of [0, 7) using `list`
# Internally `list` tries to iterate on the given object i.e. `7`
# now that the iteration is defined as [0, 7) we get the list from
# from iteration, instead of an exception
>>> list(7)
[0, 1, 2, 3, 4, 5, 6]
3 để nó có thể được sử dụng trên CPython. Khai báo hàm trong
>>> for i in 7: print(i, end=" ");
0 1 2 3 4 5 6

# Since integers are now iterable, we can create a list of [0, 7) using `list`
# Internally `list` tries to iterate on the given object i.e. `7`
# now that the iteration is defined as [0, 7) we get the list from
# from iteration, instead of an exception
>>> list(7)
[0, 1, 2, 3, 4, 5, 6]
3 bằng cách sử dụng macro Python tiêu chuẩn như thế này

PyAPI_FUNC(PyObject *)   PyLongRangeIter_ZeroToN(PyObject *);

Hàm chiếm vị trí

PyAPI_FUNC(PyObject *)   PyLongRangeIter_ZeroToN(PyObject *);
2 sẽ nhận đối tượng
>>> for i in 7: print(i, end=" ");
0 1 2 3 4 5 6

# Since integers are now iterable, we can create a list of [0, 7) using `list`
# Internally `list` tries to iterate on the given object i.e. `7`
# now that the iteration is defined as [0, 7) we get the list from
# from iteration, instead of an exception
>>> list(7)
[0, 1, 2, 3, 4, 5, 6]
6 làm đối số đầu vào và dự kiến ​​sẽ trả về thể hiện của trình vòng lặp. Do đó, hàm
/*
 *  long_iter creates an instance of range iterator using PyLongRangeIter_ZeroToN
 *  and returns the iterator instance.
 *
 *  The argument to the `tp_iter` is the `self` object and since we are trying to
 *  iterate an integer here, the input argument to `long_iter` will be the
 *  PyObject of type PyLong_Type, holding the integer value.
 */
static PyObject * long_iter(PyObject *long_obj)
{
    return PyLongRangeIter_ZeroToN(long_obj);
}
5 sẽ nhận đối tượng số nguyên python (bản thân) đang được lặp lại làm đối số đầu vào và nó sẽ trả về thể hiện của trình lặp. Ở đây chúng ta sẽ sử dụng hàm tiện ích
>>> for i in 7: print(i, end=" ");
0 1 2 3 4 5 6

# Since integers are now iterable, we can create a list of [0, 7) using `list`
# Internally `list` tries to iterate on the given object i.e. `7`
# now that the iteration is defined as [0, 7) we get the list from
# from iteration, instead of an exception
>>> list(7)
[0, 1, 2, 3, 4, 5, 6]
1 mà chúng ta vừa xác định, hàm này sẽ trả về cho chúng ta một thể hiện của trình vòng lặp phạm vi. Toàn bộ chức năng
/*
 *  long_iter creates an instance of range iterator using PyLongRangeIter_ZeroToN
 *  and returns the iterator instance.
 *
 *  The argument to the `tp_iter` is the `self` object and since we are trying to
 *  iterate an integer here, the input argument to `long_iter` will be the
 *  PyObject of type PyLong_Type, holding the integer value.
 */
static PyObject * long_iter(PyObject *long_obj)
{
    return PyLongRangeIter_ZeroToN(long_obj);
}
5 có thể được định nghĩa là

/*
 *  long_iter creates an instance of range iterator using PyLongRangeIter_ZeroToN
 *  and returns the iterator instance.
 *
 *  The argument to the `tp_iter` is the `self` object and since we are trying to
 *  iterate an integer here, the input argument to `long_iter` will be the
 *  PyObject of type PyLong_Type, holding the integer value.
 */
static PyObject * long_iter(PyObject *long_obj)
{
    return PyLongRangeIter_ZeroToN(long_obj);
}

Bây giờ chúng ta đã xác định được

/*
 *  long_iter creates an instance of range iterator using PyLongRangeIter_ZeroToN
 *  and returns the iterator instance.
 *
 *  The argument to the `tp_iter` is the `self` object and since we are trying to
 *  iterate an integer here, the input argument to `long_iter` will be the
 *  PyObject of type PyLong_Type, holding the integer value.
 */
static PyObject * long_iter(PyObject *long_obj)
{
    return PyLongRangeIter_ZeroToN(long_obj);
}
5, chúng ta có thể đặt hàm trên vị trí
PyAPI_FUNC(PyObject *)   PyLongRangeIter_ZeroToN(PyObject *);
2 của
PyAPI_FUNC(PyObject *)   PyLongRangeIter_ZeroToN(PyObject *);
8 để kích hoạt khả năng lặp cần thiết trên các số nguyên

PyTypeObject PyLong_Type = {
    ...

    "int",                                      /* tp_name */
    offsetof(PyLongObject, ob_digit),           /* tp_basicsize */
    sizeof(digit),                              /* tp_itemsize */
    ...
    long_iter,                                  /* tp_iter */
    ...
};

dòng chảy hợp nhất

Khi chúng tôi có mọi thứ tại chỗ, toàn bộ quy trình sẽ diễn ra như sau -

Mỗi khi một số nguyên được lặp lại, sử dụng bất kỳ phương thức lặp nào - ví dụ như

# The range(0, 7, 1) will iterate through values 0 to 6 and every time
# it will increment the current value by 1 i.e. the step.
>>> for x in range(0, 7, 1): print(x, end=" ")
0 1 2 3 4 5 6
0, nó sẽ kiểm tra
PyAPI_FUNC(PyObject *)   PyLongRangeIter_ZeroToN(PyObject *);
2 của
>>> a, b = 7
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: too many values to unpack (expected 2)

>>> a, b = 2
>>> a, b
0, 1
5 và vì bây giờ nó giữ con trỏ hàm
/*
 *  long_iter creates an instance of range iterator using PyLongRangeIter_ZeroToN
 *  and returns the iterator instance.
 *
 *  The argument to the `tp_iter` is the `self` object and since we are trying to
 *  iterate an integer here, the input argument to `long_iter` will be the
 *  PyObject of type PyLong_Type, holding the integer value.
 */
static PyObject * long_iter(PyObject *long_obj)
{
    return PyLongRangeIter_ZeroToN(long_obj);
}
5, nên hàm sẽ được gọi. Lời gọi này sẽ trả về một đối tượng trình vòng lặp loại
PyTypeObject PyLong_Type = {
    ...

    "int",                                      /* tp_name */
    offsetof(PyLongObject, ob_digit),           /* tp_basicsize */
    sizeof(digit),                              /* tp_itemsize */
    ...
    long_iter,                                  /* tp_iter */
    ...
};
7 với các giá trị bắt đầu, chỉ mục và bước cố định - mà theo thuật ngữ Pythonic thực sự là một
>>> a, b = 7
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: too many values to unpack (expected 2)

>>> a, b = 2
>>> a, b
0, 1
8. Do đó,
# The range(0, 7, 1) will iterate through values 0 to 6 and every time
# it will increment the current value by 1 i.e. the step.
>>> for x in range(0, 7, 1): print(x, end=" ")
0 1 2 3 4 5 6
3 vốn đã được đánh giá là
# The range(0, 7, 1) will iterate through values 0 to 6 and every time
# it will increment the current value by 1 i.e. the step.
>>> for x in range(0, 7, 1): print(x, end=" ")
0 1 2 3 4 5 6
00 cho phép chúng ta lặp lại các số nguyên

Những thay đổi này cũng được lưu trữ trên một nhánh từ xa cpython@02-long-iter và Yêu cầu kéo giữ

# The range(0, 7, 1) will iterate through values 0 to 6 and every time
# it will increment the current value by 1 i.e. the step.
>>> for x in range(0, 7, 1): print(x, end=" ")
0 1 2 3 4 5 6
01 có thể được tìm thấy tại đây

Lặp lại số nguyên trong hành động

Khi chúng tôi xây dựng nhị phân python mới với các thay đổi đã nói ở trên, chúng tôi có thể thấy các số nguyên có thể lặp lại trong các hành động. Bây giờ khi chúng ta thực hiện

# The range(0, 7, 1) will iterate through values 0 to 6 and every time
# it will increment the current value by 1 i.e. the step.
>>> for x in range(0, 7, 1): print(x, end=" ")
0 1 2 3 4 5 6
3, thay vì đưa ra một ngoại lệ, nó thực sự lặp qua các giá trị
# The range(0, 7, 1) will iterate through values 0 to 6 and every time
# it will increment the current value by 1 i.e. the step.
>>> for x in range(0, 7, 1): print(x, end=" ")
0 1 2 3 4 5 6
6

>>> for i in 7: print(i, end=" ");
0 1 2 3 4 5 6

# Since integers are now iterable, we can create a list of [0, 7) using `list`
# Internally `list` tries to iterate on the given object i.e. `7`
# now that the iteration is defined as [0, 7) we get the list from
# from iteration, instead of an exception
>>> list(7)
[0, 1, 2, 3, 4, 5, 6]
Tại sao nó không phải là một ý kiến ​​hay

Mặc dù có vẻ thú vị và hơi hữu ích khi có các số nguyên có thể lặp lại, nhưng đó thực sự không phải là một ý tưởng hay. Lý do cốt lõi của điều này là nó làm cho việc giải nén trở nên khó đoán. Giải nén là khi bạn giải nén một iterable và gán nó cho nhiều biến. Ví dụ.

# The range(0, 7, 1) will iterate through values 0 to 6 and every time
# it will increment the current value by 1 i.e. the step.
>>> for x in range(0, 7, 1): print(x, end=" ")
0 1 2 3 4 5 6
04 sẽ gán 3 cho a và 4 cho b. Vì vậy, việc gán
# The range(0, 7, 1) will iterate through values 0 to 6 and every time
# it will increment the current value by 1 i.e. the step.
>>> for x in range(0, 7, 1): print(x, end=" ")
0 1 2 3 4 5 6
05 sẽ là một lỗi vì chỉ có một giá trị ở bên phải và nhiều giá trị ở bên trái

Giải nén coi kích thước bên phải là có thể lặp lại và cố gắng lặp lại kích thước đó;

Mọi thứ sẽ hoạt động tốt nếu chúng ta làm

# The range(0, 7, 1) will iterate through values 0 to 6 and every time
# it will increment the current value by 1 i.e. the step.
>>> for x in range(0, 7, 1): print(x, end=" ")
0 1 2 3 4 5 6
07 vì bây giờ phía bên tay phải, sau lần lặp, có hai giá trị và phía bên trái có hai biến. Do đó, hai câu lệnh rất giống nhau dẫn đến hai kết quả rất khác nhau, khiến việc giải nén trở nên khó đoán

>>> a, b = 7
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: too many values to unpack (expected 2)

>>> a, b = 2
>>> a, b
0, 1
Kết luận

Trong bài tiểu luận này, chúng tôi đã sửa đổi mã nguồn của Python và tạo các số nguyên có thể lặp lại. Mặc dù làm như vậy không phải là một ý tưởng hay, nhưng thật thú vị khi chơi với mã và thực hiện các thay đổi trong ngôn ngữ lập trình yêu thích của chúng tôi. Nó giúp chúng tôi có ý tưởng chi tiết về triển khai python cốt lõi và có thể mở đường cho chúng tôi trở thành nhà phát triển Python cốt lõi. Đây là một trong nhiều bài viết trong loạt bài Python Internals - Làm thế nào python triển khai các số nguyên siêu dài?

Người giới thiệu
  • Đối tượng kiểu Python
  • Giao thức trình lặp Python
  • CPython với long_iter

Các bài viết khác mà bạn có thể thích
  • Python lưu trữ số nguyên
  • Làm thế nào python thực hiện các số nguyên siêu dài?
  • Tôi đã thay đổi Python của mình và khiến nó trở nên đáng ngờ. Nội bộ Python
  • Xây dựng các máy trạng thái hữu hạn với Python Coroutines
  • Cá nhân hóa dấu nhắc python của bạn

Nếu bạn thích những gì bạn đọc, hãy cân nhắc đăng ký nhận bản tin hàng tuần của tôi tại arpitbhayani. tôi/bản tin là, mỗi tuần một lần, tôi viết một bài luận về nội bộ ngôn ngữ lập trình hoặc tìm hiểu sâu về một số thuật toán siêu thông minh hoặc chỉ một số mẹo về xây dựng hệ thống phân tán có khả năng mở rộng cao

Bạn luôn có thể tìm thấy tôi duyệt qua twitter @arpit_bhayani

cpythonInternalsPython

Bài báo cáo

Thưởng thức bài viết này?

8

Chia sẻ

Arpit Bhayani

Phần phụ trợ @Unacademy • Dữ liệu @Amazon • Nền tảng @Practo. Viết về Ngôn ngữ bên trong và Toán học trong Khoa học Máy tính

Tôi là một lập trình viên đam mê, đam mê viết mã, thiết kế, khởi nghiệp và công nghệ. Hiện tại tôi đang làm việc tại Amazon với vị trí Kỹ sư phát triển phần mềm 2. Trước Amazon, tôi đang làm việc cho một công ty khởi nghiệp về chăm sóc sức khỏe tên là Practo, nơi tôi độc thân

Bạn có thể lặp lại một số nguyên trong Python không?

Iterables trong Python là các đối tượng và vùng chứa có thể được chuyển qua từng mục một, thường sử dụng lệnh for. trong vòng lặp. Không phải tất cả các đối tượng đều có thể được lặp lại, ví dụ - chúng tôi không thể lặp lại một số nguyên , đó là một giá trị số ít.

Cách chính xác để lặp qua một dãy số trong Python là gì?

Để lặp qua một bộ mã với số lần xác định, chúng ta có thể sử dụng hàm range() , Hàm range() .

Vòng lặp for có thể lặp qua một dãy số không?

Vòng lặp for dùng để lặp lại các phần tử trong phạm vi cho trước . Chúng ta có thể sử dụng vòng lặp for để nối, in hoặc thực hiện một số thao tác trên phạm vi số nguyên đã cho.

Vòng lặp nào lặp trên một phạm vi số nguyên được chỉ định?

Chúng ta có thể lặp qua một dãy số được tạo bởi hàm range() bằng cách sử dụng vòng lặp for .