2016-11-17 15 views
14

Vì vậy, đó là một điều CPython, không hoàn toàn chắc chắn rằng nó có cùng hành vi với các triển khai khác.'{0}'. Định dạng() nhanh hơn định dạng str() và '{}'.() Sử dụng IPython% timeit và sử dụng Python thuần

Nhưng '{0}'.format() nhanh hơn str()'{}'.format(). Tôi đang đăng kết quả từ Python 3.5.2, nhưng, tôi đã thử nó với Python 2.7.12 và xu hướng giống nhau.

%timeit q=['{0}'.format(i) for i in range(100, 100000, 100)] 
%timeit q=[str(i) for i in range(100, 100000, 100)] 
%timeit q=['{}'.format(i) for i in range(100, 100000, 100)] 

1000 loops, best of 3: 231 µs per loop 
1000 loops, best of 3: 298 µs per loop 
1000 loops, best of 3: 434 µs per loop 

Từ docs trên object.__str__(self)

gọi bởi str(object) và được xây dựng trong các chức năng format()print() để tính các đại diện chuỗi “không chính thức” hay độc đáo in của một đối tượng.

Vì vậy, str()format() gọi cùng phương thức object.__str__(self), nhưng sự khác biệt về tốc độ đến từ đâu?

CẬP NHẬT như @StefanPochmann và @Leon ghi nhận trong nhận xét, họ nhận được kết quả khác nhau. Tôi cố gắng để chạy nó với python -m timeit "..." và, họ là đúng, vì kết quả là:

$ python3 -m timeit "['{0}'.format(i) for i in range(100, 100000, 100)]" 
1000 loops, best of 3: 441 usec per loop 

$ python3 -m timeit "[str(i) for i in range(100, 100000, 100)]" 
1000 loops, best of 3: 297 usec per loop 

$ python3 -m timeit "['{}'.format(i) for i in range(100, 100000, 100)]" 
1000 loops, best of 3: 420 usec per loop 

Vì vậy, có vẻ như IPython đang làm một cái gì đó kỳ lạ ...

MỚI HỎI: cách gì được ưa thích thế nào để chuyển đổi một đối tượng sang tốc độ str?

+0

Để nhanh hơn, bạn cũng có thể thử sử dụng 'i .__ str __()' trực tiếp. Mặc dù 'str' thực sự là cách thích hợp. Nó không đủ nhanh cho bạn sao? –

Trả lời

7

Thời gian IPython chỉ tắt vì một số lý do (mặc dù khi được kiểm tra bằng chuỗi định dạng dài hơn trong các ô khác nhau, nó hoạt động tốt hơn tốt hơn một chút). Có thể thực hiện trong cùng một tế bào là không đúng, không thực sự biết.

Dù bằng cách nào, "{}" nhanh hơn một chút so với "{pos}" nhanh hơn "{name}" trong khi tất cả chúng đều chậm hơn str.

str(val) là cách nhanh nhất để biến đổi đối tượng thành str; nó gọi trực tiếp các đối tượng '__str__, nếu có, và trả về chuỗi kết quả. Những người khác, như format, (hoặc str.format) bao gồm chi phí bổ sung do một cuộc gọi chức năng bổ sung (đến số format chính nó); xử lý bất kỳ đối số nào, phân tích cú pháp chuỗi định dạng và rồi gọi số __str__ trong số args của chúng.

Đối với phương thức str.format"{}" sử dụng đánh số tự động; từ một phần nhỏ trong docs on the format syntax:

Thay đổi trong phiên bản 3.1: Các specifiers luận vị trí có thể được bỏ qua, vì vậy '{} {}' tương đương với '{0} {1}'.

có nghĩa là, nếu bạn cung cấp một chuỗi có dạng:

"{}{}{}".format(1, 2, 3) 

CPython ngay biết rằng đây là tương đương với:

"{0}{1}{2}".format(1, 2, 3) 

Với một chuỗi định dạng có chứa số chỉ vị trí; CPython không thể giả định một số lượng ngày càng chặt chẽ (bắt đầu từ 0) và phải phân tích tất cả các khung duy nhất để làm cho nó đúng, làm chậm điều xuống một chút trong quá trình này:

"{1}{2}{0}".format(1, 2, 3) 

Đó là lý do tại sao nó cũng không phải là phép trộn hai với nhau:

"{1}{}{2}".format(1, 2, 3) 

bạn sẽ nhận được một đẹp ValueError trở lại khi bạn cố gắng để làm như vậy:

ValueError: cannot switch from automatic field numbering to manual field specification 

nó cũng lấy những số positionals with PySequence_GetItem mà tôi khá chắc chắn là nhanh, ít nhất, so với PyObject_GetItem [xem tiếp theo].

Đối với giá trị "{name}", CPython luôn có thêm công việc cần làm do thực tế chúng tôi đang xử lý đối số từ khóa thay vì đối số từ khóa; điều này bao gồm những thứ như xây dựng từ điển cho các cuộc gọi và tạo ra cách thêm LOAD hướng dẫn mã byte để tải key s và các giá trị. Các hình thức từ khóa của chức năng gọi điện thoại luôn luôn giới thiệu một số chi phí. Ngoài ra, có vẻ như grabbing thực sự sử dụng PyObject_GetItem mà phải gánh chịu thêm một số chi phí do tính chất chung của nó.

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