2010-01-10 11 views
5

Tôi không thực sự hiểu cách hoạt động của câu lệnh yield trong trường hợp này. Vấn đề nói rằng được đưa ra một biểu thức mà không có dấu ngoặc đơn, viết một hàm để tạo ra tất cả các biểu thức có thể hoàn toàn có dấu ngoặc đơn (FP). Này, đầu vào là '1+2+3+4' mà phải được tạo ra để 5 FP biểu:Kết quả khác nhau từ sản lượng so với lợi nhuận

  1. (1+ (2+ (3 + 4)))
  2. (1 + ((2 + 3) +4))
  3. ((1 + 2) + (3 + 4))
  4. ((1+ (2 + 3)) + 4)
  5. (((1 + 2) +3) +4)

Mã của tôi như sau.

OPS = ('+', '-', '*', '/') 
def f(expr): 
    """ 
    Generates FP exprs 
    Recursive formula: f(expr1[op]expr2) = (f(expr1) [op] f(expr2)) 
    """ 
    if expr.isdigit(): yield expr 
#  return [expr] 

# ret = [] 
    first = '' 
    i = 0 
    while i < len(expr): 
     if expr[i] not in OPS: 
      first += expr[i] 
      i += 1 
     else: 
      op = expr[i] 
      i += 1 
      second = expr[i:] 
      firstG, secondG = f(first), f(second) 
      for e in ('(' + e1 + op + e2 + ')' for e1 in firstG for e2 in secondG): 
       yield e 
#    ret.append(e) 
      first += op 
# return ret 

Nếu tôi sử dụng câu lệnh return (dòng đã nhận xét), thì mã hoạt động như mong đợi. Tuy nhiên, khi tôi thay đổi thành câu lệnh yield khi mã hiển thị, tôi chỉ nhận được 4 kết quả đầu tiên. Nếu số lượng toán hạng của biểu thức đầu vào được tăng lên, thì tất nhiên nhiều kết quả hơn sẽ bị mất. Ví dụ, đối với đầu vào '1+2+3+4+5', tôi chỉ nhận được 8 thay vì 14.

tôi cuối cùng đã tìm ra cách để làm cho công việc mã bằng cách bình luận ra các dòng firstG, secondG = f(first), f(second) và thay thế dòng

for e in ('(' + e1 + op + e2 + ')' for e1 in firstG for e2 in secondG):

bởi

for e in ('(' + e1 + op + e2 + ')' for e1 in f(first) for e2 in f(second)):

Điều đó có nghĩa một số 'thông tin' của các máy phát điện bị mất vì dòng firstG, secondG = f(first), f(second) nhưng Tôi không thể tìm ra lý do thực sự. Các bạn có thể cho tôi một số ý tưởng không?

+0

Hãy chỉnh sửa các câu hỏi và sửa chữa các vết lõm của chương trình của bạn.Sai thụt đầu dòng đặc biệt khó chịu trong các chương trình Python. – avakar

+0

Xin lỗi, đó là vì tôi không quen với cách mã hoạt động ở đây. Tôi đã sửa nó rồi. Cảm ơn – user247468

+0

đã gắn thẻ nó là bài tập về nhà, vì tôi đã có ấn tượng rằng đó là. –

Trả lời

4

Vấn đề là bạn đang lặp qua máy phát thay vì danh sách trong phiên bản lợi nhuận, cụ thể là secondG bị cạn kiệt sau một vòng lặp. Thay đổi dòng này và nó hoạt động:

firstG, secondG = f(first), list(f(second)) 

Hoặc, bạn có thể thay đổi vòng lặp của bạn:

for e in ("(%s%s%s)" % (e1, op, e2) for e1 in f(first) for e2 in f(second)): 
#        new generator object every loop ^^^^^^^^^ 

Các phiên bản không có năng suất làm việc vì bạn quay lại danh sách, có thể được lặp đi lặp lại, không giống như máy phát điện. Cũng lưu ý rằng bạn chỉ lặp lại trên firstG một lần, vì vậy nó không bị ảnh hưởng.

Hãy nhớ rằng đây:

r = [v for a in A for b in B] 

Tương đương với:

r = [] 
for a in A: 
    for b in B: 
    r.append(v) 

nào cho thấy rõ ràng hơn vòng lặp lặp đi lặp lại B.

Một ví dụ khác:

def y(): 
    yield 1 
    yield 2 
    yield 3 
def r(): 
    return [1, 2, 3] 

vy = y() 
for v in vy: 
    print v 
for v in vy: 
    print v 

print "---" 

vr = r() 
for v in vr: 
    print v 
for v in vr: 
    print v 
+0

Gotcha;) Cảm ơn, Roger! – user247468