Gần đây, tôi đã viết một hàm để tạo ra các chuỗi nhất định với các ràng buộc không đáng kể. Vấn đề đến với một giải pháp đệ quy tự nhiên. Bây giờ nó xảy ra rằng, ngay cả đối với đầu vào tương đối nhỏ, các chuỗi là vài nghìn, vì vậy tôi muốn sử dụng thuật toán của mình như một trình tạo thay vì sử dụng nó để điền vào một danh sách với tất cả các chuỗi.
Đây là một ví dụ. Giả sử chúng ta muốn tính toán tất cả các hoán vị của một chuỗi bằng một hàm đệ quy. Thuật toán ngây thơ sau đây nhận thêm một đối số 'bộ nhớ' và thêm một hoán vị vào nó bất cứ khi nào nó tìm thấy:
def getPermutations(string, storage, prefix=""):
if len(string) == 1:
storage.append(prefix + string) # <-----
else:
for i in range(len(string)):
getPermutations(string[:i]+string[i+1:], storage, prefix+string[i])
storage = []
getPermutations("abcd", storage)
for permutation in storage: print permutation
(Xin đừng quan tâm đến sự kém hiệu quả, đây chỉ là một ví dụ.)
Bây giờ tôi muốn biến hàm của mình thành một trình tạo, tức là để mang lại một hoán vị thay vì thêm nó vào danh sách lưu trữ:
def getPermutations(string, prefix=""):
if len(string) == 1:
yield prefix + string # <-----
else:
for i in range(len(string)):
getPermutations(string[:i]+string[i+1:], prefix+string[i])
for permutation in getPermutations("abcd"):
print permutation
Mã này không hoạt động (chức năng hoạt động giống như một trình tạo trống).
Tui bỏ lỡ điều gì vậy? Có cách nào để biến thuật toán đệ quy trên thành một trình tạo mà không cần thay thế nó bằng một thuật toán lặp không?
yield from getPermutations(string[:i] + string[i+1:])
, điều này hiệu quả hơn theo nhiều cách!