2013-04-19 23 views
7

Trong trang chủ matplotlib, có một liên kết đến hướng dẫn của Nicolas Rougier. Trong phần của hướng dẫn mang tên "quỷ là trong các chi tiết", kịch bản:Chỉ định đối số từ điển với dict() hoặc niềng răng quan trọng trong set_bbox

http://www.loria.fr/~rougier/teaching/matplotlib/scripts/exercice_10.py

tạo ra con số hiển thị trên trang web. Dòng 48 của kịch bản là:

label.set_bbox(dict(facecolor='white', edgecolor='None', alpha=0.65)) 

Nếu chúng ta thay thế dòng này bằng cách:

label.set_bbox({"facecolor": "white", "edgecolor": "None","alpha":0.65}) 

sau đó yêu cầu edgecolor không đưa vào tính toán. Tôi đã nghĩ rằng hai câu trên là tương đương. Tôi đã hỏi tác giả của hướng dẫn này, Nicolas Rougier, về điều này và ông cũng ngạc nhiên. Đây có phải là lỗi của Matplotlib không?

+0

Điều này thực sự lạ ... Tôi thực sự có thể tái tạo điều này ... – mgilson

+0

Ma quỷ thực sự là chi tiết ... – BioGeek

+0

Tôi nghi ngờ điều này có liên quan đến 'alpha'. Việc xử lý màu rgb vs rgba là khó tính. Bạn đang sử dụng phiên bản mpl nào? – tacaswell

Trả lời

4

Bạn có thể dễ dàng xác định nếu hai dicts là tương đương:

dict(facecolor='white', edgecolor='None', alpha=0.65) == \ 
    {"facecolor": "white", "edgecolor": "None", "alpha":0.65} 

Đây là True.

Tuy nhiên, nếu bạn nhập các chữ cái này vào trình thông dịch Python, từ điển kết quả repr có các giá trị theo thứ tự khác nhau.

{'alpha': 0.65000000000000002, 'facecolor': 'white', 'edgecolor': 'None'} 
{'edgecolor': 'None', 'facecolor': 'white', 'alpha': 0.65000000000000002} 

Điều này có thể khác nhau dựa trên phiên bản Python bạn sử dụng và tôi tin rằng trong phiên bản Python mới hơn, nó thay đổi từ khi chạy đến phiên dịch; việc nhân giống băm được phân ngẫu nhiên để ngăn các từ điển không được xây dựng với hiệu suất kém. Đầu ra ở trên là từ Python 2.6.6 (Win32).

Python dict s không có thứ tự, theo đó chúng tôi có nghĩa là bạn không thể dựa vào thứ tự. Tuy nhiên, khi lặp qua từ điển, các phần tử phải xuất hiện theo số một số đơn đặt hàng. Lệnh này bị ảnh hưởng bởi thứ tự các mục được chèn vào, và mặc dù nó không hiển nhiên, chúng được chèn vào hai thứ tự khác nhau trong hai từ điển sau: hàm dựng dict() nhận từ điển từ khóa, sau đó chèn vào từ điển dict, do đó, có hiệu lực các yếu tố của dict đầu tiên được chèn hai lần! Đầu tiên theo thứ tự bạn chỉ định chúng, sau đó theo thứ tự bất kỳ mà chúng đã kết thúc trong từ điển được xây dựng trong bước đó.

Giả thuyết: Có gì đó trong matplotlib (hoặc phiên bản Python bạn đang sử dụng) quan tâm đến thứ tự từ điển theo thứ tự xuất hiện. Thực tế, vì từ khóa thứ hai có khóa edgecolor đầu tiên, có lẽ nó bỏ qua mục đầu tiên giá trị hoặc có thể một trong các giá trị sau có tác dụng phụ khiến nó ghi đè edgecolor (ví dụ: có thể facecolor cũng đặt edgecolor để đảm bảo không có khoảng trống giữa các khuôn mặt). Điều này có thể được gọi là một lỗi hợp lý vì hành vi có thể khác nhau dựa trên thứ tự mà từ khóa xảy ra để xuất hiện trong từ điển.

+1

Đây là kết luận mà tôi cũng đã tham gia . My My, matplotlib dựa vào lệnh dict. Điều đó thật bất ngờ. Tôi nhận được cùng một thứ tự như bạn cho cả hai constructor dict và literal bằng cách sử dụng python2.7.3 trên OS-X. Tôi không chắc chắn khi họ bẻ khóa ngẫu nhiên băm theo mặc định ... – mgilson

+0

Làm một ít nghiên cứu hơn, có vẻ như ngẫu nhiên băm được kích hoạt theo mặc định trong Python 3.3. – kindall

+0

Có vẻ như 'artist.update' lặp lại từ điển của bạn và gọi các hàm theo thứ tự các mục được truy xuất, xem https://github.com/matplotlib/matplotlib/blob/master/lib/matplotlib/artist.py#L667. Vấn đề sau đó phải nằm trong sự kết hợp của 'set_edgecolor',' set_facecolor' và 'set_alpha'. –

0

Nếu bạn thay thế phù hợp với:

label.set_bbox({"facecolor": "white", "alpha":0.65, "edgecolor": "None",}) 

nó hoạt động một cách chính xác.

Tôi nghĩ rằng đây là lỗi trong set_alpha hoặc có thể trong trình kết xuất đồ họa.

Là một công việc xung quanh bạn có thể thiết lập độ rộng dòng 0:

label.set_bbox({"facecolor": "white", "edgecolor": "None","alpha":0.65, 'lw':0}) 

đó sẽ đảm bảo rằng dòng sẽ không được rút ra, không phụ thuộc vào những gì màu sắc/alpha là.

Cách mã hoạt động, bạn vượt qua set_bbox một dict sau đó được lưu trữ trong _bbox. Vào lúc bốc thăm, nếu _bbox không phải là None (và không có _bbox_patch) _bbox được chuyển cho patches.bbox_artist mà là một chức năng (dán nhãn là một chức năng gỡ lỗi trong docstring!) Trong đó sử dụng các dict để tạo ra một đối tượng Rectangle khi đang bay (mà không được trả lại!). Một nơi nào đó trong các set_*draw trong hình chữ nhật là nơi có lỗi.

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