2017-07-07 26 views
5

Tôi có câu hỏi về phạm vi trong hàm python. Tôi đã đưa vào một ví dụ minh họa vấn đề tôi đang gặp phải.Phạm vi chức năng Python

fun0 xác định lại mục nhập đầu tiên trong danh sách có thể thay đổi c. Thay đổi này được phản ánh bên ngoài fun0, ngay cả khi tôi không trả lại bất kỳ giá trị nào từ fun0.

fun1 định nghĩa lại biến c hoàn toàn, nhưng sự thay đổi là không được phản ánh bên ngoài của fun1. Tương tự, fun2 xác định lại c và thay đổi không được phản ánh bên ngoài fun2.

Câu hỏi của tôi là, tại sao không fun0 sửa đổi val3 trong chính chức năng, trong khi fun1fun2 không sửa đổi val4val7, tương ứng?

def fun0(a, b, c): 
    c[0] = a[0] + b[0] 
    return 

def fun1(a, b, c): 
    c = a[0] + b[0] 
    return 

def fun2(a, b, c): 
    c = a + b 
    return 

def main(): 
    val1 = ['one'] 
    val2 = ['two'] 
    val3 = [''] 
    fun0(val1, val2, val3) 
    print val3 

    val4 = [] 
    fun1(val1, val2, val4) 
    print val4 

    val5 = 1 
    val6 = 1 
    val7 = 0 
    fun2(val5, val6, val7) 
    print val7 
    return 

if __name__=='__main__': 
    main() 
+4

Danh sách có thể thay đổi, bạn có thể sửa đổi các yếu tố của chúng và ảnh hưởng đến tất cả mọi người có tham chiếu. Khi bạn gán lại nó, bạn đang tạo một tham chiếu mới. – byxor

+0

Thật kỳ lạ khi tôi tham khảo các đoạn mã khác như "mọi người". Có lẽ mã nhân bản là cách hiểu của tôi tốt hơn. – byxor

Trả lời

1

Câu hỏi của tôi là, tại sao fun0 sửa đổi val3 trong hàm chính, trong khi fun1 và fun2 không sửa đổi val4 và val7, tương ứng?

Điều này là do cách Python chuyển đối số.

Khi bạn chuyển đối số cho hàm, Python chuyển chúng bằng lệnh gán. Điều này có nghĩa là nó liên kết tham chiếu đối số với tên tham số. Đó là cách duy nhất các tên tham số và đối số có liên quan. Trong ví dụ đầu tiên của bạn, bạn chỉ cần chuyển một tham chiếu đến val3 và vì cả hai val3c đều đề cập đến cùng một đối tượng danh sách, các thay đổi được phản ánh trên cả hai tên.

Tuy nhiên, khi bạn gán lại c bên trong các chức năng của mình, bạn đã thay thế tham chiếu thành danh sách c đang giữ và gán lại c một tham chiếu mới.

+0

Theo phạm vi, các hàm trong ví dụ của tôi có quyền truy cập vào các tham số đầu vào, biến cục bộ và toàn cầu. Nếu một đối số là có thể thay đổi, thì một hàm có thể thay đổi giá trị của nó bằng tham chiếu và ngược lại, những thay đổi đó xảy ra bên ngoài phạm vi của hàm (sửa tôi nếu tôi sai hoặc không chính xác). – shoe02

+0

Có, mọi thứ bạn nói là khá chính xác. Bình luận duy nhất tôi sẽ làm là các biến không phải là toàn cầu theo mặc định. [Xem ở đây để biết thêm chi tiết] (https://stackoverflow.com/questions/10588317/python-function-global-variables). –

+0

Ok, vì vậy khi tôi đang xem xét mã, tôi cũng sẽ ghi nhớ nếu tham số đầu vào có thể thay đổi hay không. Cảm ơn sự giúp đỡ của bạn! – shoe02

2

Nó phải làm với cách danh sách và biến được lưu trữ. Bạn có thể sửa đổi một danh sách trong một hàm vì chúng là các đối tượng có thể thay đổi được. Tuy nhiên, nếu bạn thực hiện c = a[0] + b[0], bạn sẽ tạo một biến cục bộ trong phạm vi fun1fun2, nằm trong phạm vi chức năng.

0

Cind Shindell là gì hoàn toàn chính xác. Hơn nữa, nếu bạn DID muốn lưu các giá trị cập nhật, đây là cách bạn có thể thay đổi mã của bạn để làm điều đó, tôi đã thay đổi các báo cáo in kể từ khi tôi thử nghiệm điều này trong python 3.6.1. Câu hỏi hay.

def main(): 
    val1 = ['one'] 
    val2 = ['two'] 
    val3 = [''] 
    fun0(val1, val2, val3) 
    print(val3) 

    val4 = [] 
    val4 = fun1(val1, val2, val4) 
    print(val4) 

    val5 = 1 
    val6 = 1 
    val7 = 0 
    val7 = fun2(val5, val6, val7) 
    print(val7) 
    return 
1

Về mặt kỹ thuật khi bạn chuyển đối số cho hàm bạn đang chuyển một bản sao chứ không phải bản gốc. Bây giờ có một sự khác biệt giữa việc chuyển danh sách và biến đi qua. Một danh sách giữ một tham chiếu đến đối tượng khác trong khi một biến chứa một giá trị.Do đó khi chuyển một danh sách ngay cả khi nó được sao chép nó vẫn đang tham chiếu cùng một đối tượng và có thể được thay đổi trong hàm, nhưng khi truyền một biến mà đối tượng đã sao chép không liên quan gì đến bản gốc. Hy vọng điều này có ý nghĩa.

0

như đã nói trước đây, danh sách có thể thay đổi. Nếu bạn vượt qua một danh sách và sửa đổi nó, bạn làm điều đó ở khắp mọi nơi. Điều này áp dụng cho tất cả các danh sách trong fun0.

trong fun2 bạn không vượt qua danh sách và do đó c được tính trong vòng fun2, nhưng không có ở bên ngoài.

Tôi không chắc chắn về fun1, nhưng tôi nghĩ bạn đang ghi đè c bằng biến mới không có sẵn ở bên ngoài như trong fun2.

Các vấn đề liên quan