2010-09-02 9 views
10

Tôi đã viết một đoạn mã nhỏ mà tính độ dài đường đi của một nút cho trước (ví dụ như khoảng cách của nó tới nút gốc):Python: Hành vi kỳ lạ của hàm đệ quy với đối số từ khóa

def node_depth(node, depth=0, colored_nodes=set()): 
    """ 
    Return the length of the path in the parse tree from C{node}'s position 
    up to the root node. Effectively tests if C{node} is inside a circle 
    and, if so, returns -1. 

    """ 
    if node.mother is None: 
     return depth 
    mother = node.mother 
    if mother.id in colored_nodes: 
     return -1 
    colored_nodes.add(node.id) 
    return node_depth(mother, depth + 1, colored_nodes) 

Bây giờ có một điều kỳ lạ xảy ra với hàm đó (ít nhất nó lạ với tôi): Gọi node_depth lần đầu tiên trả về giá trị đúng. Tuy nhiên, gọi nó lần thứ hai với cùng một nút trả về -1. Các colored_nodes thiết rỗng trong cuộc gọi đầu tiên, nhưng có chứa tất cả các node-ID trong cuộc gọi thứ hai đã được thêm vào trong một đầu tiên:

print node_depth(node) # --> 9 
# initially colored nodes --> set([]) 
print node_depth(node) # --> -1 
# initially colored nodes --> set([1, 2, 3, 38, 39, 21, 22, 23, 24]) 

print node_depth(node, colored_nodes=set()) # --> 9 
print node_depth(node, colored_nodes=set()) # --> 9 

Tôi có thiếu một số điều Python cụ thể ở đây và điều này thực sự là phải theo cách đó?

Cảm ơn trước,

Jena

+0

Điều tương tự cũng làm tôi khó chịu và tôi đã tìm thấy câu hỏi của bạn và một giải thích chi tiết khác về SO. http://stackoverflow.com/questions/1132941/least-astonishment-in-python-which-scope-is-the-mutable-default-argument-in – Yefei

Trả lời

15

"Giá trị mặc định" cho một tham số hàm trong Python được khởi tạo vào thời điểm khai báo hàm, không phải mỗi khi hàm được gọi. Bạn hiếm khi muốn thay đổi giá trị mặc định của một tham số và do đó thường là ý tưởng hay khi sử dụng thứ gì đó bất biến cho giá trị mặc định.

Trong trường hợp của bạn, bạn có thể muốn làm một cái gì đó như thế này:

def node_depth(node, depth=0, colored_nodes=None): 
    ... 
    if colored_nodes is None: colored_nodes = set() 
+0

Đó là điều tốt để biết - cảm ơn rất nhiều. (Và vì ai đó đã hỏi: Không, đây không phải là bài tập về nhà.) – jena

+0

Cảm ơn vì điều này! Mẹo hay. @ jena: cảm ơn vì đã hỏi điều này, quá. :) – hayavuk

6

Đây là, bởi vì trong Python, các giá trị tham số mặc định là không đánh giá mỗi khi hàm được gọi, nhưng chỉ một lần ở thời gian định nghĩa hàm. Vì vậy, có hiệu quả, bạn đang gọi chức năng với một điền sẵn colored_nodes đặt trên tất cả nhưng cuộc gọi đầu tiên sau khi định nghĩa.

+0

Cảm ơn, tôi đã học được điều gì đó. Bây giờ ngày của tôi đã hoàn tất. – wheaties