Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

What is range ()? Why not produce iterators?

2025-01-30 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Database >

Share

Shulou(Shulou.com)06/01 Report--

What is range()? Why not produce iterators? I believe that many inexperienced people are helpless about this. For this reason, this article summarizes the causes and solutions of the problem. Through this article, I hope you can solve this problem.

Iterators are one of the most commonly used of the 23 design patterns, and they're ubiquitous in Python, often used without necessarily realizing they exist. In my series on iterators (see links at the end), I mentioned at least 23 ways to generate iterators. Some methods are specifically designed to generate iterators, while others are used "implicitly" to solve other problems.

Before the system learned iterators, I always thought that the range() method was also used to generate iterators, but now I suddenly realized that it only generates iterable objects, not iterators! (PS: Python2 range() generates a list, this article is based on Python 3, generated an iterable object)

So, I have this question: Why doesn't range() generate iterators? As I searched for answers, I discovered that I had some misconceptions about range types. Therefore, this article will have a comprehensive understanding of range and look forward to learning and improving with you.

1 What is Range()?

Its syntax: range(start, stop [,step]) ;start refers to the starting value of the count, the default is 0;stop refers to the end value of the count, but does not include stop ;step is the step, the default is 1, can not be 0. The range() method generates a range of integers that is left closed and right open.

>>> a = range(5) #i.e. range(0,5)>>> range (0,5)>> len(a)5>>> for x in a:>>> print(x,end=" ")0 1 2 3 4

There are several caveats to the range() function: (1) it represents a left-closed right-open interval;(2) the parameters it receives must be integers, which can be negative, but cannot be floating point numbers and other types;(3) it is an immutable sequence type, which can perform operations such as judging elements, finding elements, slicing, etc., but cannot modify elements; and (4) it is an iterable object, but not an iterator.

#(1) Left Closed Right Open>>> for i in range(3, 6):>>> print(i,end=" ")3 4 5#(2) Parameter type>>> for i in range(-8, -2, 2):>>> print(i,end=" ")-8 -6 -4>>> range(2.2)----------------------------TypeError Traceback (most recent call last)... TypeError: 'float' object cannot be interpreted as an integer#(3) sequence operation>>> b = range(1,10)>>> b[0]1>> b[:-3]range(1,7)>>> b[0] = 2TypeError Traceback (most recent call last)... TypeError: 'range' object does not support item assignment#(4) is not an iterator>> hasattr(range(3),'__iter__')True>> hasattr(range(3),'__next__')False>> hasattr(iter(range(3)),'__next__')True

Why does range() not produce iterators?

There are many built-in methods to obtain iterators, such as zip(), enumerate(), map(), filter(), reversed(), etc., but there are only a few methods like range() that only get iterable objects (if there are counterexamples, please let me know). This is where my knowledge went wrong.

In for-loop traversal, iterable objects behave the same as iterators, i.e. they are both lazy to evaluate, and there is no difference in spatial complexity or time complexity. I have summarized the difference between the two as "one and two different": the same is that both can be iterated lazily, the difference is that iterable objects do not support self-traversal (i.e., the next() method), and iterators themselves do not support slicing (i.e., the__getitem__() method).

Despite these differences, it is difficult to conclude which is better. Now, the tricky part is, why are iterators designed for all five built-in methods, but iterators designed for range()? Wouldn't it be better to unify them all?

In fact, Pyhton has done a lot of this for the sake of regularity. For example, Python2 has two methods, range() and xrange(), and Python 3 has killed one of them and used the "plum instead of peach" method. Why not make range() generate iterators?

I can't find an official explanation for this problem. The following is my personal opinion.

Zip() and other methods need to receive certain iterable object parameters, is a reprocessing process for them, so also want to immediately produce a certain result, so Python developers designed this result is an iterator. This also has the advantage that when the iterable object as a parameter changes, the resulting iterator, because it is expendable, will not be used incorrectly.

The range() method is different. The parameters it receives are not iterable objects. It is a process of initial processing, so it is designed as iterable objects, which can be used directly or for other reprocessing purposes. For example, methods such as zip() are perfectly capable of accepting parameters of type range.

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

In other words, the range() method, as a primary producer, produces raw materials that are of great use in themselves, and turning it into an iterator early is undoubtedly a superfluous behavior.

Does this interpretation make sense to you? Welcome to discuss this topic with me.

3 What is the range type?

That's one of my answers to why range() doesn't produce iterators. Following this line of thought, I studied the range object it generated, and as soon as I studied it, I found that this range object is not simple.

The first strange thing was that it was an immutable sequence! I never noticed that. Although I never thought about changing the value of range(), this immutable property surprised me.

Looking through the documentation, the official distinction is that there are three basic sequence types: list, tuple, and range objects.(There are three basic sequence types: lists, tuples, and range objects.)

I hadn't noticed this before. It turns out that the range type is actually the same basic sequence as the list and tuple! I always remember that strings are immutable sequence types, and I didn't think there was an immutable sequence type here.

What is the difference between range sequences and other sequence types?

There are 12 operations supported by ordinary sequences. Do you really know what Python strings are? It was mentioned in this article. Range sequences only support 10 of them, and do not support addition splicing and multiplication repetition.

>>> range(2) + range(3)-----------------------------------------TypeError Traceback (most recent call last)... TypeError: unsupported operand type(s) for +: 'range' and 'range'>>> range(2)*2-----------------------------------------TypeError Traceback (most recent call last)... TypeError: unsupported operand type(s) for *: 'range' and 'int'

So the question is: why do strings and tuples support these two operations, but range sequences don't? Although we can't modify immutable sequences directly, we can copy them to new sequences for operation. Why doesn't range object support this?

See the official document for explanation:

... due to the fact that range objects can only represent sequences that follow a strict pattern and repetition and concatenation will usually violate that pattern.

The reason is that range objects simply represent a sequence that follows a strict pattern, and repetition and concatenation often break this pattern...

The key to the problem lies in the pattern of the range sequence. If you think about it carefully, it actually represents an arithmetic series (meow, high school math knowledge has not forgotten...). Splicing two arithmetic series, or repeatedly splicing an arithmetic series, think about it is really wrong, this is why the range type does not support these two operations. From this corollary, other modification actions will also destroy the arithmetic progression structure, so all do not give modification is.

4. Summary

Looking back, I came to two surprising conclusions: range is an iterable object, not an iterator; and range objects are invariant arithmetic sequences.

If you simply look at the conclusion, you may not feel it, or you may say it's nothing. But if I ask, why is range not an iterator, why is range an immutable sequence? Can you answer these two questions with a self-explanatory design idea? (PS: I decided that if I have the opportunity to interview someone, I must ask these two questions.)

Because of the subtle and interesting nature of range objects, I think this article is well written. This article was written as part of an iterator series, so the basics of iterators are not covered much. Please check out the previous articles. In addition, there is also a special iterator that is worth writing separately, that is, the generator. Please look forward to the follow-up tweets ~

After reading the above, what do you know about range()? Why not produce iterators? How to do it? If you still want to learn more skills or want to know more related content, welcome to pay attention to the industry information channel, thank you for reading!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Database

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report