program tip

이 코드에서 list [:]의 의미는 무엇입니까?

radiobox 2020. 12. 12. 10:22
반응형

이 코드에서 list [:]의 의미는 무엇입니까?


이 질문에 이미 답변이 있습니다.

이 코드는 Python의 문서에서 가져온 것입니다. 조금 혼란 스러워요.

words = ['cat', 'window', 'defenestrate']
for w in words[:]:
    if len(w) > 6:
        words.insert(0, w)
print(words)

그리고 다음은 처음에 내가 생각한 것입니다.

words = ['cat', 'window', 'defenestrate']
for w in words:
    if len(w) > 6:
        words.insert(0, w)
print(words)

이 코드가 무한 루프를 생성하고 첫 번째 코드는 생성하지 않는 이유는 무엇입니까?


이것은 잡힌 것 중 하나입니다! 초보자를 피할 수있는 파이썬의.

words[:]여기에 마법의 소스입니다.

관찰 :

>>> words =  ['cat', 'window', 'defenestrate']
>>> words2 = words[:]
>>> words2.insert(0, 'hello')
>>> words2
['hello', 'cat', 'window', 'defenestrate']
>>> words
['cat', 'window', 'defenestrate']

그리고 이제 [:]:

>>> words =  ['cat', 'window', 'defenestrate']
>>> words2 = words
>>> words2.insert(0, 'hello')
>>> words2
['hello', 'cat', 'window', 'defenestrate']
>>> words
['hello', 'cat', 'window', 'defenestrate']

여기서 주목해야 할 중요한 것은 기존 목록의 words[:]a 반환 copy하므로 수정되지 않은 복사본을 반복한다는 것입니다.

다음을 사용하여 동일한 목록을 참조하고 있는지 확인할 수 있습니다 id().

첫 번째 경우 :

>>> words2 = words[:]
>>> id(words2)
4360026736
>>> id(words)
4360188992
>>> words2 is words
False

두 번째 경우 :

>>> id(words2)
4360188992
>>> id(words)
4360188992
>>> words2 is words
True

slicing operator[i:j] 라고 불리는 것은 주목할 가치가 있으며, 그것이하는 일은 index 에서 시작하여 index 까지 (하지만 포함하지 않는) 목록의 새로운 복사본을 반환한다는 것 입니다.ij

그래서 words[0:2]당신에게

>>> words[0:2]
['hello', 'cat']

시작 색인 0을 생략하면 기본값이 로 설정되고 마지막 색인을 생략하면 기본값이 len(words)로 설정되며 최종 결과는 전체 목록 의 사본을 받게 됩니다.


코드를 좀 더 읽기 쉽게 만들고 싶다면 copy모듈을 추천합니다 .

from copy import copy 

words = ['cat', 'window', 'defenestrate']
for w in copy(words):
    if len(w) > 6:
        words.insert(0, w)
print(words)

이것은 기본적으로 첫 번째 코드 스 니펫과 동일한 작업을 수행하며 훨씬 더 읽기 쉽습니다.

또는 (주석에서 DSM이 언급했듯이) python> = 3 words.copy()에서 동일한 작업을 수행하는 것을 사용할 수도 있습니다 .


words[:] copies all the elements in words into a new list. So when you iterate over words[:], you're actually iterating over all the elements that words currently has. So when you modify words, the effects of those modifications are not visible in words[:] (because you called on words[:] before starting to modify words)

In the latter example, you are iterating over words, which means that any changes you make to words is indeed visible to your iterator. As a result, when you insert into index 0 of words, you "bump up" every other element in words by one index. So when you move on to the next iteration of your for-loop, you'll get the element at the next index of words, but that's just the element that you just saw (because you inserted an element at the beginning of the list, moving all the other element up by an index).

To see this in action, try the following code:

words = ['cat', 'window', 'defenestrate']
for w in words:
    print("The list is:", words)
    print("I am looking at this word:", w)
    if len(w) > 6:
        print("inserting", w)
        words.insert(0, w)
        print("the list now looks like this:", words)
print(words)

(In addition to @Coldspeed answer)

Look at the below examples:

words = ['cat', 'window', 'defenestrate']
words2 = words
words2 is words

results: True

It means names word and words2 refer to the same object.

words = ['cat', 'window', 'defenestrate']
words2 = words[:]
words2 is words

results: False

In this case, we have created the new object.


Let's have a look at iterator and iterables:

An iterable is an object that has an __iter__ method which returns an iterator, or which defines a __getitem__ method that can take sequential indexes starting from zero (and raises an IndexError when the indexes are no longer valid). So an iterable is an object that you can get an iterator from.

An iterator is an object with a next (Python 2) or __next__ (Python 3) method.

iter(iterable) returns iterator object, and list_obj[:] returns a new list object, exact copy of list_object.

In your first case:

for w in words[:]

The for loop will iterate over new copy of the list not the original words. Any change in words has no effect on loop iteration, and the loop terminates normally.

This is how the loop does its work:

  1. loop calls iter method on iterable and iterates over the iterator

  2. loop calls next method on iterator object to get next item from iterator. This step is repeated until there are no more elements left

  3. loop terminates when a StopIteration exception is raised.

In your second case:

words = ['cat', 'window', 'defenestrate']
for w in words:
    if len(w) > 6:
        words.insert(0, w)
print(words)

You are iterating over the original list words and adding elements to words have a direct impact on the iterator object. So every time your words is updated, the corresponding iterator object is also updated and therefore creates an infinite loop.

Look at this:

>>> l = [2, 4, 6, 8]
>>> i = iter(l) # returns list_iterator object which has next method
>>> next(i)
2
>>> next(i)
4
>>> l.insert(2, 'A')
>>> next(i)
'A'

Every time you update your original list before StopIteration you will get the updated iterator and next returns accordingly. That's why your loop runs infinitely.

For more on iteration and the iteration protocol you can look here.

참고URL : https://stackoverflow.com/questions/44633798/what-is-the-meaning-of-list-in-this-code

반응형