2011-06-20 58 views
94

Trong python, làm cách nào để kiểm tra xem đối tượng có phải là đối tượng máy phát không?Làm thế nào để kiểm tra xem một đối tượng là một đối tượng máy phát trong python?

Cố gắng này -

>>> type(myobject, generator) 

cung cấp cho các lỗi -

Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
NameError: name 'generator' is not defined 

(Tôi biết tôi có thể kiểm tra nếu đối tượng có một phương pháp next cho nó trở thành một máy phát điện, nhưng tôi muốn có một số cách sử dụng mà tôi có thể xác định loại đối tượng bất kỳ, không chỉ máy phát điện.)

+3

Bạn đang cố giải quyết vấn đề thực tế nào? Đăng thêm ngữ cảnh, có thể có cách thông minh hơn. Tại sao bạn cần phải biết nếu nó là một máy phát điện? – Daenyth

+4

'từ kiểu nhập GeneratorType; type (myobject, GeneratorType)' sẽ cho bạn kết quả phù hợp với các đối tượng của lớp 'generator'. Nhưng như Daenyth ngụ ý, đó không nhất thiết phải là con đường đúng đắn để đi. – JAB

+6

Nếu bạn đang kiểm tra '__next__', bạn thực sự chấp nhận bất kỳ trình lặp nào, không chỉ các trình tạo - rất có thể là những gì bạn muốn. – delnan

Trả lời

138

Bạn có thể sử dụng GeneratorType từ các loại:

>>> import types 
>>> types.GeneratorType 
<class 'generator'> 
>>> gen = (i for i in range(10)) 
>>> isinstance(gen, types.GeneratorType) 
True 
23

Bạn có nghĩa là các chức năng của trình tạo? sử dụng inspect.isgeneratorfunction.

EDIT:

nếu bạn muốn có một đối tượng phát bạn có thể sử dụng inspect.isgenerator như chỉ ra bởi JAB trong bình luận của ông.

+1

chức năng máy phát không phải là đối tượng máy phát; xem câu trả lời của @ utdemir –

+2

@Piotr: Trong trường hợp này bạn sử dụng ['inspect.isgenerator'] (http://docs.python.org/library/inspect.html#inspect.isgenerator). – JAB

+0

@JAB, @Piotr: Phản ánh để giải quyết tất cả các khả năng của OP có nghĩa là gì, cảm ơn JAB :) – mouad

2

Tôi biết tôi có thể kiểm tra nếu đối tượng có một phương pháp tiếp theo cho nó trở thành một máy phát điện, nhưng tôi muốn có một số cách sử dụng mà tôi có thể xác định loại đối tượng bất kỳ, không chỉ máy phát điện.

Đừng làm điều này. Nó đơn giản là một ý tưởng rất, rất tệ.

Thay vào đó, làm điều này:

try: 
    # Attempt to see if you have an iterable object. 
    for i in some_thing_which_may_be_a_generator: 
     # The real work on `i` 
except TypeError: 
    # some_thing_which_may_be_a_generator isn't actually a generator 
    # do something else 

Trong trường hợp không chắc rằng cơ thể của cho loop cũng có TypeError s, có một số lựa chọn: (1) xác định một chức năng để giới hạn phạm vi các lỗi hoặc (2) sử dụng một khối lồng nhau thử.

Hoặc (3) một cái gì đó như thế này để phân biệt tất cả các số này TypeError s đang trôi nổi xung quanh.

try: 
    # Attempt to see if you have an iterable object. 
    # In the case of a generator or iterator iter simply 
    # returns the value it was passed. 
    iterator = iter(some_thing_which_may_be_a_generator) 
except TypeError: 
    # some_thing_which_may_be_a_generator isn't actually a generator 
    # do something else 
else: 
    for i in iterator: 
     # the real work on `i` 

Hoặc (4) sửa các phần khác của ứng dụng để cung cấp máy phát điện phù hợp. Điều đó thường đơn giản hơn tất cả điều này.

+1

Giải pháp của bạn sẽ bắt được TypeErrors được ném bởi phần thân của vòng lặp for. Tôi đã đề xuất một bản chỉnh sửa có thể ngăn chặn hành vi không mong muốn này. – Dunes

+0

Đây là cách thực hiện nhiều thứ Pythonic hơn, nếu tôi không nhầm. – JAB

+0

Mặc dù, nếu bạn đang lặp qua danh sách các mục và nhiều hơn trong số chúng không phải là vòng lặp hơn là các trình vòng lặp thì điều này có thể mất nhiều thời gian hơn? –

2
>>> import inspect 
>>> 
>>> def foo(): 
... yield 'foo' 
... 
>>> print inspect.isgeneratorfunction(foo) 
True 
+0

Tính năng này chỉ hoạt động nếu nó là một chức năng. Nếu 'foo' là một đối tượng máy phát, nó hiển thị 'False'. Xem câu hỏi của tôi, tôi muốn kiểm tra đối tượng máy phát điện. –

+1

inspect.isgenerator –

9

Chức năng inspect.isgenerator là tốt nếu bạn muốn kiểm tra máy phát điện thuần túy (tức là đối tượng của máy phát điện ")". Tuy nhiên, nó sẽ trả lại False nếu bạn kiểm tra, ví dụ: izip có thể lặp lại.Một cách khác để kiểm tra cho một máy phát điện tổng quát là sử dụng chức năng này:

def isgenerator(iterable): 
    return hasattr(iterable,'__iter__') and not hasattr(iterable,'__len__') 
+1

Hmm. Điều này trả về true cho 'x = iter ([1,2])'. Dường như với tôi nó thực sự thử nghiệm có hay không một đối tượng là một ** iterator **, không phải là một máy phát điện. Nhưng có lẽ "iterator" là chính xác những gì bạn có nghĩa là "máy phát điện tổng quát". –

10

Tôi nghĩ rằng điều quan trọng là làm cho sự phân biệt giữa chức năng máy phát điệnphát (kết quả chức năng máy phát điện của):

>>> def generator_function(): 
...  yield 1 
...  yield 2 
... 
>>> import inspect 
>>> inspect.isgeneratorfunction(generator_function) 
True 

gọi generator_function sẽ không mang lại kết quả bình thường, thậm chí nó sẽ không thực thi bất kỳ mã nào trong chính hàm đó, kết quả sẽ là đối tượng đặc biệt được gọi là generator:

>>> generator = generator_function() 
>>> generator 
<generator object generator_function at 0x10b3f2b90> 

nên nó không phải là chức năng máy phát điện, tuy nhiên trình tạo:

>>> inspect.isgeneratorfunction(generator) 
False 

>>> import types 
>>> isinstance(generator, types.GeneratorType) 
True 

và chức năng máy phát điện không phải là máy phát điện:

>>> isinstance(generator_function, types.GeneratorType) 
False 

chỉ dành riêng cho một tài liệu tham khảo, cuộc gọi thực tế của cơ quan chức năng sẽ xảy ra bằng cách tiêu thụ máy phát điện, ví dụ:

>>> list(generator) 
[1, 2] 

Xem thêm In python is there a way to check if a function is a "generator function" before calling it?

1

Nếu bạn đang sử dụng máy chủ web lốc xoáy hoặc tương tự, bạn có thể thấy rằng các phương thức máy chủ thực sự là máy phát và không phải là phương pháp. Điều này khiến cho việc gọi các phương thức khác trở nên khó khăn vì năng suất không hoạt động bên trong phương thức và do đó bạn cần bắt đầu quản lý các nhóm đối tượng tạo chuỗi. Một phương pháp đơn giản để quản lý nhóm của máy phát điện xích là tạo ra một chức năng giúp đỡ như

def chainPool(*arg): 
    for f in arg: 
     if(hasattr(f,"__iter__")): 
      for e in f: 
      yield e 
     else: 
     yield f 

Bây giờ viết máy phát điện bị xích như

[x for x in chainPool(chainPool(1,2),3,4,chainPool(5,chainPool(6)))] 

Tạo ra

[1, 2, 3, 4, 5, 6] 

Mà có lẽ là những gì bạn muốn nếu bạn đang tìm kiếm để sử dụng máy phát điện như là một thay thế thread hoặc tương tự.

Các vấn đề liên quan