<질문>
Python generators 매우 유용합니다. 목록을 반환하는 함수보다 장점이 있습니다. 그러나 당신은 할 수 있습니다len(list_returning_function())
. 방법이 있나요len(generator_function())
?
업데이트:
물론len(list(generator_function()))
작동 할 것이다.....
생성 중인 새 생성기 내부에서 생성한 생성기를 사용하려고 합니다. 새 생성기에서 계산의 일부로 이전 생성기의 길이를 알아야 합니다. 그러나 나는 두 가지를 모두 생성기와 동일한 속성으로 유지하고 싶습니다. 특히 전체 목록을 메모리에 유지하지 마십시오.매우 긴.
업데이트 2:
발전기를 가정알고 있다 첫 번째 단계부터 목표 길이입니다. 또한 유지해야 할 이유가 없습니다.len()
통사론. 예 - Python의 함수가 객체인 경우 새 생성기가 액세스할 수 있는 이 객체의 변수에 길이를 할당할 수 없습니까?
<답변1>
로의 변환list
다른 답변에서 제안한 것은 나중에 여전히 생성기 요소를 처리하고 싶지만 한 가지 결함이 있는 경우 가장 좋은 방법입니다. O(n) 메모리를 사용합니다. 다음을 사용하여 많은 메모리를 사용하지 않고도 생성기의 요소를 계산할 수 있습니다.
sum(1 for x in generator)
물론 이것은len(list(generator))
일반적인 파이썬 구현에서, 그리고 생성기가 메모리 복잡성이 중요할 만큼 충분히 길다면, 작업은 꽤 오랜 시간이 걸릴 것입니다. 그래도 개인적으로 이 솔루션을 선호하는 이유는 내가 얻고자 하는 것을 설명하고 필요하지 않은 추가 항목(예: 모든 요소 목록)을 제공하지 않기 때문입니다.
또한 delnan의 조언을 들어보십시오. 생성기의 출력을 버리는 경우 요소를 실행하지 않고 또는 다른 방식으로 계산하여 요소 수를 계산하는 방법이 있을 가능성이 매우 높습니다.
<답변2>
Generator는 길이가 없으며 결국 컬렉션이 아닙니다.
발전기는내부 상태가 있는 기능 (그리고 멋진 구문). 반복적으로 호출하여 값 시퀀스를 얻을 수 있으므로 루프에서 사용할 수 있습니다. 그러나 요소가 포함되어 있지 않으므로 생성기의 길이를 묻는 것은 함수의 길이를 묻는 것과 같습니다.
파이썬의 함수가 객체라면 길이를 할당할 수 없습니까? 새 생성기에 액세스할 수 있는 이 개체의 변수는 무엇입니까?
함수는 객체이지만 새 속성을 할당할 수 없습니다. 그 이유는 아마도 그러한 기본 객체를 가능한 한 효율적으로 유지하기 위함일 것입니다.
그러나 간단히 반환할 수 있습니다.(generator, length)
함수에서 쌍을 만들거나 다음과 같은 간단한 객체로 생성기를 래핑합니다.
class GeneratorLen(object):
def __init__(self, gen, length):
self.gen = gen
self.length = length
def __len__(self):
return self.length
def __iter__(self):
return self.gen
g = some_generator()
h = GeneratorLen(g, 1)
print len(h), list(h)
<답변3>
생성기가 있다고 가정합니다.
def gen():
for i in range(10):
yield i
알려진 길이와 함께 생성기를 객체에 래핑할 수 있습니다.
import itertools
class LenGen(object):
def __init__(self,gen,length):
self.gen=gen
self.length=length
def __call__(self):
return itertools.islice(self.gen(),self.length)
def __len__(self):
return self.length
lgen=LenGen(gen,10)
의 인스턴스LenGen
호출하면 반복자가 반환되기 때문에 생성자 자체입니다.
이제 우리는 사용할 수 있습니다lgen
대신 발전기gen
및 액세스len(lgen)
또한:
def new_gen():
for i in lgen():
yield float(i)/len(lgen)
for i in new_gen():
print(i)
<답변4>
당신이 사용할 수있는len(list(generator_function())
. 그러나 이것은 생성기를 소비하지만 생성된 요소 수를 확인할 수 있는 유일한 방법입니다. 따라서 항목을 사용하려는 경우 목록을 어딘가에 저장하는 것이 좋습니다.
a = list(generator_function())
print(len(a))
print(a[0])
<답변5>
당신은 할 수 있습니다len(list(generator))
하지만 정말로 결과를 버리려고 한다면 더 효율적인 것을 만들 수 있을 것입니다.
<답변6>
당신이 사용할 수있는reduce
.
파이썬 3의 경우:
>>> import functools
>>> def gen():
... yield 1
... yield 2
... yield 3
...
>>> functools.reduce(lambda x,y: x + 1, gen(), 0)
파이썬 2에서는reduce
전역 네임스페이스에 있으므로 가져오기가 필요하지 않습니다.
<답변7>
당신이 사용할 수있는send
해킹으로:
def counter():
length = 10
i = 0
while i < length:
val = (yield i)
if val == 'length':
yield length
i += 1
it = counter()
print(it.next())
#0
print(it.next())
#1
print(it.send('length'))
#10
print(it.next())
#2
print(it.next())
#3
<답변8>
발전기의 이점과 다음의 확실성을 결합할 수 있습니다.len()
, 고유한 반복 가능한 객체를 생성하여:
class MyIterable(object):
def __init__(self, n):
self.n = n
def __len__(self):
return self.n
def __iter__(self):
self._gen = self._generator()
return self
def _generator(self):
# Put your generator code here
i = 0
while i < self.n:
yield i
i += 1
def next(self):
return next(self._gen)
mi = MyIterable(100)
print len(mi)
for i in mi:
print i,
이것은 기본적으로 간단한 구현입니다.xrange
, len을 취할 수 있는 객체를 반환하지만 명시적 목록을 생성하지는 않습니다.
'개발 > Python' 카테고리의 다른 글
[파이썬] 멀티스레딩은 모든 스레드가 완료될 때까지 기다립니다 (0) | 2022.10.12 |
---|---|
[파이썬] py.test 내부 사용 중단 경고를 억제하는 방법 (0) | 2022.10.12 |
[파이썬] pandas DataFrame의 첫 번째 열을 시리즈로 가져오는 방법은 무엇입니까? (0) | 2022.10.12 |
[파이썬] 블록 범위 (0) | 2022.10.11 |