สตริง Python

Python มีคลาสสตริงในตัวชื่อ "str" พร้อมด้วยฟีเจอร์ที่เป็นประโยชน์มากมาย (มีโมดูลที่เก่ากว่าชื่อ "string" ซึ่งคุณไม่ควรใช้) ลิเทอรัลสตริงสามารถอยู่ในเครื่องหมายคำพูดแบบคู่หรือแบบเดี่ยวก็ได้ แม้ว่าเครื่องหมายคำพูดเดี่ยวจะนิยมใช้มากกว่า การหลีกแบ็กสแลชทำงานตามปกติทั้งในลิเทอรัลแบบอัญประกาศเดี่ยวและคู่ เช่น \n \" \" ลิเทอรัลของสตริงที่มีเครื่องหมายคำพูดคู่สามารถมีเครื่องหมายคำพูดเดี่ยวได้โดยไม่ต้องยุ่งยาก (เช่น "ฉันไม่ได้ทำ") และสตริงเครื่องหมายคำพูดเดี่ยวก็มีเครื่องหมายคำพูดแบบคู่ด้วยเช่นกัน ลิเทอรัลของสตริงอาจครอบคลุมหลายบรรทัด แต่จะต้องมีเครื่องหมายแบ็กสแลช \ ต่อท้ายแต่ละบรรทัด เพื่อหลีกบรรทัดใหม่ ลิเทอรัลสตริงภายในเครื่องหมายคำพูดสามชุด """ หรือ ''' สามารถครอบคลุมข้อความได้หลายบรรทัด

สตริง Python จะ "เปลี่ยนแปลงไม่ได้" ซึ่งหมายความว่าหลังจากสร้างสตริงแล้วจะเปลี่ยนแปลงไม่ได้ (สตริง Java ก็ใช้รูปแบบที่เปลี่ยนแปลงไม่ได้นี้ด้วย) เนื่องจากสตริงจะเปลี่ยนแปลงไม่ได้ เราจึงสร้างสตริง *ใหม่* เมื่อเราแสดงค่าที่คำนวณไว้ ตัวอย่างเช่น นิพจน์ ('hello' + 'there') จะใช้ 2 สตริงอย่าง 'hello' และ 'there' และสร้างสตริงใหม่คือ 'hellothere'

อักขระในสตริงสามารถเข้าถึงได้โดยใช้ไวยากรณ์มาตรฐาน [ ] และเช่นเดียวกับ Java และ C++ นั้น Python จะใช้การจัดทำดัชนีแบบศูนย์ ดังนั้นหาก s คือ "hello" s[1] คือ "e" หากดัชนีอยู่นอกขอบเขตของสตริง Python จะเพิ่มข้อผิดพลาด รูปแบบ Python (ต่างจาก Perl) คือการหยุดหากบอกไม่ได้ว่าต้องทำอะไร แต่จะใช้เพียงค่าเริ่มต้น ไวยากรณ์ "slice" ที่ใช้ง่าย (ด้านล่าง) สามารถใช้ในการดึงสตริงย่อยจากสตริงได้ด้วย ฟังก์ชัน len(สตริง) จะแสดงผลความยาวของสตริง ไวยากรณ์ [ ] และฟังก์ชัน len() จะใช้ได้กับลำดับทุกประเภท เช่น สตริง รายการ ฯลฯ Python จะพยายามทำให้การดำเนินการของตนทำงานในประเภทต่างๆ ได้สอดคล้องกัน Gotcha มือใหม่สำหรับ Python: อย่าใช้ "len" เป็นชื่อตัวแปรเพื่อหลีกเลี่ยงการปิดกั้นฟังก์ชัน len() เครื่องหมาย "+" สามารถเชื่อม 2 สตริงเข้าด้วยกัน สังเกตในโค้ดด้านล่างว่าตัวแปรไม่ได้มีการประกาศไว้ล่วงหน้า เพียงกำหนดให้กับตัวแปรเท่านั้นก็ไปได้

  s = 'hi'
  print(s[1])          ## i
  print(len(s))        ## 2
  print(s + ' there')  ## hi there

'+' จะไม่แปลงตัวเลขหรือประเภทอื่นๆ เป็นรูปแบบสตริงโดยอัตโนมัติ ซึ่งต่างจาก Java ฟังก์ชัน str() จะแปลงค่าเป็นรูปแบบสตริงเพื่อให้นำไปรวมกับสตริงอื่นๆ ได้

  pi = 3.14
  ##text = 'The value of pi is ' + pi      ## NO, does not work
  text = 'The value of pi is '  + str(pi)  ## yes

สำหรับตัวเลข โอเปอเรเตอร์มาตรฐาน +, /, * จะทำงานตามปกติ ไม่มีโอเปอเรเตอร์ ++ แต่มีเครื่องหมาย +=, -= ฯลฯ หากต้องการหารจำนวนเต็ม ให้ใช้เครื่องหมายทับ 2 ตัว เช่น 6 // 5 คือ 1

โดยปกติแล้ว ฟังก์ชัน "พิมพ์" จะพิมพ์รายการ Python ออกมาอย่างน้อย 1 รายการตามด้วยบรรทัดใหม่ ลิเทอรัลของสตริง "raw" จะมีอักขระนำหน้าด้วย "r" และส่งต่ออักขระทั้งหมดโดยไม่ใช้แบ็กสแลชแบบพิเศษ ดังนั้น r'x\nx' จะประเมินสตริงความยาว 4 "x\nx" "print" อาจใช้อาร์กิวเมนต์หลายข้อเพื่อเปลี่ยนวิธีที่ระบบพิมพ์สิ่งต่างๆ ออกมา (ดู คำจำกัดความฟังก์ชันการพิมพ์ python.org) เช่น การตั้งค่า "end" เป็น "" ไม่ให้พิมพ์บรรทัดใหม่อีกต่อไปหลังจากที่พิมพ์รายการทั้งหมดเสร็จแล้ว

  raw = r'this\t\n and that'

  # this\t\n and that
  print(raw)

  multi = """It was the best of times.
  It was the worst of times."""

  # It was the best of times.
  #   It was the worst of times.
  print(multi)

เมธอดเป็นสตริง

ต่อไปนี้คือวิธีสตริงที่นิยมใช้กันมากที่สุด เมธอดคล้ายกับฟังก์ชัน แต่จะเรียกใช้ "on" กับออบเจ็กต์ หากตัวแปร s เป็นสตริง โค้ด s.lower() จะเรียกใช้เมธอด level() ในออบเจ็กต์สตริงนั้นและส่งคืนผลลัพธ์ (แนวคิดของเมธอดที่ทำงานบนออบเจ็กต์เป็นหนึ่งในแนวคิดพื้นฐานที่ประกอบขึ้นเป็น Object Oriented Programming, OOP) วิธีสตริงที่นิยมใช้กันมากที่สุดมีดังนี้

  • s.lower(), s.upper() -- แสดงผลสตริงในรูปแบบตัวพิมพ์เล็กหรือตัวพิมพ์ใหญ่
  • s.strip() -- แสดงผลสตริงที่มีการลบช่องว่างออกจากจุดเริ่มต้นและสิ้นสุด
  • s.isalpha()/s.isdigit()/s.isspace()... -- ทดสอบว่าอักขระของสตริงทั้งหมดอยู่ในคลาสอักขระต่างๆ หรือไม่
  • s.startswith('other'), s.endswith('other') -- ทดสอบว่าสตริงเริ่มต้นหรือลงท้ายด้วยสตริงอื่นที่ระบุ
  • s.find('other') -- การค้นหาสตริงอื่นที่ระบุ (ไม่ใช่นิพจน์ทั่วไป) ภายใน s และแสดงดัชนีแรกที่เริ่มต้น หรือ -1 หากไม่พบ
  • s.replace('old', 'new') -- แสดงผลสตริงที่รายการ "เก่า" ทั้งหมดถูกแทนที่ด้วย "new"
  • s.split('delim') -- แสดงรายการสตริงย่อยที่คั่นด้วยตัวคั่นที่กำหนด ตัวคั่นไม่ใช่นิพจน์ทั่วไป แต่เป็นเพียงข้อความ 'aaa,bbb,ccc'.split(',') -> ['aaa', 'bbb', 'ccc'] แบ่งเป็นกรณีพิเศษที่สะดวก s.split() (ไม่มีอาร์กิวเมนต์) ที่แยกอักขระที่เป็นช่องว่างทั้งหมด
  • s.join(list) -- ตรงข้ามกับSplit() นำองค์ประกอบต่างๆ ในรายการที่กำหนดมารวมกันโดยใช้สตริงเป็นตัวคั่น เช่น '---'.join(['aaa', 'bbb', 'ccc']) -> aaa---bbb---ccc

การค้นหา "python str" ใน Google ควรนําคุณไปยังเมธอดสตริง python.org อย่างเป็นทางการ ซึ่งจะแสดงเมธอด str ทั้งหมด

Python ไม่มีประเภทอักขระแยกต่างหาก โดยนิพจน์อย่างเช่น s[8] จะแสดงผลสตริง-length-1 ที่มีอักขระนั้น เมื่อใช้สตริง-length-1 โอเปอเรเตอร์ ==, <=, ... ทั้งหมดจะทำงานตามที่คุณคาดหวัง ดังนั้นโดยส่วนใหญ่แล้วคุณไม่จำเป็นต้องทราบว่า Python ไม่มีประเภท "ชาร์" แบบสเกลาร์แยกต่างหาก

เชือกหั่นบาง

ไวยากรณ์ "สไลซ์" เป็นวิธีที่สะดวกในการอ้างถึงส่วนย่อยของลำดับ ซึ่งโดยทั่วไปคือสตริงและรายการ ชิ้นส่วน s[start:end] คือองค์ประกอบที่เริ่มต้นเมื่อเริ่มต้นและขยายไปจนถึง แต่ไม่รวมถึงจุดสิ้นสุด สมมติว่าเรามี s = "สวัสดี"

สตริง &quot;สวัสดี&quot; ที่มีตัวอักษรดัชนี 0 1 2 3 4

  • s[1:4] คือ "ell" -- อักขระที่เริ่มต้นที่ดัชนี 1 และขยายไปจนถึงแต่ไม่รวมดัชนี 4
  • s[1:] คือ 'ello' การละเว้นดัชนีเริ่มต้นหรือสิ้นสุดของสตริง
  • s[:] คือ 'สวัสดี' การละเว้นข้อความทั้ง 2 อย่างจะเป็นการให้สำเนาของสิ่งนั้นเสมอ (นี่เป็นวิธีคัดลอกแบบ Pythonic ในการคัดลอกลำดับ เช่น สตริงหรือรายการ)
  • s[1:100] คือ "ello" -- ดัชนีที่ใหญ่เกินไปจะถูกตัดทอนให้เหลือความยาวสตริง

หมายเลขดัชนีมาตรฐานแบบเลขศูนย์ช่วยให้เข้าถึงอักขระที่อยู่ใกล้กับจุดเริ่มต้นของสตริงได้โดยง่าย อีกทางเลือกหนึ่งคือ Python จะใช้จำนวนลบเพื่อให้เข้าถึงอักขระที่ท้ายสตริงได้โดยง่าย เช่น s[-1] คืออักขระตัวสุดท้าย 'o', s[-2] คือ 'l' คืออักขระตัวสุดท้ายถึงตัวสุดท้าย เป็นต้น ตัวเลขดัชนีที่เป็นลบจะนับย้อนกลับจากจุดสิ้นสุดของสตริง:

  • s[-1] คือ 'o' -- อักขระตัวสุดท้าย (ตัวแรกจากตัวสุดท้าย)
  • s[-4] คือ 'e' -- ที่ 4 จากจุดสิ้นสุด
  • s[:-3] คือ "เขา" -- เลื่อนขึ้นแต่ไม่รวมอักขระ 3 ตัวสุดท้าย
  • s[-3:] คือ 'llo' -- เริ่มด้วยอักขระตัวที่ 3 จากส่วนท้ายและขยายไปถึงส่วนท้ายของสตริง

เป็นความจริงที่แบ่งเป็นส่วนๆ ที่สำหรับดัชนี n หรือ s[:n] + s[n:] == s ซึ่งทำงานได้แม้จะเป็นค่าลบหรือไม่อยู่ในขอบเขตก็ตาม หรือใส่วิธีอื่นที่ s[:n] และ s[n:] แบ่งพาร์ติชันสตริงออกเป็น 2 ส่วนเสมอ เพื่อรักษาอักขระทั้งหมดไว้ ตามที่เราจะเห็นในส่วนรายการในภายหลัง ส่วนต่างๆ สามารถทำงานกับรายการได้เช่นกัน

การจัดรูปแบบสตริง

สิ่งหนึ่งที่ Python ทำได้คือแปลงวัตถุโดยอัตโนมัติ ให้เป็นสตริงที่เหมาะสำหรับการพิมพ์ วิธีการในตัว 2 วิธีคือสตริงที่มีการจัดรูปแบบ หรือที่เรียกว่า "f-strings" และเรียกใช้ str.format()

ลิเทอรัลสตริงที่จัดรูปแบบ

คุณมักจะเห็นลิเทอรัลของสตริงที่มีการจัดรูปแบบในสถานการณ์ต่างๆ เช่น

  value = 2.791514
  print(f'approximate value = {value:.2f}')  # approximate value = 2.79

  car = {'tires':4, 'doors':2}
  print(f'car = {car}') # car = {'tires': 4, 'doors': 2}

สตริงลิเทอรัลที่มีการจัดรูปแบบจะมี "f" นำหน้า (เช่น คำนำหน้า "r" ที่ใช้สำหรับสตริงดิบ) ข้อความใดๆ ที่อยู่นอกวงเล็บปีกกา "{}" จะพิมพ์ออกมาโดยตรง นิพจน์ที่อยู่ใน "{}" จะพิมพ์ออกมาโดยใช้ข้อกำหนดเฉพาะของรูปแบบซึ่งอธิบายไว้ในข้อกำหนดของรูปแบบ มีการจัดรูปแบบที่ใช้ได้หลายอย่าง เช่น การตัดและการแปลงเป็นสัญกรณ์วิทยาศาสตร์ และการจัดข้อความชิดซ้าย/ขวา/ตรงกลาง

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

  address_book = [{'name':'N.X.', 'addr':'15 Jones St', 'bonus': 70},
      {'name':'J.P.', 'addr':'1005 5th St', 'bonus': 400},
      {'name':'A.A.', 'addr':'200001 Bdwy', 'bonus': 5},]

  for person in address_book:
    print(f'{person["name"]:8} || {person["addr"]:20} || {person["bonus"]:>5}')

  # N.X.     || 15 Jones St          ||    70
  # J.P.     || 1005 5th St          ||   400
  # A.A.     || 200001 Bdwy          ||     5

% สตริง

นอกจากนี้ Python ยังมีฟังก์ชันแบบเก่าซึ่งคล้ายกับ {2}printf() เพื่อรวมสตริงเข้าด้วยกัน โอเปอเรเตอร์ % จะใช้สตริงรูปแบบ Printf-type ทางด้านซ้าย (%d int, สตริง %s, จุดลอยตัว %f/%g) และค่าที่ตรงกันใน Tuple ทางด้านขวา (Tuple เกิดจากค่าที่คั่นด้วยเครื่องหมายจุลภาค ซึ่งโดยปกติแล้วจะจัดกลุ่มอยู่ในวงเล็บ)

  # % operator
  text = "%d little pigs come out, or I'll %s, and I'll %s, and I'll blow your %s down." % (3, 'huff', 'puff', 'house')

บรรทัดด้านบนค่อนข้างยาว สมมติว่าคุณต้องการแยกเป็นบรรทัดๆ คุณไม่สามารถแบ่งบรรทัดหลังเครื่องหมาย "%" เหมือนกับในภาษาอื่นๆ ได้ เนื่องจากโดยค่าเริ่มต้น Python จะถือว่าแต่ละบรรทัดเป็นคำสั่งที่แยกจากกัน (ในด้านบวก เราจึงไม่จำเป็นต้องพิมพ์เครื่องหมายเซมิโคลอนต่อบรรทัด) ในการแก้ไขปัญหานี้ ให้ใส่นิพจน์ทั้งหมดในชุดวงเล็บด้านนอก จากนั้นนิพจน์จะสามารถขยายได้หลายบรรทัด เทคนิคการแสดงโค้ดข้ามเส้นนี้จะทำงานร่วมกับโครงสร้างการจัดกลุ่มต่างๆ ตามรายละเอียดด้านล่าง: ( ), [ ], { }

  # Add parentheses to make the long line work:
  text = (
    "%d little pigs come out, or I'll %s, and I'll %s, and I'll blow your %s down."
    % (3, 'huff', 'puff', 'house'))

ดีกว่านี้ แต่คิวยังยาวไปหน่อย Python ให้คุณตัดบรรทัดออกเป็นส่วนๆ แล้วนำมาต่อกันโดยอัตโนมัติ ดังนั้น เพื่อให้บรรทัดนี้สั้นลง เราสามารถทำดังนี้

  # Split the line into chunks, which are concatenated automatically by Python
  text = (
    "%d little pigs come out, "
    "or I'll %s, and I'll %s, "
    "and I'll blow your %s down."
    % (3, 'huff', 'puff', 'house'))

สตริง (Unicode เทียบกับไบต์)

สตริง Python ปกติคือ Unicode

นอกจากนี้ Python ยังรองรับสตริงที่ประกอบด้วยไบต์ปกติ (แสดงด้วยคำนำหน้า "b" หน้าสตริงลิเทอรัล) เช่น

> byte_string = b'A byte string'
> byte_string
  b'A byte string'

สตริง Unicode เป็นออบเจ็กต์ประเภทอื่นจากสตริงแบบไบต์ แต่ไลบรารีต่างๆ เช่น นิพจน์ทั่วไปทำงานได้อย่างถูกต้องหากส่งสตริงประเภทใดประเภทหนึ่ง

หากต้องการแปลงสตริง Python ปกติเป็นไบต์ ให้เรียกใช้เมธอด encode() ในสตริง ในทางกลับกัน วิธีการถอดรหัสสตริงไบต์ (ไบต์) จะแปลงไบต์ปกติที่เข้ารหัสเป็นสตริง Unicode ดังนี้

> ustring = 'A unicode \u018e string \xf1'
> b = ustring.encode('utf-8')
> b
b'A unicode \xc6\x8e string \xc3\xb1'  ## bytes of utf-8 encoding. Note the b-prefix.
> t = b.decode('utf-8')                ## Convert bytes back to a unicode string
> t == ustring                         ## It's the same as the original, yay!

True

ในส่วนการอ่านไฟล์จะมีตัวอย่างที่แสดงวิธีเปิดไฟล์ข้อความด้วยการเข้ารหัสและอ่านสตริง Unicode

หากใบแจ้งยอด

Python ไม่ได้ใช้ { } เพื่อล้อมรอบบล็อกโค้ดสำหรับ if/loops/function ฯลฯ แต่ Python จะใช้โคลอน (:) และการเยื้อง/ช่องว่างเพื่อจัดกลุ่มคำสั่งแทน การทดสอบบูลีนของ if ที่ไม่จำเป็นต้องอยู่ในวงเล็บ (แตกต่างมากจาก C++/Java) และมีอนุประโยค *elif* และ *else* (mnemonic: คำว่า "elif" มีความยาวเท่ากับคำว่า "else")

ค่าใดๆ จะใช้เป็น if-test ได้ ค่า "ศูนย์" จะนับเป็น false ทั้งหมด ได้แก่ ไม่มี 0 สตริงว่างเปล่า รายการที่ว่างเปล่า พจนานุกรมเปล่า นอกจากนี้ยังมีประเภทบูลีนที่มี 2 ค่า ได้แก่ True และ False (แปลงเป็น int ค่าเหล่านี้คือ 1 และ 0) Python มีการเปรียบเทียบตามปกติ ได้แก่ ==, !=, <, <=, >, >= ซึ่งต่างจาก Java และ C ตรงที่ == มีการมากเกินไปเพื่อให้ทำงานกับสตริงได้อย่างถูกต้อง โอเปอเรเตอร์บูลีนคือคำที่สะกดเป็น *และ*, *หรือ*, *ไม่ใช่* (Python ไม่ใช้รูปแบบ C && || !) นี่คือหน้าตาของโค้ดสำหรับแอปสุขภาพที่ให้คำแนะนำเรื่องเครื่องดื่มตลอดทั้งวัน ลองสังเกตดูว่าแต่ละบล็อกของคำสั่งนั้น/ไม่มีจะขึ้นต้นด้วย : และจัดกลุ่มคำสั่งตามการเยื้องอย่างไร

  if time_hour >= 0 and time_hour <= 24:
    print('Suggesting a drink option...')
    if mood == 'sleepy' and time_hour < 10:
      print('coffee')
    elif mood == 'thirsty' or time_hour < 2:
      print('lemonade')
    else:
      print('water')

ฉันพบว่าการไม่ใส่เครื่องหมาย ":" เป็นความผิดพลาดทางไวยากรณ์ที่พบได้บ่อยที่สุดเมื่อพิมพ์รหัสด้านบน ซึ่งอาจเป็นเพราะการพิมพ์เป็นการทำงานเพิ่มเติมเมื่อเทียบกับพฤติกรรม C++/Java ของฉัน และอย่าวางการทดสอบบูลีนไว้ในวงเล็บ นั่นเป็นพฤติกรรมแบบ C/Java หากโค้ดนั้นสั้น คุณสามารถวางโค้ดไว้ในบรรทัดเดียวกันหลัง ":" แบบนี้ (สำหรับฟังก์ชัน ลูป ฯลฯ เช่นเดียวกัน) แม้ว่าบางคนจะรู้สึกว่าการเว้นช่องว่างในแต่ละบรรทัดแยกกันเป็นสิ่งที่อ่านได้ง่ายขึ้น

  if time_hour < 10: print('coffee')
  else: print('water')

แบบฝึกหัด: string1.py

หากต้องการฝึกเนื้อหาในส่วนนี้ ให้ลองแบบฝึกหัด string1.py ในแบบฝึกหัดพื้นฐาน