2009-10-13 47 views
13

Tôi đang tìm cách đảo ngược đối tượng máy phát điện. Tôi biết làm thế nào để đảo ngược trình tự:Máy phát điện đảo ngược Python

foo = imap(seq.__getitem__, xrange(len(seq)-1, -1, -1)) 

Nhưng là một cái gì đó tương tự có thể với một máy phát điện như các đầu vào và một máy phát điện đảo ngược như đầu ra (len (seq) giữ nguyên, vì vậy giá trị từ chuỗi ban đầu có thể được đã sử dụng)?

+3

Tôi phải ngoại lệ với ví dụ về việc đảo ngược chuỗi của bạn. Tại sao không chỉ sử dụng 'đảo ngược'? hoặc '.reverse'? Ngay cả 'seq [:: - 1]' rõ ràng hơn những gì bạn viết. –

+0

Bởi vì tất cả các ví dụ này sẽ tạo một danh sách mới. Ví dụ của tôi ở trên là cách duy nhất tôi biết để tạo danh sách mà không cần sao chép trước. –

+0

Vâng, tôi đã học được một cái gì đó mới - seq [:: - 1] * không * trong thực tế tạo ra một danh sách mới. Xem câu trả lời biểu thức trình tạo của tôi cho một thay thế bằng cách sử dụng các chỉ số tiêu cực. – PaulMcG

Trả lời

19

Bạn không thể đảo ngược trình tạo theo bất kỳ cách thức chung nào ngoại trừ bằng cách truyền nó thành một chuỗi và tạo một trình lặp từ đó. Các điều khoản sau của máy phát không nhất thiết phải được biết đến cho đến khi các máy trước đó được tính toán.

Thậm chí tệ hơn, bạn không thể biết máy phát điện của bạn có bao giờ đạt ngoại lệ StopIteration cho đến khi bạn nhấn hay không, vì vậy không có cách nào để biết những gì sẽ có một thuật ngữ đầu tiên trong chuỗi của bạn.

Điều tốt nhất bạn có thể làm là viết một hàm reversed_iterator:

def reversed_iterator(iter): 
    return reversed(list(iter)) 

EDIT: Bạn cũng có thể, tất nhiên, thay thế đảo ngược trong này với dựa trên phiên bản lặp đi lặp lại imap của bạn, để tiết kiệm một tạo danh sách.

+13

Nói đúng, 'list (iter)' không phải là * cast *, nó là việc xây dựng một danh sách bằng cách sử dụng iterator iterator. Tôi không chắc Python có bất kỳ chức năng * cast * nào hay không, ít nhất là không theo nghĩa mà thuật ngữ đó được sử dụng trong các ngôn ngữ như C hoặc Java. int ("100") không phải là một diễn viên, và phao (100) không phải là một diễn viên - cả hai đều là các hàm tạo trả về các đối tượng. Trong C, nếu một cái gì đó được đúc, đối tượng gốc vẫn giữ nguyên. Nếu bạn đã làm một điều như vậy trong Python, bạn có thể lấy id của giá trị ban đầu, và giá trị được đúc, và chúng sẽ giống nhau. Tóm lại: trong Python, dàn diễn viên đã chết. – PaulMcG

+5

"Dàn diễn viên đã chết": tốt nhất! :) –

+2

@Paul McGuire: Tôi đồng ý với những phần quan trọng của những gì bạn nói. Một nit, mặc dù: trong C, một diễn viên * có thể * thay đổi đối tượng gốc. Nếu bạn cast 100 để float, C sẽ thay đổi nó thành 100.0f; C sẽ không chỉ đơn giản là ném mẫu bit 0x00000064 vào biến float và để nó biến thành bất kỳ giá trị nào có thể là một phao.Trong C, một diễn viên có thể chỉ cần thay đổi kiểu (thay đổi 'int *' thành 'long int *', hoặc thay đổi 'int' thành' long int') hoặc có thể thay đổi giá trị và kiểu. C++ có một số toán tử đúc, bao gồm một toán tử "tái diễn giải" mà không thay đổi giá trị nào cả. – steveha

6

reversed(list(input_generator)) có lẽ là cách dễ nhất.

Không có cách nào để nhận giá trị của máy phát theo thứ tự "đảo ngược" mà không thu thập tất cả chúng vào chuỗi đầu tiên, vì việc tạo mục thứ hai có thể dựa vào lần đầu tiên được tạo.

4

Bạn phải đi qua máy phát điện để có được mục đầu tiên để bạn cũng có thể tạo danh sách. Hãy thử

reversed(list(g)) 

nơi máy phát điện g.

reversed(tuple(g)) 

cũng sẽ hoạt động (tôi không kiểm tra xem có sự khác biệt đáng kể về hiệu suất).