φυβλαςのβλογ
บล็อกของ phyblas



เปรียบเทียบระหว่างการใช้ %, ใช้ format และใช้ f-string ใน python
เขียนเมื่อ 2019/07/13 07:45
แก้ไขล่าสุด 2024/02/22 10:43
ในไพธอนเวลาที่จะสร้างหรือเรียบเรียงสายอักขระนั้นมี ๓ วิธีที่ใช้ได้คือ
- '%s%s'%(a,b) เป็นวิธีดั้งเดิม ใช้รูปแบบเหมือน printf ของภาษาซี มีใช้ในหลายภาษา
- '{}{}'.format(a,b) เป็นรูปแบบเฉพาะของภาษาไพธอน แย่การเขียนค่อนข้างเยิ่นเย้อ
- f'{a}{b}' วิธีนี้มีชื่อเรียกเฉพาะว่า f-string เป็นวิธีใหม่ที่เพิ่มเข้ามาในไพธอน 3.6 ไม่สามารถใช้ในไพธอนรุ่นเก่าได้

ทั้ง ๓ วิธีนั้นก็มีข้อดีข้อเสียต่างกันไป จะเลือกวิธีไหนก็อาจแล้วแต่คนถนัด

ในที่นี้จะขอพิจารณาเทียบในเรื่องของความเร็วดูว่าถ้าใช้ ๓ วิธีนี้ทำสิ่งเดียวกัน อย่างไหนจะดีกว่าในแง่ประสิทธิภาพ

ผลการเปรียบเทียบจะต่างกันออกไปขึ้นอยู่กับชนิดข้อมูลที่ใช้แปลง ในที่นี่ลองสอดสอบกรณีดังนี้
- เอาสายอักขระมาต่อเฉยๆ (%s, {})
- เอา int มาแปลงเป็นสายอักขระ (%d, {})
- เอา int เต็มมาแปลงเป็นสายอักขระโดยมีการเติม 0 ตามจำนวนที่กำหนด (%010d, {:010})
- เอา float มาแปลงเป็นสายอักขระโดยเขียนแบบเอ็กซ์โพเนนเชียลโดยไม่กำหนดความยาวเลขทศนิยม (%e, {:e})
- เอา float มาแปลงเป็นสายอักขระโดยเขียนแบบเอ็กซ์โพเนนเชียลโดยกำหนดความยาวเลขทศนิยม (%.10e, {:.e})
- เอา float มาแปลงเป็นสายอักขระโดยไม่กำหนดความยาวเลขทศนิยม (%f, {:f})
- เอา float มาแปลงเป็นสายอักขระโดยกำหนดความยาวเลขทศนิยม (%.10f, {:.f})
- เอา float มาแปลงเป็นสายอักขระโดยไม่ระบุชัด (%s, {})
- เอา None มาแปลงเป็นสายอักขระ
- เอา list แปลงเป็นสายอักขระ

โค้ดสำหรับทดสอบเขียนดังนี้

import time
import numpy as np
import matplotlib.pyplot as plt

tt =[]
n = 100000



t = [[],[],[]]
for j in range(5):
    a = 'กข'
    b = 'คง'
    
    t0 = time.time()
    for i in range(n):
        '%s%s'%(a, b)
    t[0].append(time.time()-t0)
    
    t0 = time.time()
    for i in range(n):
        '{}{}'.format(a, b)
    t[1].append(time.time()-t0)
    
    t0 = time.time()
    for i in range(n):
        f'{a}{b}'
    t[2].append(time.time()-t0)

tt.append(t)



t = [[],[],[]]
for j in range(5):
    a = 10
    b = 200
    
    t0 = time.time()
    for i in range(n):
        '%d%d'%(a, b)
    t[0].append(time.time()-t0)
    
    t0 = time.time()
    for i in range(n):
        '{}{}'.format(a, b)
    t[1].append(time.time()-t0)
    
    t0 = time.time()
    for i in range(n):
        f'{a}{b}'
    t[2].append(time.time()-t0)

tt.append(t)



t = [[],[],[]]
for j in range(5):
    a = 10
    b = 200
    
    t0 = time.time()
    for i in range(n):
        '%010d%010d'%(a, b)
    t[0].append(time.time()-t0)
    
    t0 = time.time()
    for i in range(n):
        '{:010}{:010}'.format(a, b)
    t[1].append(time.time()-t0)
    
    t0 = time.time()
    for i in range(n):
        f'{a:010}{b:010}'
    t[2].append(time.time()-t0)

tt.append(t)



t = [[],[],[]]
for j in range(5):
    a = 1.522555
    b = 3.125
    
    t0 = time.time()
    for i in range(n):
        '%e%e'%(a, b)
    t[0].append(time.time()-t0)
    
    t0 = time.time()
    for i in range(n):
        '{:e}{:e}'.format(a, b)
    t[1].append(time.time()-t0)
    
    t0 = time.time()
    for i in range(n):
        f'{a:e}{b:e}'
    t[2].append(time.time()-t0)

tt.append(t)



t = [[],[],[]]
for j in range(5):
    a = 1.522555
    b = 3.125
    
    t0 = time.time()
    for i in range(n):
        '%.10e%.10e'%(a, b)
    t[0].append(time.time()-t0)
    
    t0 = time.time()
    for i in range(n):
        '{:.10e}{:.10e}'.format(a, b)
    t[1].append(time.time()-t0)
    
    t0 = time.time()
    for i in range(n):
        f'{a:.10e}{b:.10e}'
    t[2].append(time.time()-t0)

tt.append(t)



t = [[],[],[]]
for j in range(5):
    a = 1.522555
    b = 3.125
    
    t0 = time.time()
    for i in range(n):
        '%f%f'%(a, b)
    t[0].append(time.time()-t0)
    
    t0 = time.time()
    for i in range(n):
        '{:f}{:f}'.format(a, b)
    t[1].append(time.time()-t0)
    
    t0 = time.time()
    for i in range(n):
        f'{a:f}{b:f}'
    t[2].append(time.time()-t0)

tt.append(t)



t = [[],[],[]]
for j in range(5):
    a = 1.522555
    b = 3.125
    
    t0 = time.time()
    for i in range(n):
        '%.10f%.10f'%(a, b)
    t[0].append(time.time()-t0)
    
    t0 = time.time()
    for i in range(n):
        '{:.10f}{:.10f}'.format(a, b)
    t[1].append(time.time()-t0)
    
    t0 = time.time()
    for i in range(n):
        f'{a:.10f}{b:.10f}'
    t[2].append(time.time()-t0)

tt.append(t)



t = [[],[],[]]
for j in range(5):
    a = 1.522555
    b = 3.125
    
    t0 = time.time()
    for i in range(n):
        '%s%s'%(a, b)
    t[0].append(time.time()-t0)
    
    t0 = time.time()
    for i in range(n):
        '{}{}'.format(a, b)
    t[1].append(time.time()-t0)
    
    t0 = time.time()
    for i in range(n):
        f'{a}{b}'
    t[2].append(time.time()-t0)

tt.append(t)



t = [[],[],[]]
for j in range(5):
    a = None
    b = None
    
    t0 = time.time()
    for i in range(n):
        '%s%s'%(a, b)
    t[0].append(time.time()-t0)
    
    t0 = time.time()
    for i in range(n):
        '{}{}'.format(a, b)
    t[1].append(time.time()-t0)
    
    t0 = time.time()
    for i in range(n):
        f'{a}{b}'
    t[2].append(time.time()-t0)

tt.append(t)



t = [[],[],[]]
for j in range(5):
    a = list(range(1,6))
    b = list(range(11,16))
    
    t0 = time.time()
    for i in range(n):
        '%s%s'%(a, b)
    t[0].append(time.time()-t0)
    
    t0 = time.time()
    for i in range(n):
        '{}{}'.format(a, b)
    t[1].append(time.time()-t0)
    
    t0 = time.time()
    for i in range(n):
        f'{a}{b}'
    t[2].append(time.time()-t0)

tt.append(t)



tt = np.array(tt)/n*1e6
plt.figure(figsize=[6.5,6])

plt.subplot(211)
for i,c in enumerate(['#ffaaaa','#aaffaa','#aaaaff']):
    plt.bar(np.arange(10)+(i-1)/4.,tt[:,i].mean(1),width=0.25,yerr=tt[:,i].std(1),capsize=4,color=c,ecolor='#332255')

plt.legend(['ใช้ %','ใช้ format','ใช้ f-string'],prop={'family':'Tahoma'})
plt.ylabel('เวลา (ไมโครวินาที)',family='Tahoma')
plt.xticks([])

plt.subplot(212)
for i,c in enumerate(['#ffaaaa','#aaffaa','#aaaaff']):
    plt.bar(np.arange(10)+(i-1)/4.,(tt[:,i]/tt[:,0]).mean(1),width=0.25,yerr=(tt[:,i]/tt[:,0]).std(1),capsize=5,color=c,ecolor='#332211')

plt.ylabel('จำนวนเท่าของแบบใช้ %',family='Tahoma')
plt.xticks(np.arange(10),['s','d','010d','e','.10e','f','.10f','f>>s','None','list'])

plt.tight_layout()
plt.show()


ผลที่ได้



สรุปได้ว่าโดยรวมแล้ววิธีการดั้งเดิมอย่างการใช้ % นั้นเร็วที่สุด ส่วน .format นั้นยังไงก็ช้ากว่ากว่า % ทุกกรณี

ส่วน f-string นั้นจะเร็วมากในกรณีที่ป้อนสายอักขระโดยตรง แต่พอแปลง int กลับจะเร็วพอๆกันกับการใช้ %

แต่เมื่อมีการกำหนดให้เติมเลข 0 แบบนี้ f-string จะทำงานช้าลงมาก ช้ายิ่งกว่า .format เสียอีก

สำหรับการแปลง float นั้น f-string ช้าสุดในทุกกรณี

ดังนั้นหากคำนึงถึงความเร็ว การใช้ % ยังเร็วที่สุด

แต่ f-string อาจเหมาะเวลาที่ต้องการป้อนข้อมูลที่เดิมทีเป็นสายอักขระ เพราะเขียนได้กระชับสั้นที่สุดและยังเร็วที่สุด

อีกทั้ง อันนี้แค่เทียบในแง่ความเร็วเป็นหลัก แต่หากพูดถึงความสามารถ f-string สามารถทำอะไรบางอย่างที่ไม่สามารถใช้ % ทำได้ เช่น แทรกจุลภาคลงใประหว่างตัวเลข
a = 123456789
print(f'{a:,}') # ได้ 123,456,789

ยังไงก็อาจแยกใช้ตามความเหมาะสม ขึ้นอยู่กับว่าต้องการใช้ทำอะไร


-----------------------------------------

囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧

ดูสถิติของหน้านี้

หมวดหมู่

-- คอมพิวเตอร์ >> เขียนโปรแกรม >> python

ไม่อนุญาตให้นำเนื้อหาของบทความไปลงที่อื่นโดยไม่ได้ขออนุญาตโดยเด็ดขาด หากต้องการนำบางส่วนไปลงสามารถทำได้โดยต้องไม่ใช่การก๊อปแปะแต่ให้เปลี่ยนคำพูดเป็นของตัวเอง หรือไม่ก็เขียนในลักษณะการยกข้อความอ้างอิง และไม่ว่ากรณีไหนก็ตาม ต้องให้เครดิตพร้อมใส่ลิงก์ของทุกบทความที่มีการใช้เนื้อหาเสมอ

สารบัญ

รวมคำแปลวลีเด็ดจากญี่ปุ่น
มอดูลต่างๆ
-- numpy
-- matplotlib

-- pandas
-- manim
-- opencv
-- pyqt
-- pytorch
การเรียนรู้ของเครื่อง
-- โครงข่าย
     ประสาทเทียม
ภาษา javascript
ภาษา mongol
ภาษาศาสตร์
maya
ความน่าจะเป็น
บันทึกในญี่ปุ่น
บันทึกในจีน
-- บันทึกในปักกิ่ง
-- บันทึกในฮ่องกง
-- บันทึกในมาเก๊า
บันทึกในไต้หวัน
บันทึกในยุโรปเหนือ
บันทึกในประเทศอื่นๆ
qiita
บทความอื่นๆ

บทความแบ่งตามหมวด



ติดตามอัปเดตของบล็อกได้ที่แฟนเพจ

  ค้นหาบทความ

  บทความแนะนำ

ตัวอักษรกรีกและเปรียบเทียบการใช้งานในภาษากรีกโบราณและกรีกสมัยใหม่
ที่มาของอักษรไทยและความเกี่ยวพันกับอักษรอื่นๆในตระกูลอักษรพราหมี
การสร้างแบบจำลองสามมิติเป็นไฟล์ .obj วิธีการอย่างง่ายที่ไม่ว่าใครก็ลองทำได้ทันที
รวมรายชื่อนักร้องเพลงกวางตุ้ง
ภาษาจีนแบ่งเป็นสำเนียงอะไรบ้าง มีความแตกต่างกันมากแค่ไหน
ทำความเข้าใจระบอบประชาธิปไตยจากประวัติศาสตร์ความเป็นมา
เรียนรู้วิธีการใช้ regular expression (regex)
การใช้ unix shell เบื้องต้น ใน linux และ mac
g ในภาษาญี่ปุ่นออกเสียง "ก" หรือ "ง" กันแน่
ทำความรู้จักกับปัญญาประดิษฐ์และการเรียนรู้ของเครื่อง
ค้นพบระบบดาวเคราะห์ ๘ ดวง เบื้องหลังความสำเร็จคือปัญญาประดิษฐ์ (AI)
หอดูดาวโบราณปักกิ่ง ตอนที่ ๑: แท่นสังเกตการณ์และสวนดอกไม้
พิพิธภัณฑ์สถาปัตยกรรมโบราณปักกิ่ง
เที่ยวเมืองตานตง ล่องเรือในน่านน้ำเกาหลีเหนือ
ตระเวนเที่ยวตามรอยฉากของอนิเมะในญี่ปุ่น
เที่ยวชมหอดูดาวที่ฐานสังเกตการณ์ซิงหลง
ทำไมจึงไม่ควรเขียนวรรณยุกต์เวลาทับศัพท์ภาษาต่างประเทศ

บทความแต่ละเดือน

2024年

1月 2月 3月 4月
5月 6月 7月 8月
9月 10月 11月 12月

2023年

1月 2月 3月 4月
5月 6月 7月 8月
9月 10月 11月 12月

2022年

1月 2月 3月 4月
5月 6月 7月 8月
9月 10月 11月 12月

2021年

1月 2月 3月 4月
5月 6月 7月 8月
9月 10月 11月 12月

2020年

1月 2月 3月 4月
5月 6月 7月 8月
9月 10月 11月 12月

ค้นบทความเก่ากว่านั้น

ไทย

日本語

中文