Làm thế nào để tôi biết nếu một máy phát điện trống từ đầu?


146

Có một cách đơn giản để kiểm tra nếu máy phát điện không có mặt hàng, như peek, hasNext, isEmpty, một cái gì đó dọc theo những đường?


Sửa lỗi cho tôi nếu tôi sai, nhưng nếu bạn có thể đưa ra một giải pháp thực sự chung cho bất kỳ trình tạo nào , thì nó sẽ tương đương với việc thiết lập các điểm dừng trên các báo cáo lợi tức và có khả năng "lùi bước". Điều đó có nghĩa là nhân bản khung stack trên sản lượng và khôi phục chúng trên StopIteration?

Chà, tôi đoán có thể khôi phục chúng StopIteration hay không, nhưng ít nhất StopIteration sẽ cho bạn biết nó trống. Vâng tôi cần ngủ ...

4
Tôi nghĩ rằng tôi biết tại sao anh ấy muốn điều này. Nếu bạn đang thực hiện phát triển web với các mẫu và chuyển giá trị trả về vào một mẫu như Cheetah hoặc một cái gì đó, danh sách trống []là Falsey thuận tiện để bạn có thể thực hiện nếu kiểm tra trên đó và thực hiện hành vi đặc biệt cho một cái gì đó hoặc không có gì. Máy phát điện là đúng ngay cả khi chúng không mang lại yếu tố nào.
jpsimons

Đây là trường hợp sử dụng của tôi ... Tôi đang sử dụng glob.iglob("filepattern")trên mẫu ký tự đại diện do người dùng cung cấp và tôi muốn cảnh báo người dùng nếu mẫu đó không khớp với bất kỳ tệp nào. Chắc chắn tôi có thể giải quyết vấn đề này theo nhiều cách khác nhau, nhưng thật hữu ích khi có thể kiểm tra rõ ràng xem trình lặp có bị trống hay không.
LarsH

Có thể sử dụng giải pháp này: stackoverflow.com/a/11467686/463758
balki

Câu trả lời:


53

Câu trả lời đơn giản cho câu hỏi của bạn: không, không có cách nào đơn giản. Có rất nhiều công việc xung quanh.

Thực sự không nên có một cách đơn giản, bởi vì các trình tạo là gì: một cách để tạo ra một chuỗi các giá trị mà không giữ chuỗi trong bộ nhớ . Vì vậy, không có truyền thống lạc hậu.

Bạn có thể viết hàm has_next hoặc thậm chí có thể đưa nó vào trình tạo như một phương thức với trình trang trí lạ mắt nếu bạn muốn.


2
đủ công bằng, điều đó có ý nghĩa tôi biết không có cách nào để tìm ra chiều dài của một máy phát điện, nhưng nghĩ rằng tôi có thể đã bỏ lỡ một cách tìm kiếm nếu ban đầu nó sẽ tạo ra bất cứ thứ gì.
Dan

1
Ồ, và để tham khảo, tôi đã thử thực hiện gợi ý "trang trí lạ mắt" của riêng tôi. CỨNG. Rõ ràng copy.deepcopy không hoạt động trên máy phát điện.
David Berger

47
Tôi không chắc mình có thể đồng ý với "không nên có một cách đơn giản". Có rất nhiều khái niệm trừu tượng trong khoa học máy tính được thiết kế để đưa ra một chuỗi các giá trị mà không giữ chuỗi đó trong bộ nhớ, nhưng điều đó cho phép lập trình viên hỏi liệu có giá trị nào khác mà không loại bỏ nó khỏi "hàng đợi" hay không. Có những thứ như nhìn trộm trước mà không yêu cầu "di chuyển ngược". Điều đó không có nghĩa là một thiết kế lặp phải cung cấp một tính năng như vậy, nhưng nó chắc chắn là hữu ích. Có lẽ bạn đang phản đối trên cơ sở rằng giá trị đầu tiên có thể thay đổi sau khi nhìn trộm?
LarsH

9
Tôi phản đối với lý do rằng một triển khai điển hình thậm chí không tính được giá trị cho đến khi cần. Người ta có thể buộc giao diện thực hiện điều này, nhưng điều đó có thể là tối ưu phụ cho việc triển khai nhẹ.
David Berger

6
@ S.Lott bạn không cần tạo toàn bộ chuỗi để biết chuỗi đó có trống hay không. Giá trị lưu trữ của một yếu tố là đủ - xem câu trả lời của tôi.
Đánh dấu tiền chuộc

98

Gợi ý:

def peek(iterable):
    try:
        first = next(iterable)
    except StopIteration:
        return None
    return first, itertools.chain([first], iterable)

Sử dụng:

res = peek(mysequence)
if res is None:
    # sequence is empty.  Do stuff.
else:
    first, mysequence = res
    # Do something with first, maybe?
    # Then iterate over the sequence:
    for element in mysequence:
        # etc.

2
Tôi hoàn toàn không nhận được điểm trả lại phần tử đầu tiên hai lần return first, itertools.chain([first], rest).
njzk2

6
@ njzk2 Tôi đang thực hiện thao tác "peek" (do đó là tên hàm). wiki "peek là một hoạt động trả về giá trị của đỉnh của bộ sưu tập mà không xóa giá trị khỏi dữ liệu"
John Fouhy

Điều này sẽ không hoạt động nếu máy phát điện được thiết kế để mang lại Không có. def gen(): for pony in range(4): yield None if pony == 2 else pony
Paul

4
@Paul Nhìn vào các giá trị trả lại chặt chẽ. Nếu trình tạo được thực hiện - tức là không quay lại Nonemà tăng StopIteration- kết quả của hàm là None. Mặt khác, nó là một tuple, mà không phải None.
Vụ kiện của Quỹ Monica

Điều này đã giúp tôi rất nhiều với dự án hiện tại của tôi. Tôi đã tìm thấy một ví dụ tương tự trong mã cho mô-đun thư viện tiêu chuẩn 'hộp thư' của python. This method is for backward compatibility only. def next(self): """Return the next message in a one-time iteration.""" if not hasattr(self, '_onetime_keys'): self._onetime_keys = self.iterkeys() while True: try: return self[next(self._onetime_keys)] except StopIteration: return None except KeyError: continue
ngang hàng

29

Một cách đơn giản là sử dụng tham số tùy chọn cho next () được sử dụng nếu trình tạo hết (hoặc trống). Ví dụ:

iterable = some_generator()

_exhausted = object()

if next(iterable, _exhausted) == _exhausted:
    print('generator is empty')

Chỉnh sửa: Khắc phục sự cố được chỉ ra trong nhận xét của mehtunguh.


1
Không. Điều này không chính xác đối với bất kỳ trình tạo nào có giá trị đầu tiên mang lại là không đúng sự thật.
mehtunguh

7
Sử dụng object()thay vì classlàm cho nó ngắn hơn một dòng : _exhausted = object(); if next(iterable, _exhausted) is _exhausted:
Messa

13

next(generator, None) is not None

Hoặc thay thế Nonenhưng bất kỳ giá trị nào bạn biết nó không có trong máy phát điện của bạn.

Chỉnh sửa : Có, điều này sẽ bỏ qua 1 mục trong trình tạo. Tuy nhiên, thường thì tôi kiểm tra xem một trình tạo có trống chỉ cho mục đích xác nhận hay không, sau đó không thực sự sử dụng nó. Hoặc nếu không tôi làm một cái gì đó như:

def foo(self):
    if next(self.my_generator(), None) is None:
        raise Exception("Not initiated")

    for x in self.my_generator():
        ...

Đó là, điều này hoạt động nếu trình tạo của bạn đến từ một chức năng , như trong generator().


4
Tại sao đây không phải là câu trả lời tốt nhất? Trong trường hợp máy phát điện trở lại None?
Sait

8
Có lẽ bởi vì điều này buộc bạn phải thực sự tiêu thụ máy phát điện thay vì chỉ kiểm tra nếu nó trống.
bfontaine

3
Thật tệ vì khoảnh khắc bạn gọi tiếp theo (máy phát điện, Không có) bạn sẽ bỏ qua 1 mục nếu nó khả dụng
Nathan Do

Chính xác, bạn sẽ bỏ lỡ yếu tố thứ 1 trong gen của bạn và bạn cũng sẽ sử dụng gen của mình thay vì thử nghiệm nếu nó trống.
AJ

12

Cách tiếp cận tốt nhất, IMHO, sẽ là tránh một bài kiểm tra đặc biệt. Hầu hết các lần, sử dụng máy phát điện thử nghiệm:

thing_generated = False

# Nothing is lost here. if nothing is generated, 
# the for block is not executed. Often, that's the only check
# you need to do. This can be done in the course of doing
# the work you wanted to do anyway on the generated output.
for thing in my_generator():
    thing_generated = True
    do_work(thing)

Nếu điều đó không đủ tốt, bạn vẫn có thể thực hiện một bài kiểm tra rõ ràng. Tại thời điểm này, thingsẽ chứa giá trị cuối cùng được tạo. Nếu không có gì được tạo, nó sẽ không được xác định - trừ khi bạn đã xác định biến. Bạn có thể kiểm tra giá trị của thing, nhưng điều đó không đáng tin cậy một chút. Thay vào đó, chỉ cần đặt cờ trong khối và kiểm tra nó sau đó:

if not thing_generated:
    print "Avast, ye scurvy dog!"

3
Giải pháp này sẽ cố gắng tiêu thụ toàn bộ máy phát điện, do đó làm cho nó không thể sử dụng được cho các máy phát vô hạn.
Viktor Stískala

@ ViktorStískala: Tôi không thấy quan điểm của bạn. Sẽ thật ngu ngốc khi kiểm tra nếu một máy phát vô hạn tạo ra bất kỳ kết quả nào.
vezult

Tôi muốn chỉ ra rằng giải pháp của bạn có thể chứa sự phá vỡ trong vòng lặp for, bởi vì bạn không xử lý các kết quả khác và việc chúng được tạo ra là vô ích. range(10000000)là trình tạo hữu hạn (Python 3), nhưng bạn không cần phải xem qua tất cả các mục để tìm hiểu xem nó có tạo ra thứ gì không.
Viktor Stískala

1
@ ViktorStískala: Đã hiểu. Tuy nhiên, quan điểm của tôi là thế này: Nói chung, bạn thực sự muốn hoạt động trên đầu ra của trình tạo. Trong ví dụ của tôi, nếu không có gì được tạo ra, bây giờ bạn biết điều đó. Mặt khác, bạn hoạt động trên đầu ra được tạo như dự định - "Việc sử dụng trình tạo là thử nghiệm". Không cần thử nghiệm đặc biệt, hoặc tiêu thụ đầu ra máy phát một cách vô nghĩa. Tôi đã chỉnh sửa câu trả lời của mình để làm rõ điều này.
vezult

8

Tôi ghét đưa ra một giải pháp thứ hai, đặc biệt là giải pháp mà tôi sẽ không sử dụng cho mình, nhưng, nếu bạn hoàn toàn phải làm điều này và không tiêu thụ máy phát điện, như trong các câu trả lời khác:

def do_something_with_item(item):
    print item

empty_marker = object()

try:
     first_item = my_generator.next()     
except StopIteration:
     print 'The generator was empty'
     first_item = empty_marker

if first_item is not empty_marker:
    do_something_with_item(first_item)
    for item in my_generator:
        do_something_with_item(item)

Bây giờ tôi thực sự không thích giải pháp này, vì tôi tin rằng đây không phải là cách sử dụng máy phát điện.


4

Tôi nhận ra rằng bài đăng này đã 5 tuổi vào thời điểm này, nhưng tôi đã tìm thấy nó trong khi tìm kiếm một cách thành ngữ để làm điều này, và không thấy giải pháp của tôi được đăng. Vì vậy, cho hậu thế:

import itertools

def get_generator():
    """
    Returns (bool, generator) where bool is true iff the generator is not empty.
    """
    gen = (i for i in [0, 1, 2, 3, 4])
    a, b = itertools.tee(gen)
    try:
        a.next()
    except StopIteration:
        return (False, b)
    return (True, b)

Tất nhiên, như tôi chắc chắn rằng nhiều nhà bình luận sẽ chỉ ra, đây là hacky và chỉ hoạt động ở tất cả các tình huống hạn chế nhất định (ví dụ như các máy phát điện không có tác dụng phụ). YMMV.


1
Điều này sẽ chỉ gọi trình gentạo một lần cho mỗi mục, vì vậy tác dụng phụ không phải là vấn đề quá tệ. Nhưng nó sẽ lưu trữ một bản sao của tất cả mọi thứ đã được kéo từ máy phát qua b, nhưng không thông qua a, do đó, hàm ý bộ nhớ tương tự như chỉ chạy list(gen)và kiểm tra điều đó.
Matthias Fripp

Nó có hai vấn đề. 1. itertool này có thể yêu cầu lưu trữ phụ trợ đáng kể (tùy thuộc vào lượng dữ liệu tạm thời cần được lưu trữ). Nói chung, nếu một iterator sử dụng hầu hết hoặc tất cả dữ liệu trước khi một iterator khác bắt đầu, thì việc sử dụng list () thay vì tee () sẽ nhanh hơn. 2. lặp iterators không phải là chủ đề an toàn. Một RuntimeError có thể được nâng lên khi sử dụng các trình lặp đồng thời được trả về bởi cùng một lệnh gọi tee (), ngay cả khi lần lặp ban đầu là chủ đề an toàn.
AJ

3

Xin lỗi vì cách tiếp cận rõ ràng, nhưng cách tốt nhất sẽ là:

for item in my_generator:
     print item

Bây giờ bạn đã phát hiện ra rằng trình tạo trống trong khi bạn đang sử dụng nó. Tất nhiên, mục sẽ không bao giờ được hiển thị nếu trình tạo trống.

Điều này có thể không hoàn toàn phù hợp với mã của bạn, nhưng đây là thành ngữ của trình tạo là: lặp đi lặp lại, vì vậy có lẽ bạn có thể thay đổi cách tiếp cận của mình một chút hoặc hoàn toàn không sử dụng trình tạo.


Hoặc ... người hỏi có thể cung cấp một số gợi ý về lý do tại sao một người sẽ cố gắng phát hiện một trình tạo trống?
S.Lott

ý bạn là "không có gì sẽ được hiển thị vì trình tạo trống"?
SilentGhost

S.Lott. Tôi đồng ý. Tôi không thể hiểu tại sao. Nhưng tôi nghĩ ngay cả khi có một lý do, vấn đề có thể tốt hơn là chuyển sang sử dụng từng mục thay thế.
Ali Afshar

1
Điều này không cho biết chương trình nếu máy phát điện trống.
Ethan Furman

3

Tất cả những gì bạn cần làm để xem máy phát điện có trống không là cố gắng để có kết quả tiếp theo. Tất nhiên nếu bạn chưa sẵn sàng sử dụng kết quả đó thì bạn phải lưu nó để trả lại sau.

Đây là một lớp bao bọc có thể được thêm vào một trình vòng lặp hiện có để thêm một __nonzero__bài kiểm tra, vì vậy bạn có thể xem liệu trình tạo có trống không với một đơn giản if. Nó có lẽ cũng có thể được biến thành một trang trí.

class GenWrapper:
    def __init__(self, iter):
        self.source = iter
        self.stored = False

    def __iter__(self):
        return self

    def __nonzero__(self):
        if self.stored:
            return True
        try:
            self.value = next(self.source)
            self.stored = True
        except StopIteration:
            return False
        return True

    def __next__(self):  # use "next" (without underscores) for Python 2.x
        if self.stored:
            self.stored = False
            return self.value
        return next(self.source)

Đây là cách bạn sử dụng nó:

with open(filename, 'r') as f:
    f = GenWrapper(f)
    if f:
        print 'Not empty'
    else:
        print 'Empty'

Lưu ý rằng bạn có thể kiểm tra sự trống rỗng bất cứ lúc nào, không chỉ khi bắt đầu lặp lại.


Điều này đang đi đúng hướng. Nó nên được sửa đổi để cho phép nhìn trộm trước như bạn muốn, lưu trữ càng nhiều kết quả nếu cần. Lý tưởng nhất là nó sẽ cho phép đẩy các vật phẩm tùy ý lên đầu luồng. Một Pushter-iterator là một bản tóm tắt rất hữu ích mà tôi thường sử dụng.
sfkleach

@sfkleach Tôi không thấy cần phải phức tạp hóa vấn đề này cho nhiều người nhìn trước, nó khá hữu ích và trả lời câu hỏi. Mặc dù đây là một câu hỏi cũ, nó vẫn nhận được giao diện không thường xuyên, vì vậy nếu bạn muốn để lại câu trả lời của riêng mình, ai đó có thể thấy nó hữu ích.
Đánh dấu tiền chuộc

Mark hoàn toàn đúng khi giải pháp của anh trả lời câu hỏi, đó là điểm chính. Tôi nên phras nó tốt hơn. Điều tôi muốn nói là các trình lặp có thể đẩy được với việc đẩy lùi không giới hạn là một thành ngữ tôi thấy cực kỳ hữu ích và việc thực hiện thậm chí còn đơn giản hơn. Theo đề xuất tôi sẽ đăng mã biến thể.
sfkleach

2

Được nhắc nhở bởi Mark Ransom, đây là một lớp mà bạn có thể sử dụng để bọc bất kỳ trình vòng lặp nào để bạn có thể nhìn trộm phía trước, đẩy các giá trị trở lại luồng và kiểm tra trống. Đó là một ý tưởng đơn giản với cách thực hiện đơn giản mà trước đây tôi thấy rất tiện dụng.

class Pushable:

    def __init__(self, iter):
        self.source = iter
        self.stored = []

    def __iter__(self):
        return self

    def __bool__(self):
        if self.stored:
            return True
        try:
            self.stored.append(next(self.source))
        except StopIteration:
            return False
        return True

    def push(self, value):
        self.stored.append(value)

    def peek(self):
        if self.stored:
            return self.stored[-1]
        value = next(self.source)
        self.stored.append(value)
        return value

    def __next__(self):
        if self.stored:
            return self.stored.pop()
        return next(self.source)

2

Chỉ cần rơi vào chủ đề này và nhận ra rằng một câu trả lời rất đơn giản và dễ đọc đã bị thiếu:

def is_empty(generator):
    for item in generator:
        return False
    return True

Nếu chúng ta không giả sử tiêu thụ bất kỳ vật phẩm nào thì chúng ta cần phải tiêm lại vật phẩm đầu tiên vào máy phát điện:

def is_empty_no_side_effects(generator):
    try:
        item = next(generator)
        def my_generator():
            yield item
            yield from generator
        return my_generator(), False
    except StopIteration:
        return (_ for _ in []), True

Thí dụ:

>>> g=(i for i in [])
>>> g,empty=is_empty_no_side_effects(g)
>>> empty
True
>>> g=(i for i in range(10))
>>> g,empty=is_empty_no_side_effects(g)
>>> empty
False
>>> list(g)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

1
>>> gen = (i for i in [])
>>> next(gen)
Traceback (most recent call last):
  File "<pyshell#43>", line 1, in <module>
    next(gen)
StopIteration

Khi kết thúc trình tạo StopIterationđược nâng lên, vì trong trường hợp của bạn kết thúc ngay lập tức, ngoại lệ được đưa ra. Nhưng thông thường, bạn không nên kiểm tra sự tồn tại của giá trị tiếp theo.

một điều khác bạn có thể làm là:

>>> gen = (i for i in [])
>>> if not list(gen):
    print('empty generator')

2
Mà thực sự tiêu thụ toàn bộ máy phát điện. Đáng buồn thay, nó không rõ ràng từ câu hỏi nếu đây là hành vi mong muốn hoặc không mong muốn.
S.Lott

như bất kỳ cách nào khác của "chạm" máy phát điện, tôi cho rằng.
SilentGhost

Tôi nhận ra điều này đã cũ, nhưng sử dụng 'list ()' không thể là cách tốt nhất, nếu danh sách được tạo không trống nhưng thực tế thì điều này thật lãng phí
Chris_Rands

1

Nếu bạn cần biết trước khi sử dụng trình tạo, thì không, không có cách nào đơn giản. Nếu bạn có thể đợi cho đến khi bạn sử dụng trình tạo, có một cách đơn giản:

was_empty = True

for some_item in some_generator:
    was_empty = False
    do_something_with(some_item)

if was_empty:
    handle_already_empty_generator_case()

1

Đơn giản chỉ cần bọc trình tạo bằng itertools.chain , đặt một cái gì đó sẽ đại diện cho phần cuối của lần lặp là lần lặp thứ hai, sau đó chỉ cần kiểm tra xem.

Ví dụ:

import itertools

g = some_iterable
eog = object()
wrap_g = itertools.chain(g, [eog])

Bây giờ tất cả những gì còn lại là để kiểm tra giá trị đó mà chúng tôi đã thêm vào cuối của lần lặp, khi bạn đọc nó thì điều đó sẽ biểu thị sự kết thúc

for value in wrap_g:
    if value == eog: # DING DING! We just found the last element of the iterable
        pass # Do something

Sử dụng eog = object()thay vì cho rằng điều đó float('-inf')sẽ không bao giờ xảy ra trong vòng lặp.
bfontaine

@bfontaine Ý kiến ​​hay
smac89

1

Trong trường hợp của tôi, tôi cần phải biết liệu một loạt các máy phát điện có được đưa vào hay không trước khi tôi chuyển nó sang một hàm, hợp nhất các mục, tức là , zip(...). Giải pháp tương tự, nhưng đủ khác nhau, từ câu trả lời được chấp nhận:

Định nghĩa:

def has_items(iterable):
    try:
        return True, itertools.chain([next(iterable)], iterable)
    except StopIteration:
        return False, []

Sử dụng:

def filter_empty(iterables):
    for iterable in iterables:
        itr_has_items, iterable = has_items(iterable)
        if itr_has_items:
            yield iterable


def merge_iterables(iterables):
    populated_iterables = filter_empty(iterables)
    for items in zip(*populated_iterables):
        # Use items for each "slice"

Vấn đề cụ thể của tôi có thuộc tính là các iterables trống hoặc có chính xác cùng số lượng mục nhập.


1

Tôi chỉ tìm thấy giải pháp này khi làm việc cho các lần lặp trống.

def is_generator_empty(generator):
    a, b = itertools.tee(generator)
    try:
        next(a)
    except StopIteration:
        return True, b
    return False, b

is_empty, generator = is_generator_empty(generator)

Hoặc nếu bạn không muốn sử dụng ngoại lệ cho việc này hãy thử sử dụng

def is_generator_empty(generator):
    a, b = itertools.tee(generator)
    for item in a:
        return False, b
    return True, b

is_empty, generator = is_generator_empty(generator)

Trong giải pháp được đánh dấu, bạn không thể sử dụng nó cho các trình tạo trống như

def get_empty_generator():
    while False:
        yield None 

generator = get_empty_generator()


0

Đây là cách tiếp cận đơn giản của tôi mà tôi sử dụng để tiếp tục trả về một trình vòng lặp trong khi kiểm tra xem có cái gì mang lại không, tôi chỉ kiểm tra xem vòng lặp có chạy không:

        n = 0
        for key, value in iterator:
            n+=1
            yield key, value
        if n == 0:
            print ("nothing found in iterator)
            break

0

Đây là một trình trang trí đơn giản bao bọc trình tạo, vì vậy nó trả về Không nếu trống. Điều này có thể hữu ích nếu mã của bạn cần biết liệu trình tạo sẽ tạo ra bất cứ thứ gì trước khi lặp qua nó.

def generator_or_none(func):
    """Wrap a generator function, returning None if it's empty. """

    def inner(*args, **kwargs):
        # peek at the first item; return None if it doesn't exist
        try:
            next(func(*args, **kwargs))
        except StopIteration:
            return None

        # return original generator otherwise first item will be missing
        return func(*args, **kwargs)

    return inner

Sử dụng:

import random

@generator_or_none
def random_length_generator():
    for i in range(random.randint(0, 10)):
        yield i

gen = random_length_generator()
if gen is None:
    print('Generator is empty')

Một ví dụ trong đó điều này hữu ích là trong mã tạo khuôn mẫu - tức là jinja2

{% if content_generator %}
  <section>
    <h4>Section title</h4>
    {% for item in content_generator %}
      {{ item }}
    {% endfor %
  </section>
{% endif %}

Điều này gọi chức năng của trình tạo hai lần, do đó sẽ phải chịu chi phí khởi động của trình tạo hai lần. Điều đó có thể là đáng kể nếu, ví dụ, hàm tạo là một truy vấn cơ sở dữ liệu.
Ian Goldby

0

bằng cách sử dụng islice, bạn chỉ cần kiểm tra lần lặp đầu tiên để khám phá nếu nó trống.

từ itertools nhập islice

def isempty (iterable):
    danh sách trả về (islice (iterable, 1)) == []


Xin lỗi, đây là một bài đọc tiêu tốn ... Phải thực hiện thử / bắt với StopIteration
Quin

0

Điều gì về việc sử dụng bất kỳ ()? Tôi sử dụng nó với máy phát điện và nó hoạt động tốt. Ở đây có anh chàng giải thích một chút về điều này


2
Chúng tôi không thể sử dụng "any ()" cho mọi thứ. Chỉ cần cố gắng sử dụng nó với một trình tạo có chứa nhiều datafram. Tôi nhận được thông báo này "Giá trị thật của DataFrame là mơ hồ." trên bất kỳ (my_generator_of_df)
probitaille

any(generator)hoạt động khi bạn biết trình tạo sẽ tạo ra các giá trị có thể được truyền tới bool- các kiểu dữ liệu cơ bản (ví dụ: int, chuỗi) hoạt động. any(generator)sẽ là Sai khi trình tạo trống hoặc khi trình tạo chỉ có các giá trị sai - ví dụ: nếu trình tạo sẽ tạo 0, '' (chuỗi trống) và Sai, thì nó vẫn sẽ là Sai. Đây có thể hoặc không thể là hành vi dự định, miễn là bạn biết về nó :)
Daniel

0

Sử dụng chức năng peek trong cytoolz.

from cytoolz import peek
from typing import Tuple, Iterable

def is_empty_iterator(g: Iterable) -> Tuple[Iterable, bool]:
    try:
        _, g = peek(g)
        return g, False
    except StopIteration:
        return g, True

Trình lặp được trả về bởi hàm này sẽ tương đương với hàm ban đầu được truyền vào dưới dạng đối số.


-2

Tôi đã giải quyết nó bằng cách sử dụng hàm sum. Xem bên dưới để biết ví dụ tôi đã sử dụng với global.iglob (trả về một trình tạo).

def isEmpty():
    files = glob.iglob(search)
    if sum(1 for _ in files):
        return True
    return False

* Điều này có thể sẽ không hoạt động cho các trình tạo HUGE nhưng sẽ hoạt động tốt cho các danh sách nhỏ hơn

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.