2016-11-04 23 views
8

Các toán tử so sánh có thể được ghép trong python, do đó, ví dụ x < y < z phải cho kết quả là (x < y) and (y < z), ngoại trừ y được đảm bảo chỉ được đánh giá một lần.Làm thế nào để giải thích cây cú pháp trừu tượng của các hoạt động so sánh xích?

Cây cú pháp trừu tượng của hoạt động này trông giống như:

>>> ast.dump(ast.parse('0 < 1 < 2'), annotate_fields=0) 
'Module([Expr(Compare(Num(0), [Lt(), Lt()], [Num(1), Num(2)]))])' 

Khá in:

Module 
    Expr 
    Compare 
     Num 
     Lt 
     Lt 
     Num 
     Num 

Nhưng có vẻ như để phân tích như một cái gì đó giống như 0 < < 1 2 và tôi không chắc chắn làm thế nào để dung hòa mà với kết quả hợp lý của một cái gì đó như 0 < 1 and 1 < 2.

Làm cách nào để có thể giải thích được sự so sánh chuỗi?

Trả lời

5

Lý do đằng sau này là thực sự được đề cập trong ast docs

-- need sequences for compare to distinguish between 
-- x < 4 < 3 and (x < 4) < 3 
| Compare(expr left, cmpop* ops, expr* comparators) 

Nếu nó được đánh giá là hai riêng biệt so sánh, như thế này

Module(Expr(Compare(Compare(Num(0), [Lt()], [Num(1)]), [Lt()], [Num(2)]))]) 

Sau đó, nó thực sự so sánh boolean kết quả so sánh đầu tiên với số nguyên trong so sánh thứ hai.

Something như thế này sẽ không hoạt động

-5 < -4 < -3 

Bởi vì nó sẽ được đánh giá là

(-5 < -4) < -3 

Những đánh giá như

1 < -3 

Vì vậy, thay vào đó, nó được xử lý như một đơn biểu hiện. Một thực hiện python của hoạt động Compare sẽ giống như thế này

def Compare(left, ops, comparators): 
    if not ops[0](left, comparators[0]): 
     return False 

    for i, comparator in enumerate(comparators[1:], start=1): 
     if not ops[i](comparators[i-1], comparator): 
      return False 
    return True 
+0

tôi sẽ viết thủ tục 'Compare()' một chút khác biệt. Xem [câu trả lời của tôi] (http://stackoverflow.com/a/40431833/6394138). – Leon

3

Tôi nghĩ rằng bạn cần phải nghĩ về nó như một đường ống dẫn ngắn của những điều cần làm. ví dụ. nếu bạn zip các ops với comparators, và sau đó làm việc với chúng cùng một lúc:

result = left 
for op, comparator in zip(ops, comparators): 
    result = result and evaluate(result, op, comparator) 
    if not result: 
     break 

Rõ ràng, tôi để lại một bó để trí tưởng tượng ở đây ... ví dụ Tôi không xác định được evaluate. Tuy nhiên, đó là một điều khá khó xác định vì chúng ta không biết biểu thức so sánh trông như thế nào trong trường hợp chung.

2

Tôi muốn bổ sung cho Brendan Abel's answer với phiên bản của tôi về Compare() chức năng, mà IMHO là một chút dễ dàng hơn để hiểu:

def Compare(left, ops, comparators): 
    for x, op, y in zip([left] + comparators[:-1], ops, comparators): 
     if not op(x, y): 
      return False 
    return True 
Các vấn đề liên quan