*
là toán tử "splat": Nó nhận một danh sách làm đầu vào và mở rộng nó thành các đối số vị trí thực tế trong lệnh gọi hàm.
Vì vậy, nếu uniqueCrossTabs
là [ [ 1, 2 ], [ 3, 4 ] ]
, thì itertools.chain(*uniqueCrossTabs)
cũng giống như nóiitertools.chain([ 1, 2 ], [ 3, 4 ])
Điều này rõ ràng là khác với việc chỉ đi qua uniqueCrossTabs
. Trong trường hợp của bạn, bạn có một danh sách các danh sách mà bạn muốn san bằng; những gì itertools.chain()
thực hiện là trả về một trình lặp qua việc nối tất cả các đối số vị trí mà bạn truyền cho nó, trong đó mỗi đối số vị trí có thể lặp lại theo đúng nghĩa của nó.
Nói cách khác, bạn muốn chuyển từng danh sách vào uniqueCrossTabs
làm đối số chain()
, điều này sẽ chuỗi chúng lại với nhau, nhưng bạn không có danh sách trong các biến riêng biệt, vì vậy bạn sử dụng *
toán tử để mở rộng danh sách thành một số đối số danh sách.
Như Jochen Ritzel đã chỉ ra trong các nhận xét, chain.from_iterable()
hoạt động này phù hợp hơn với hoạt động này, vì nó giả định bắt đầu có một lần lặp lại các mục lặp. Sau đó, mã của bạn trở nên đơn giản:
uniqueCrossTabs = list(itertools.chain.from_iterable(uniqueCrossTabs))