2012-01-29 37 views
5

Trong Python, tôi thường tái sử dụng các biến theo cách tương tự như này:biến Tái sử dụng bằng Python

files = files[:batch_size] 

Tôi thích kỹ thuật này vì nó giúp tôi cắt vào số lượng các biến tôi cần phải theo dõi.

Không bao giờ gặp bất kỳ sự cố nào nhưng tôi tự hỏi liệu tôi có thiếu sót tiềm năng hay không, ví dụ: hiệu suất, vv

+0

Tôi không thấy câu hỏi ở đây là gì. Lựa chọn thay thế để so sánh là gì? Sử dụng biến thứ hai như 'files = XYZ; files_head = files [: batch_size] '? Tại sao nên có bất kỳ sự khác biệt? –

+0

thay thế là một cái gì đó như: new_set_of_files = files [: batch_size] – jldupont

+0

Bạn sẽ nhận thấy chính ngay lập tức: * Hey! Tôi vẫn cần giá trị cũ cho 'tệp'! *. – Droogans

Trả lời

6

Không có nhược điểm kỹ thuật để sử dụng lại tên biến. Tuy nhiên, nếu bạn sử dụng lại một biến và thay đổi "mục đích" của nó, điều đó có thể gây nhầm lẫn cho người khác đọc mã của bạn (đặc biệt là nếu họ bỏ qua việc phân công lại).

Trong ví dụ bạn đã cung cấp, mặc dù, nhận ra rằng bạn đang thực sự tạo ra một danh sách hoàn toàn mới khi bạn ghép. Cho đến khi GC thu thập bản sao cũ của danh sách đó, danh sách đó sẽ được lưu trữ trong bộ nhớ hai lần (ngoại trừ những gì bạn ghép nối). Cách khác là lặp qua danh sách đó và dừng lại khi bạn đạt đến yếu tố thứ batch_size, thay vì kết thúc danh sách hoặc thậm chí ngắn gọn hơn, del files[batch_size:].

+0

+1 Điểm tốt về cách bạn có thể tránh tạo một đối tượng mới (mặc dù có lẽ nó ít có thể đọc được?) – RoundTower

+1

@cheeken: Một giải pháp thay thế khác (có lẽ là Pythonic nhất) là tạo một trình tạo với 'itertools.islice'. –

+0

Cuộc gọi tốt, @NiklasBaumstark! Để bất cứ ai downvoted: Tôi sẽ đánh giá cao một bình luận giải thích lý do tại sao để tôi có thể sửa nó. – cheeken

5

Một số thông tin về rằng ví dụ cụ thể: Nếu bạn chỉ muốn lặp, bản đồ hoặc lọc kết quả, bạn có thể sử dụng một máy phát điện để tránh một bản sao mảng:

import itertools 
files = itertools.islice(files, batch_size) 

Đối với các trường hợp chung : Cho dù bạn gán giá trị mới cho một tên đã tồn tại hay một tên mới thì hoàn toàn không có sự khác biệt (ít nhất là từ quan điểm của trình thông dịch/VM). Cả hai phương pháp sản xuất gần như giống nhau bytecode chính xác:

Python 2.7.2 (default, Nov 21 2011, 17:25:27) 
[GCC 4.6.2] on linux2 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import dis 
>>> def func1(files): 
... files = files[:100] 
... 
>>> def func2(files): 
... new_files = files[:100] 
... 
>>> dis.dis(func1) 
    2   0 LOAD_FAST    0 (files) 
       3 LOAD_CONST    1 (100) 
       6 SLICE+2    
       7 STORE_FAST    0 (files) 
      10 LOAD_CONST    0 (None) 
      13 RETURN_VALUE   
>>> dis.dis(func2) 
    2   0 LOAD_FAST    0 (files) 
       3 LOAD_CONST    1 (100) 
       6 SLICE+2    
       7 STORE_FAST    1 (new_files) 
      10 LOAD_CONST    0 (None) 
      13 RETURN_VALUE   

Cùng có thể quan sát bằng Python 3.

Trong thực tế, func1 thậm chí có thể nhanh hơn một chút, bởi vì tên files đã được nhìn thấy trước và có thể đã có trong một số bộ nhớ cache tra cứu biến.

+0

Tôi có thể hỏi bạn sự khác biệt nào sẽ tạo ra sự khác biệt '1'? –

+0

@Rik: Tôi nghĩ đó là chỉ số của biến cục bộ bị ảnh hưởng ('0' trong trường hợp đầu tiên, vì đây là biến được truy cập đầu tiên,' 1' trong trường hợp thứ hai). Tôi không chắc chắn 100%. –

1

Thực sự sẽ không có nhiều nhược điểm để sử dụng lại các biến, ngoại trừ việc bạn cũng sẽ không trải nghiệm nhiều lợi thế. Python GC sẽ phải chạy anyway để thu thập đối tượng cũ, vì vậy không có một bộ nhớ tức thì khi bạn ghi đè biến, không giống như trong các ngôn ngữ được biên dịch tĩnh như C, ở đó việc sử dụng lại biến sẽ ngăn hoàn toàn việc cấp phát bộ nhớ đối tượng mới.

Hơn nữa, bạn thực sự có thể gây nhầm lẫn cho bất kỳ độc giả tương lai nào về mã của bạn, những người thường mong đợi các đối tượng mới có tên mới (sản phẩm phụ của các ngôn ngữ thu gom rác).

1

Nhược điểm sẽ là, rằng bạn không thể sử dụng:

file_rest = files[batch_size:] 

Về hiệu suất không có nhược điểm. Ngược lại: bạn thậm chí có thể cải thiện hiệu suất bằng cách tránh va chạm băm trong cùng một không gian tên.

Có một số SO-post liên quan đến điều này trong ngữ cảnh khác.

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