len (generator ())하는 방법
이 질문에는 이미 답변이 있습니다.
- 발전기 출력 길이 [중복] 9 답변
- 생성기 / 반복기의 항목 수를 계산하는 가장 짧은 방법은 무엇입니까? 답변 6 개
파이썬 생성기 는 매우 유용합니다. 리스트를 리턴하는 함수보다 장점이 있습니다. 그러나 당신은 할 수 len(list_returning_function())
있습니다. 방법이 len(generator_function())
있습니까?
업데이트 :
물론 len(list(generator_function()))
작동합니다 .....
내가 생성하는 새 생성기 내부에서 생성 한 생성기를 사용하려고합니다. 새로운 발전기의 계산의 일부로 이전 발전기의 길이를 알아야합니다. 그러나 나는 둘 다 생성기와 동일한 속성으로 함께 유지하고 싶습니다. 특히 전체 목록이 너무 길 수 있으므로 메모리에 전체 목록을 유지하지 마십시오 .
업데이트 2 :
발전기 가 첫 번째 단계에서도 목표 길이를 알고 있다고 가정하십시오 . 또한 len()
구문 을 유지할 이유가 없습니다 . 예-파이썬의 함수가 객체 인 경우 새 생성기에 액세스 할 수있는이 객체의 변수에 길이를 할당 할 수 없습니까?
생성기는 길이가 없으며 결국 수집되지 않습니다.
제너레이터는 내부 상태 (및 고급 구문)를 가진 함수입니다 . 반복적으로 값을 호출하여 일련의 값을 얻을 수 있으므로 루프에서 사용할 수 있습니다. 그러나 어떤 요소도 포함하지 않으므로 생성기의 길이를 묻는 것은 함수의 길이를 묻는 것과 같습니다.
파이썬의 함수가 객체 인 경우 새 생성기에 액세스 할 수있는이 객체의 변수에 길이를 할당 할 수 없습니까?
함수는 객체이지만 새로운 속성을 할당 할 수 없습니다. 그 이유는 아마도 이러한 기본 객체를 가능한 한 효율적으로 유지하기 위해서 일 것입니다.
그러나 단순히 (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)
list
다른 대답에서 제안 된 변환 은 나중에 생성기 요소를 처리하려고하지만 결함이있는 경우 가장 좋은 방법입니다 .O (n) 메모리를 사용합니다. 다음과 같이 많은 메모리를 사용하지 않고 생성기의 요소를 계산할 수 있습니다.
sum(1 for x in generator)
물론 이것은 len(list(generator))
일반적인 파이썬 구현 보다 속도가 느릴 수 있으며 생성기가 메모리 복잡성을 중요하게 만들기에 충분히 길면 작업에 상당한 시간이 걸릴 수 있습니다. 아직도, 나는 개인적 으로이 솔루션을 선호하고 싶습니다. 필요하지 않은 추가 요소는 제공하지 않습니다 (예 : 모든 요소 목록).
또한 delnan의 조언을 들어보십시오. 생성기의 출력을 버릴 경우 요소를 실행하지 않고 또는 다른 방식으로 계산하여 요소 수를 계산하는 방법이있을 가능성이 큽니다.
발전기가 있다고 가정 해보십시오.
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)
사용할 수 있습니다 len(list(generator_function())
. 그러나 이것은 생성기를 소비하지만 이것이 생성되는 요소 수를 알 수있는 유일한 방법입니다. 따라서 항목을 사용하려는 경우 목록을 어딘가에 저장할 수 있습니다.
a = list(generator_function())
print(len(a))
print(a[0])
You can len(list(generator))
but you could probably make something more efficient if you really intend to discard the results.
You can use send
as a hack:
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
You can combine the benefits of generators with the certainty of len()
, by creating your own iterable object:
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,
This is basically a simple implementation of xrange
, which returns an object you can take the len of, but doesn't create an explicit list.
You can use reduce
.
For Python 3:
>>> import functools
>>> def gen():
... yield 1
... yield 2
... yield 3
...
>>> functools.reduce(lambda x,y: x + 1, gen(), 0)
In Python 2, reduce
is in the global namespace so the import is unnecessary.
참고URL : https://stackoverflow.com/questions/7460836/how-to-lengenerator
'development' 카테고리의 다른 글
이것이 의미하는 것은 : 실패 [INSTALL_FAILED_CONTAINER_ERROR]? (0) | 2020.07.06 |
---|---|
socket.io에서 클라이언트의 IP 주소를 가져옵니다 (0) | 2020.07.06 |
Git 태그는 현재 브랜치에만 적용됩니까? (0) | 2020.07.06 |
Visual Studio 2017 : 표시 방법 참조 (0) | 2020.07.06 |
Intellij에서 중복 코드 감지를 비활성화 할 수 있습니까? (0) | 2020.07.06 |