ฉันจะทำตัวแบ่งบรรทัด (การต่อเนื่องบรรทัด) ใน Python ได้อย่างไร


1074

ฉันมีรหัสยาว ๆ ซึ่งฉันต้องการแยกย่อยในหลายบรรทัด ฉันจะใช้อะไรและไวยากรณ์คืออะไร

ตัวอย่างเช่นการเพิ่มสตริงจำนวนมาก

e = 'a' + 'b' + 'c' + 'd'

และมีสองบรรทัดดังนี้:

e = 'a' + 'b' +
    'c' + 'd'

คำตอบ:


1210

สายคืออะไร คุณสามารถมีข้อโต้แย้งในบรรทัดถัดไปได้โดยไม่มีปัญหา:

a = dostuff(blahblah1, blahblah2, blahblah3, blahblah4, blahblah5, 
            blahblah6, blahblah7)

มิฉะนั้นคุณสามารถทำสิ่งนี้:

if a == True and \
   b == False

ตรวจสอบคู่มือสไตล์สำหรับข้อมูลเพิ่มเติม

จากบรรทัดตัวอย่างของคุณ:

a = '1' + '2' + '3' + \
    '4' + '5'

หรือ:

a = ('1' + '2' + '3' +
    '4' + '5')

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


35
ที่จริงแล้วคุณมีการตั้งค่าสไตล์คู่มือย้อนหลัง แนะนำให้ใช้ความต่อเนื่องโดยนัยแบ็กสแลชที่ชัดเจนจะใช้ในกรณีที่จำเป็นเท่านั้น
Carl Meyer

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

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

23
สันนิษฐานได้ว่า PEP-8 มีการเปลี่ยนแปลงตั้งแต่ความคิดเห็นเหล่านี้ถูกเพิ่มเนื่องจากเป็นที่ชัดเจนแล้วในตอนนี้ว่าควรเพิ่มวงเล็บในการตัดบรรทัดยาว: "เส้นยาวสามารถแบ่งได้หลายบรรทัดโดยการห่อนิพจน์ในวงเล็บ"
Daniel

46
PEP8 เปลี่ยนไปในปี 2010 - "บางครั้งการใช้แบ็กสแลชดูดีกว่า" หายไปแล้ว
e100

230

จากPEP 8 - คู่มือสไตล์สำหรับ Python Code :

วิธีที่นิยมใช้ในการพันยาวโดยใช้ความต่อเนื่องของ Python ในวงเล็บวงเล็บและเครื่องหมายวงเล็บ เส้นยาวสามารถแบ่งได้หลายบรรทัดโดยการตัดนิพจน์ในวงเล็บ ควรใช้สิ่งเหล่านี้ในการตั้งค่าเพื่อใช้แบ็กสแลชสำหรับการต่อเนื่องของบรรทัด

แบ็กสแลชอาจยังคงเหมาะสมในบางครั้ง ตัวอย่างเช่นยาวหลายคำสั่งไม่สามารถใช้ความต่อเนื่องโดยนัยดังนั้นแบ็กสแลชจึงเป็นที่ยอมรับ:

with open('/path/to/some/file/you/want/to/read') as file_1, \
        open('/path/to/some/file/being/written', 'w') as file_2:
    file_2.write(file_1.read())

อีกกรณีหนึ่งนั้นคือข้อความยืนยัน

ตรวจสอบให้แน่ใจที่จะเยื้องบรรทัดต่อเนื่องอย่างเหมาะสม สถานที่ที่ต้องการทำลายผู้ประกอบการแบบไบนารีคือหลังจากผู้ดำเนินการไม่ใช่ก่อนหน้านี้ ตัวอย่างบางส่วน:

class Rectangle(Blob):

    def __init__(self, width, height,
                 color='black', emphasis=None, highlight=0):
        if (width == 0 and height == 0 and
                color == 'red' and emphasis == 'strong' or
                highlight > 100):
            raise ValueError("sorry, you lose")
        if width == 0 and height == 0 and (color == 'red' or
                                           emphasis is None):
            raise ValueError("I don't think so -- values are %s, %s" %
                             (width, height))
        Blob.__init__(self, width, height,
                      color, emphasis, highlight)

ตอนนี้ PEP8 แนะนำการประชุมที่ตรงกันข้าม (สำหรับการหยุดพักที่การทำงานแบบไบนารี) ที่นักคณิตศาสตร์และผู้จัดพิมพ์ใช้เพื่อปรับปรุงการอ่าน

สไตล์การทำลายของ Donald Knuth ก่อนที่ผู้ประกอบการแบบไบนารีจะปรับผู้ปฏิบัติงานให้อยู่ในแนวตั้งซึ่งช่วยลดปริมาณงานของตาเมื่อพิจารณาว่าจะเพิ่มหรือลบรายการใด

จากPEP8: เส้นแบ่งก่อนหรือหลังตัวดำเนินการไบนารีหรือไม่ :

โดนัลด์นัทท์อธิบายกฎดั้งเดิมในคอมพิวเตอร์และซีรีส์เรียงพิมพ์: "แม้ว่าสูตรในวรรคจะหยุดหลังจากการดำเนินการและความสัมพันธ์แบบไบนารีเสมอ

ตามประเพณีจากคณิตศาสตร์มักส่งผลให้รหัสอ่านง่ายขึ้น:

# Yes: easy to match operators with operands
income = (gross_wages
          + taxable_interest
          + (dividends - qualified_dividends)
          - ira_deduction
          - student_loan_interest)

ในรหัสไพ ธ อนนั้นอนุญาตให้แบ่งก่อนหรือหลังตัวดำเนินการไบนารีได้ตราบใดที่การประชุมมีความสอดคล้องกันภายในเครื่อง สำหรับรหัสใหม่แนะนำให้ใช้สไตล์ของ Knuth

[3]: The TeXBook ของ Donald Knuth หน้า 195 และ 196


3
หมายเหตุข้อเสนอแนะเปลี่ยนไปในปี 2010: "เส้นยาวสามารถหัก ... โดยการห่อนิพจน์ในวงเล็บสิ่งเหล่านี้ควรใช้ในการตั้งค่าเพื่อใช้แบ็กสแลช ... " และแบ็กสแลชทั้งหมดถูกลบออกจากตัวอย่างรหัส
e100

1
@ E100: อ่านข้อความเป็นตัวหนาด้านบน: มันเป็นสิ่งเดียวกับThe preferred way .. is by using Python's implied line continuation inside parentheses by wrapping expressions in parenthesesฉันได้อัปเดตตัวอย่างแล้ว
jfs

10
แต่โปรดทราบว่า "บางครั้งการใช้แบ็กสแลชดูดีกว่า" ก็หายไปเช่นกัน
e100


6
ในปี 2015 คู่มือรูปแบบได้รับการปรับปรุงให้เป็นที่นิยมมากกว่าก่อนผู้ประกอบการไบนารี่หลังจากการวิจัยโดยDonald Knuthเนื่องจากการปรับปรุงการรับรู้ในการอ่าน
J2C

70

อันตรายในการใช้แบ็กสแลชเพื่อสิ้นสุดบรรทัดคือถ้าเพิ่มช่องว่างหลังจากแบ็กสแลช (ซึ่งแน่นอนยากมากที่จะเห็น) แบ็กสแลชจะไม่ทำสิ่งที่คุณคิด

ดู Python Idioms และ Anti-Idioms (สำหรับPython 2หรือPython 3 ) สำหรับข้อมูลเพิ่มเติม


8
นี่คือเหตุผลหนึ่งที่ทำให้สามารถเห็นช่องว่างที่ต่อท้ายได้ดีขึ้น เช่นบางสิ่งบางอย่างเช่นset list listchars=trail:·ในกลุ่ม :)
Beau

25

ใส่\ที่ท้ายบรรทัดของคุณหรือใส่คำสั่งใน ( .. )parens จากIBM :

b = ((i1 < 20) and
     (i2 < 30) and
     (i3 < 40))

หรือ

b = (i1 < 20) and \
    (i2 < 30) and \
    (i3 < 40)

24

คุณสามารถแยกบรรทัดระหว่างวงเล็บและวงเล็บปีกกา นอกจากนี้คุณสามารถต่อท้ายอักขระแบ็กสแลช\ต่อหนึ่งบรรทัดเพื่อทำลายมันอย่างชัดเจน:

x = (tuples_first_value,
     second_value)
y = 1 + \
    2

20

จากปากม้า: เข้าร่วมสายอย่างชัดเจน

บรรทัดฟิสิคัลตั้งแต่สองเส้นขึ้นไปอาจถูกรวมเข้ากับโลจิคัลไลน์โดยใช้เครื่องหมายแบ็กสแลช ( \) ดังนี้: เมื่อฟิสิคัลไลน์สิ้นสุดในแบ็กสแลชที่ไม่ได้เป็นส่วนหนึ่งของสตริงตัวอักษรหรือความคิดเห็น ลบแบ็กสแลชและอักขระสิ้นสุดบรรทัดต่อไปนี้ ตัวอย่างเช่น:

if 1900 < year < 2100 and 1 <= month <= 12 \
   and 1 <= day <= 31 and 0 <= hour < 24 \
   and 0 <= minute < 60 and 0 <= second < 60:   # Looks like a valid date
        return 1

บรรทัดที่ลงท้ายด้วยแบ็กสแลชไม่สามารถแสดงความคิดเห็นได้ แบ็กสแลชไม่แสดงความคิดเห็นใด ๆ แบ็กสแลชไม่ได้ทำต่อโทเค็นยกเว้นสำหรับตัวอักษรสตริง (เช่นโทเค็นอื่นที่ไม่ใช่ตัวอักษรสตริงจะไม่สามารถแยกข้ามบรรทัดทางกายภาพโดยใช้เครื่องหมายแบ็กสแลช) เครื่องหมายทับขวาผิดกฎหมายที่อื่นในบรรทัดนอกตัวอักษรสตริง


7
-1 เนื่องจากตัวอย่างนี้เป็น IMO ที่ไม่มีลักษณะเฉพาะ เงื่อนไขแบบผสมนั้นสามารถมีวงเล็บล้อมรอบแทนซึ่งเป็นประโยชน์มากกว่า (สำหรับการแก้ไขหรือการ rewrapping อัตโนมัติ) และสำนวน
u0b34a0f6ae

4

อาจไม่ใช่วิธี Pythonic แต่โดยทั่วไปฉันใช้รายการที่มีฟังก์ชั่นการรวมสำหรับการเขียนสตริงยาวเช่นแบบสอบถาม SQL:

query = " ".join([
    'SELECT * FROM "TableName"',
    'WHERE "SomeColumn1"=VALUE',
    'ORDER BY "SomeColumn2"',
    'LIMIT 5;'
])

2

นำมาจากคำแนะนำของ The Hitchhiker's to Python ( Line Continuation ):

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

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

อย่างไรก็ตามบ่อยครั้งที่การแบ่งสายลอจิคัลที่ยาวเป็นสิ่งที่บ่งบอกว่าคุณกำลังพยายามทำหลายอย่างมากเกินไปในเวลาเดียวกันซึ่งอาจขัดขวางการอ่านได้

นี่คือตัวอย่างการพิจารณาการนำเข้าหลายรายการ (เมื่อเกินขีด จำกัด บรรทัดที่กำหนดไว้ใน PEP-8 ) ก็ใช้กับสตริงโดยทั่วไป:

from app import (
    app, abort, make_response, redirect, render_template, request, session
)

1

หากคุณต้องการแบ่งบรรทัดของคุณเนื่องจากสตริงตัวอักษรยาวคุณสามารถแบ่งสตริงนั้นเป็นชิ้น ๆ :

long_string = "a very long string"
print("a very long string")

จะถูกแทนที่ด้วย

long_string = (
  "a "
  "very "
  "long "
  "string"
)
print(
  "a "
  "very "
  "long "
  "string"
)

เอาต์พุตสำหรับทั้งสองข้อความสั่งพิมพ์:

a very long string

แจ้งให้ทราบวงเล็บในการส่งผลกระทบ

โปรดสังเกตว่าการแบ่งสตริงตัวอักษรออกเป็นชิ้น ๆ อนุญาตให้ใช้ส่วนนำหน้าตัวอักษรบนส่วนต่าง ๆ ของสตริงเท่านั้น:

s = (
  "2+2="
  f"{2+2}"
)

0

ใช้โอเปอเรเตอร์ต่อเนื่องบรรทัดคือ "\"

ตัวอย่าง:

# Ex.1

x = 1
s =  x + x**2/2 + x**3/3 \
       + x**4/4 + x**5/5 \
       + x**6/6 + x**7/7 \
       + x**8/8
print(s)
# 2.7178571428571425


----------


# Ex.2

text = ('Put several strings within parentheses ' \
        'to have them joined together.')
print(text)


----------


# Ex.3

x = 1
s =  x + x**2/2 \
       + x**3/3 \
       + x**4/4 \
       + x**6/6 \
       + x**8/8
print(s)
# 2.3749999999999996
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.