2015-01-28 12 views
5

Một đối tượng mã được tạo bởi trình biên dịch Python chứa một bộ các hằng số được sử dụng trong các hướng dẫn (có tên là co_consts) và cũng có một tên chứa các tên (có tên là co_names).Tại sao máy ảo python có co_names thay vì chỉ sử dụng co_consts?

Tại sao có hai danh sách riêng biệt? Sẽ không đơn giản hơn khi chỉ sử dụng co_consts cho tên?

+0

Chỉ cần kiểm tra, bạn đang nói về cpython chính xác? Phiên bản nào? –

+0

@GamesBrainiac: 'co_names' được sử dụng trong cpython cả 2 và 3 và trong pypy. Bạn không chắc chắn về các triển khai khác vì tôi không sử dụng chúng. – 6502

+0

Tôi không nhớ tất cả những gì tốt, nhưng tôi khá chắc chắn nó có một cái gì đó để làm với tẩy. –

Trả lời

6

Hãy xem xét chức năng sau.

def f(x): 
    x += n 
    return x * 4 

Ở đây x là tên địa phương, giá trị của nó có thể thay đổi. 4 là hằng số. Giá trị của nó sẽ không bao giờ thay đổi. Tuy nhiên, nó vẫn là một đối tượng và nó tốt hơn để cache chúng hơn là tạo một đối tượng mới mỗi lần nó cần thiết. Cuối cùng, n là tham chiếu toàn cầu. Chuỗi "n" được lưu trữ bởi hàm để nó có thể được sử dụng làm khóa để truy xuất n từ ngữ cảnh chung của hàm.

>>> f.__code__.co_nlocals # just 1 (for x) 
1 
>>> f.__code__.co_consts 
(None, 4) 
>>> f.__code__.co_names 
('n',) 
>>> "n" in f.__globals__ and globals() is f.__globals__ 
True 

Lý do giữ tên và tách riêng biệt là nhằm mục đích nội tâm. Lý do thực sự duy nhất để hợp nhất các bộ nhớ sẽ là hiệu quả bộ nhớ, mặc dù điều này sẽ chỉ giúp bạn có được một đối tượng và một con trỏ cho mỗi hàm. Hãy xem xét các chức năng sau đây.

def g(): 
    return "s" * n 

Nếu tuple chứa consts được sáp nhập với tên tuple chứa sau đó bạn (không phải VM) sẽ không thể để cho các giá trị đã cho globals truy cập và đó là hằng số của hàm.

1

Tôi biết câu trả lời này cũng giống như 11 tháng hết hạn nhưng từ mày mò của tôi có vẻ như sau đang xảy ra

Để truy cập co_names trong bytecode, ai sử dụng LOAD_GLOBAL (index tên đồng) và điều này đẩy một tham chiếu đến co_names mong muốn vào stack, ví dụ như nó gián tiếp

Để truy cập co_consts trong bytecode, ai sử dụng LOAD_CONST (đồng consts index) và điều này đẩy giá trị thực tế được lưu trữ tại co_consts mong muốn vào stack, ví dụ trực tiếp

tôi nó 'không chắc chắn nó có bất kỳ mang trực tiếp ở một mức độ trăn, nhưng ở một cấp độ bytecode một profou của nó nd khác biệt

+0

Tất nhiên có sự khác biệt lớn khi 'LOAD_CONST' tải một hằng số trên ngăn xếp trong khi' LOAD_GLOBAL' thay vì tìm kiếm. Tuy nhiên, tên ** toàn cục ** chỉ là một đối tượng 'str' của Python và có thể được đặt trong danh sách' co_consts' thay vì 'co_names'. Điểm của câu hỏi của tôi là "tại sao lại sử dụng hai danh sách khi chỉ sử dụng' co_const' là đủ? "... Tôi không ** nói rằng không cần mã 'LOAD_GLOBAL' vì chúng ta có' LOAD_CONST' , nhưng chỉ có hai người có thể sử dụng cùng một danh sách thay vì có hai danh sách. Bất kỳ opcode nào đề cập đến một ** tên ** có thể đã sử dụng 'op_consts'. – 6502

+0

Tôi không biết lý do của nó được thiết kế như thế nào nhưng 2 người hướng dẫn đẩy các loại dữ liệu khác nhau vào ngăn xếp (giá trị so với tham chiếu) –

+0

Nếu bạn đã có cả hai tên và tên hợp nhất, bạn vẫn cần một số loại lệnh để nói VM cho dù đó là một tham chiếu hay giá trị, vì vậy đó là 2 hướng dẫn cho mỗi tải, ví dụ loadconstname, setconstnametype, và không nhanh như một cuộc gọi, cộng với nếu bạn có idjuts (ví dụ như tôi) rối tung với bytecode an toàn hơn từ VM quan điểm –

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