วิธี Pythonic เพื่อสร้างสตริงที่มีความยาวหลายบรรทัด


1306

ฉันมีคำถามยาวมาก ฉันต้องการแยกเป็นหลายบรรทัดใน Python วิธีทำใน JavaScript จะใช้หลายประโยคและเข้าร่วมกับ+โอเปอเรเตอร์ (ฉันรู้ว่าอาจไม่ใช่วิธีที่มีประสิทธิภาพที่สุดในการทำ แต่ฉันไม่ได้กังวลเกี่ยวกับประสิทธิภาพในขั้นตอนนี้เพียงแค่อ่านโค้ดได้) . ตัวอย่าง:

var long_string = 'some text not important. just garbage to' +
                  'illustrate my example';

ฉันพยายามทำสิ่งที่คล้ายกันใน Python แต่มันใช้งานไม่ได้ดังนั้นฉันจึง\แบ่งสายยาว ๆ อย่างไรก็ตามฉันไม่แน่ใจว่าวิธีนี้เป็นวิธีที่ดีที่สุด / pythonicest เท่านั้น มันดูน่าอึดอัดใจ รหัสจริง:

query = 'SELECT action.descr as "action", '\
    'role.id as role_id,'\
    'role.descr as role'\
    'FROM '\
    'public.role_action_def,'\
    'public.role,'\
    'public.record_def, '\
    'public.action'\
    'WHERE role.id = role_action_def.role_id AND'\
    'record_def.id = role_action_def.def_id AND'\
    'action.id = role_action_def.action_id AND'\
    'role_action_def.account_id = ' + account_id + ' AND'\
    'record_def.account_id=' + account_id + ' AND'\
    'def_id=' + def_id

207
เนื่องจากตัวอย่างของคุณดูเหมือนบล็อก SQL จะรอการโจมตีจากการฉีดข้อเสนอแนะอีกประการหนึ่งคือการค้นหาไลบรารี SQL ระดับสูงกว่าเช่น SQLAlchemy หรือสิ่งที่จะหลีกเลี่ยงการแฮ็ก SQL แบบดิบร่วมกันเช่นนี้ (อาจเป็นหัวข้อ แต่คุณขอคำแนะนำ "ใด ๆ ";)
John Gaines Jr.

6
นี่ก็เป็น "วิธี Pythonic เพื่อสร้างรหัสหลายคู่สายสำหรับสายยาว" การสร้างสตริงที่มีการขึ้นบรรทัดใหม่ดูtextwrap.dedent
Bob Stein

8
@cezar ฉันเขียนคำถามนี้มานานกว่าห้าปีที่แล้ว แต่ฉันจำได้ว่ามันเกิดขึ้นจากการไม่รู้วิธีที่จะใช้แบบสอบถาม SQL ยาวในหลายบรรทัด ฉันเห็นด้วยว่าฉันกำลังทำสิ่งที่โง่ ๆ ด้วยสายยาว ๆ นั่น แต่นั่นไม่ใช่คำถามของฉันและฉันก็ไม่ฉลาดพอที่จะมองหาตัวอย่างที่ดีกว่าเพื่อแสดงให้เห็นว่ามันไม่ได้มีความกังวลเกี่ยวกับการฉีด sql
Pablo Mescher

@cezar ไม่นี่ไม่ใช่ปัญหา XY แบบสอบถามจะอยู่ในรูปแบบที่ดีที่สุดในหลายบรรทัดในทุกกรณี SQLi ไม่เกี่ยวข้องกับคำถามในมือ คำเตือนตัวหนาที่ยิ่งใหญ่ล้วน แต่เป็นธรรมโดยสิ้นเชิง :)
45414

ฉันเขียนแพ็คเกจเล็ก ๆ สำหรับสิ่งนี้ ตัวอย่างที่นี่: stackoverflow.com/a/56940938/1842491
Shay

คำตอบ:


2226

คุณกำลังพูดถึงสตริงหลายบรรทัด? ใช้คำพูดสามคำเพื่อเริ่มและจบได้ง่าย

s = """ this is a very
        long string if I had the
        energy to type more and more ..."""

คุณสามารถใช้อัญประกาศเดี่ยวได้ (3 รายการจากจุดเริ่มต้นและจุดสิ้นสุด) และจัดการสตริงผลลัพธ์sเช่นเดียวกับสตริงอื่น ๆ

หมายเหตุ : เช่นเดียวกับสตริงใด ๆ สิ่งใดระหว่างเครื่องหมายคำพูดเริ่มต้นและจุดสิ้นสุดกลายเป็นส่วนหนึ่งของสตริงดังนั้นตัวอย่างนี้มีช่องว่างนำหน้า (ตามที่ระบุโดย @ root45) สตริงนี้จะมีทั้งช่องว่างและขึ้นบรรทัดใหม่

เช่น ,:

' this is a very\n        long string if I had the\n        energy to type more and more ...'

ในที่สุดเราสามารถสร้างบรรทัดยาวใน Python เช่นนี้

 s = ("this is a very"
      "long string too"
      "for sure ..."
     )

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

'this is a verylong string toofor sure ...'

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


8
ฉันต้องการใช้โอเปอเรเตอร์ "+" อย่างชัดเจนสำหรับวิธีที่สอง ไม่ยุ่งยากและปรับปรุงความสามารถในการอ่าน
Marco Sulla

38
@LucasMalor สตริงที่อยู่ติดกันคือการต่อเวลาคอมไพล์ ไม่ได้ใช้ตัว+ดำเนินการทำให้การต่อข้อมูลเกิดขึ้นขณะใช้งานจริงหรือ
Joshua Taylor

13
สำหรับการอ้างอิงนี่คือเอกสารอย่างเป็นทางการสำหรับปรากฏการณ์นี้: docs.python.org/2/reference/ … (python 2) และdocs.python.org/3/reference/ … (python 3)
neverendingqs

4
ตัวอย่างของคุณดี แต่ฉันหวังว่ามันจะมีการสาธิตวิธีการฝังข้อมูลตัวแปรลงในแบบสอบถามอย่างปลอดภัยและปลอดภัย ทั้งโค้ดตัวอย่าง OP และ @jessee แสดงวิธีที่จะไม่ทำอย่างถูกต้อง (พวกเขากำลังเชิญให้โจมตี SQL) ดูเพิ่มเติมที่: dev.mysql.com/doc/connector-python/en/…
Scott Prive

2
คุณสามารถใช้textwrap.dedentเพื่อลบช่องว่างนำหน้าที่ไม่ต้องการ docs.python.org/3/library/textwrap.html#textwrap.dedent
Corey Goldberg

190

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

query = ('SELECT   action.descr as "action", '
         'role.id as role_id,'
         'role.descr as role'
         ' FROM '
         'public.role_action_def,'
         'public.role,'
         'public.record_def, '
         'public.action'
         ' WHERE role.id = role_action_def.role_id AND'
         ' record_def.id = role_action_def.def_id AND'
         ' action.id = role_action_def.action_id AND'
         ' role_action_def.account_id = '+account_id+' AND'
         ' record_def.account_id='+account_id+' AND'
         ' def_id='+def_id)

ในคำสั่ง SQL เช่นเดียวกับสิ่งที่คุณกำลังสร้างสตริงหลายบรรทัดก็ไม่เป็นไร แต่ถ้าช่องว่างพิเศษที่มีหลายบรรทัดจะมีปัญหาก็จะเป็นวิธีที่ดีในการบรรลุสิ่งที่คุณต้องการ


1
@Pablo คุณสามารถเพิ่มความคิดเห็นหลังจาก,
Ashwini Chaudhary

@ 200OK คุณหมายถึง'อะไรเหรอ
kon Psych

3
อีกวิธีในการจัดรูปแบบสายนี้จะเพิ่ม.format(...)หลังจากวงเล็บปิด %สัญกรณ์การขึ้นรูปต้องทำงานด้วย แต่ฉันไม่ได้ลองเลย
kon Psych

3
โปรดทราบว่าแต่ละบรรทัดต้องลงท้ายด้วยค่าคงที่สตริงดังนั้น' foo '+variableจะไม่ทำงาน แต่' foo '+variable+''จะ
yoyo

46
ตัวอย่างนี้เป็นประตูเปิดสู่การโจมตีด้วยการฉีด SQL โปรดไม่มีใครใช้สิ่งนี้กับแอปพลิเคชันสาธารณะใด ๆ ดูเอกสาร MySQL สำหรับวิธีการใช้ 'ตัวยึด': dev.mysql.com/doc/connector-python/en/…
Scott Prive

138

ทำลายเส้นด้วยการ\ทำงานให้ฉัน นี่คือตัวอย่าง:

longStr = "This is a very long string " \
        "that I wrote to help somebody " \
        "who had a question about " \
        "writing long strings in Python"

9
ฉันต้องการทั้งเครื่องหมายคำพูดสามหรือห่อภายใน () เพื่อ \ character
Khanh Hua

14
ฉันแนะนำอย่างยิ่งให้วางช่องว่างไว้ที่จุดเริ่มต้นของบรรทัดต่อไปนี้แทนตอนท้ายของบรรทัดที่ตามมา วิธีนี้สิ่งหนึ่งที่ขาดหายไปโดยบังเอิญเป็นวิธีที่ชัดเจนมากขึ้น (และมีโอกาสน้อยที่จะเกิดขึ้น)
Alfe

ใช้ได้กับตัวแปรที่ส่วนท้ายของบรรทัดด้วยlongStr = "account: " + account_id + \ ...
frmbelz

ฉันได้รับข้อผิดพลาดต่อไปนี้: the backslash is redundant between bracketsเมื่อฉันเขียนภายในprint()
alper

50

ฉันพบว่าตัวเองมีความสุขกับสิ่งนี้:

string = """This is a
very long string,
containing commas,
that I split up
for readability""".replace('\n',' ')

31
ไม่เห็นด้วย เกิดอะไรขึ้นถ้าบรรทัดแรก ("string = ... ") มีการเยื้องอย่างหนัก หนึ่งจะต้องกำจัดเส้นต่อไปนี้เพื่อเยื้องศูนย์ซึ่งดูน่าเกลียดในช่วงกลางของบล็อกเว้าแหว่งอย่างอื่น
xjcl

1
ส่วนใหญ่ของสตริงความยาวของฉันเกิดขึ้นที่ระดับโมดูลซึ่งสิ่งนี้เหมาะสมอย่างยิ่ง ในกรณีของคุณแม้ว่าจะเห็นได้ชัดว่านี่ไม่ใช่ทางออกที่ดีที่สุด
Eero Aaltonen

1
ฉันชอบวิธีการนี้เพราะสิทธิ์ในการอ่าน ในกรณีที่เรามีสายยาวไม่มีทาง ... ขึ้นอยู่กับระดับของการเยื้องที่คุณอยู่และยัง จำกัด อยู่ที่ 80 ตัวอักษรต่อบรรทัด ... ดี ... ไม่จำเป็นต้องพูดอะไรอีก ในมุมมองของฉันคู่มือสไตล์หลามยังคงคลุมเครือมาก ขอบคุณ!
Eduardo Lucio

มันจะน่าเกลียดมากถ้ามันถูกใช้ภายใต้โมดูลฉันต้องเป็นยัง.replace('\t','')
alper

44

ฉันพบว่าเมื่อสร้างสายยาวคุณมักจะทำอะไรบางอย่างเช่นการสร้างแบบสอบถาม SQL ซึ่งในกรณีนี้จะดีที่สุด:

query = ' '.join((  # note double parens, join() takes an iterable
    "SELECT foo",
    "FROM bar",
    "WHERE baz",
))

สิ่งที่ Levon แนะนำนั้นดี แต่อาจเสี่ยงต่อความผิดพลาด:

query = (
    "SELECT foo"
    "FROM bar"
    "WHERE baz"
)

query == "SELECT fooFROM barWHERE baz"  # probably not what you want

8
+1 บรรเทารหัสวิจารณ์จากที่มีการเพียรพยายามตรวจสอบด้านขวาสุดของบรรทัดสำหรับทุกช่องว่างไม่เพียงพอ OP ยอมรับข้อผิดพลาดนี้หลายครั้งตามที่ระบุไว้โดย @KarolyHorvath
Bob Stein

2
เมื่อตรวจสอบสตริงหลายบรรทัดที่เขียนในลักษณะเดียวกันฉันต้องการช่องว่างที่เพียงพอที่ด้านซ้ายของทุกบรรทัดเพื่อยืนยันง่าย
ร่ม

3
@ BobStein-VisiBone Code บทวิจารณ์ไม่ควรเกี่ยวกับข้อผิดพลาดทางไวยากรณ์หรือข้อบกพร่องเล็ก ๆ เช่นนี้พวกเขาควรจะเกี่ยวกับสาร หากใครบางคนกำลังวางโค้ดเพื่อการตรวจสอบที่มีข้อผิดพลาดทางไวยากรณ์ (และจะไม่เรียกใช้เลยหรือในบางสถานการณ์) แสดงว่ามีบางอย่างผิดปกติ มันไม่ยากที่จะใช้ผ้าสำลีก่อนที่จะส่ง หากบุคคลนั้นไม่ได้สังเกตเห็นว่าโปรแกรมของพวกเขาทำงานไม่ถูกต้องเพราะพวกเขาทำผิดพลาดอย่างเห็นได้ชัดพวกเขาไม่ควรกระทำ
Charles Addis

1
เห็นด้วย @CharlesAddis การตรวจสอบโค้ดควรมาหลังจากวิธีการอัตโนมัติเช่นผ้าสำลีการเน้นไวยากรณ์ ฯลฯ อย่างไรก็ตามข้อผิดพลาดบางอย่างที่หายไปจาก white-space อาจไม่ถูกจับเช่นนั้น ประโยชน์ของตัวเองในทุกข้อได้เปรียบที่สมเหตุสมผลในการป้องกันข้อผิดพลาดฉันแนะนำ
Bob Stein

33

คุณสามารถเชื่อมตัวแปรเข้าด้วยกันเมื่อใช้สัญลักษณ์ "" ":

foo = '1234'

long_string = """fosdl a sdlfklaskdf as
as df ajsdfj asdfa sld
a sdf alsdfl alsdfl """ +  foo + """ aks
asdkfkasdk fak"""

แก้ไข: พบวิธีที่ดีกว่าด้วยชื่อ params และ. format ():

body = """
<html>
<head>
</head>
<body>
    <p>Lorem ipsum.</p>
    <dl>
        <dt>Asdf:</dt>     <dd><a href="{link}">{name}</a></dd>
    </dl>
    </body>
</html>
""".format(
    link='http://www.asdf.com',
    name='Asdf',
)

print(body)

26

วิธีนี้ใช้:

  • แบ็กสแลชเพียงอันเดียวเพื่อหลีกเลี่ยงการป้อนบรรทัดแรก
  • เกือบไม่มีเครื่องหมายวรรคตอนภายในโดยใช้สตริงที่ยกมาสาม
  • แยกการเยื้องโลคัลออกโดยใช้โมดูลtextwrap inspect
  • ใช้การแก้ไขสตริงในรูปแบบ python 3.6 ('f') สำหรับaccount_idและdef_idตัวแปร

วิธีนี้ดูไพเราะที่สุดสำหรับฉัน

# import textwrap  # See update to answer below
import inspect

# query = textwrap.dedent(f'''\
query = inspect.cleandoc(f'''
    SELECT action.descr as "action", 
    role.id as role_id,
    role.descr as role
    FROM 
    public.role_action_def,
    public.role,
    public.record_def, 
    public.action
    WHERE role.id = role_action_def.role_id AND
    record_def.id = role_action_def.def_id AND
    action.id = role_action_def.action_id AND
    role_action_def.account_id = {account_id} AND
    record_def.account_id={account_id} AND
    def_id={def_id}'''
)

อัปเดต : 1/29/2019 รวมคำแนะนำของ @ ShadowRanger ไว้ใช้inspect.cleandocแทนtextwrap.dedent


5
หมายเหตุ: inspect.cleandocเป็นดีกว่าเล็กน้อยกว่าtextwrap.dedentขณะที่มันไม่จำเป็นต้องมีบรรทัดแรกจะเป็นที่ว่างเปล่าด้วยตัวอักษรเส้นต่อเนื่องในตอนท้าย
ShadowRanger

2
@ShadowRanger ว้าวฉันไม่เคยใช้ cleandoc มาก่อน ฉันอัปเดตคำตอบของฉันและจะใช้ในอนาคตinspect.cleandocสำหรับสิ่งนี้
Christopher Bruns

23

ใน Python> = 3.6 คุณสามารถใช้ตัวอักษรสตริงที่จัดรูปแบบ (สตริง f)

query= f'''SELECT   action.descr as "action"
    role.id as role_id,
    role.descr as role
    FROM
    public.role_action_def,
    public.role,
    public.record_def,
    public.action
    WHERE role.id = role_action_def.role_id AND
    record_def.id = role_action_def.def_id AND
    action.id = role_action_def.action_id AND
    role_action_def.account_id = {account_id} AND
    record_def.account_id = {account_id} AND
    def_id = {def_id}'''

4
f-string จะทำงานอย่างไรถ้าฉันต้องการบันทึกผลลัพธ์ของสตริงหลายบรรทัดและไม่มีแท็บ / ช่องว่างด้านซ้ายปรากฏขึ้น
kuanb

7
ยังคงมีความเสี่ยงต่อการฉีด SQL
เทรนตัน

19

ตัวอย่างเช่น:

sql = ("select field1, field2, field3, field4 "
       "from table "
       "where condition1={} "
       "and condition2={}").format(1, 2)

Output: 'select field1, field2, field3, field4 from table 
         where condition1=1 and condition2=2'

ถ้าค่าของเงื่อนไขควรเป็นสตริงคุณสามารถทำสิ่งนี้:

sql = ("select field1, field2, field3, field4 "
       "from table "
       "where condition1='{0}' "
       "and condition2='{1}'").format('2016-10-12', '2017-10-12')

Output: "select field1, field2, field3, field4 from table where
         condition1='2016-10-12' and condition2='2017-10-12'"

13

ฉันพบtextwrap.dedentที่ดีที่สุดสำหรับสายยาวตามที่อธิบายไว้ที่นี่ :

def create_snippet():
    code_snippet = textwrap.dedent("""\
        int main(int argc, char* argv[]) {
            return 0;
        }
    """)
    do_something(code_snippet)

1
ฉันชอบเครื่องหมายทับสีดำที่ป้องกันบรรทัดใหม่อัตโนมัติขอบคุณมาก!
zyy

12

คนอื่น ๆ ได้พูดถึงวิธีการในวงเล็บแล้ว แต่ฉันต้องการที่จะเพิ่มว่าในวงเล็บมีความคิดเห็นแบบอินไลน์ได้รับอนุญาต

แสดงความคิดเห็นในแต่ละส่วน:

nursery_rhyme = (
    'Mary had a little lamb,'          # Comments are great!
    'its fleece was white as snow.'
    'And everywhere that Mary went,'
    'her sheep would surely go.'       # What a pesky sheep.
)

ไม่อนุญาตให้แสดงความคิดเห็นหลังจากดำเนินการต่อ:

เมื่อใช้เครื่องหมายทับขวาของบรรทัดแบ็กสแลช ( \) จะไม่อนุญาตให้ใส่ความคิดเห็น คุณจะได้รับSyntaxError: unexpected character after line continuation characterข้อผิดพลาด

nursery_rhyme = 'Mary had a little lamb,' \  # These comments
    'its fleece was white as snow.'       \  # are invalid!
    'And everywhere that Mary went,'      \
    'her sheep would surely go.'
# => SyntaxError: unexpected character after line continuation character

ความคิดเห็นที่ดีขึ้นสำหรับสตริง Regex:

ขึ้นอยู่กับตัวอย่างจากhttps://docs.python.org/3/library/re.html#re.VERBOSE ,

a = re.compile(
    r'\d+'  # the integral part
    r'\.'   # the decimal point
    r'\d*'  # some fractional digits
)
# Using VERBOSE flag, IDE usually can't syntax highight the string comment.
a = re.compile(r"""\d +  # the integral part
                   \.    # the decimal point
                   \d *  # some fractional digits""", re.X)

10

ฉันเองพบว่าต่อไปนี้เป็นวิธีที่ดีที่สุด (ง่ายปลอดภัยและ Pythonic) เพื่อเขียนแบบสอบถาม SQL ดิบใน Python โดยเฉพาะเมื่อใช้โมดูล sqlite3 ของ Python :

query = '''
    SELECT
        action.descr as action,
        role.id as role_id,
        role.descr as role
    FROM
        public.role_action_def,
        public.role,
        public.record_def,
        public.action
    WHERE
        role.id = role_action_def.role_id
        AND record_def.id = role_action_def.def_id
        AND action.id = role_action_def.action_id
        AND role_action_def.account_id = ?
        AND record_def.account_id = ?
        AND def_id = ?
'''
vars = (account_id, account_id, def_id)   # a tuple of query variables
cursor.execute(query, vars)   # using Python's sqlite3 module

ข้อดี

  • รหัสเรียบร้อยและเรียบง่าย (Pythonic!)
  • ปลอดภัยจากการฉีด SQL
  • เข้ากันได้กับทั้ง Python 2 และ Python 3 (เป็น Pythonic หลังจากทั้งหมด)
  • ไม่ต้องต่อสตริงเข้าด้วยกัน
  • ไม่จำเป็นต้องตรวจสอบให้แน่ใจว่าอักขระที่เหมาะสมที่สุดของแต่ละบรรทัดคือช่องว่าง

จุดด้อย

  • เนื่องจากตัวแปรในแบบสอบถามถูกแทนที่ด้วย?ตัวยึดตำแหน่งมันอาจกลายเป็นเรื่องยากเล็กน้อยที่จะติดตามว่า?จะแทนที่ด้วยตัวแปร Python ใดเมื่อมีจำนวนมากในแบบสอบถาม

หมายเหตุผมไม่ได้ทดสอบนี้ แต่คุณอาจจะสามารถหลีกเลี่ยงความสับสนเครื่องหมายคำถามโดยการแทนที่พวกเขาด้วย "{0} {1} {2}" cursor.execute(query.format(vars))ในสถานที่ที่เกี่ยวข้องและแล้วเปลี่ยนเส้นสุดท้ายที่จะ ที่ควรดูแล "แย้ง" ของคุณเท่านั้น (ฉันหวังว่า)
Ben

ใช่การใช้formatจะดี แต่ฉันไม่แน่ใจว่าสตริงการสืบค้นที่จัดรูปแบบแล้วจะปลอดภัยจากการฉีด SQL หรือไม่
Faheel

ใช่นั่นคือจุดยุติธรรมและแน่นอนอาจได้รับบิตหากิน บางทีการทดสอบกับบางสิ่งที่อาจจะฉลาดพอสมควร ... ไม่ต้องสงสัยเลยว่าคอมพ์ วิทย์ อันเดอร์กราวด์จะเดินผ่านไปเร็วพอ ;)
Ben

2
@Ben ถ้าคุณcursor.execute(query.format(vars))ไม่ได้กำไรจากคำสั่งที่เตรียมไว้อีกต่อไปดังนั้นคุณจึงมีความเสี่ยงต่อปัญหาหลาย ๆ อย่างเริ่มจากข้อเท็จจริงที่ว่าหากพารามิเตอร์ไม่ใช่แค่ตัวเลขคุณต้องใส่เครื่องหมายอัญประกาศเป็นคู่ในแบบสอบถาม SQL
Patrick Mevzek

4

ฉันมักจะใช้สิ่งนี้:

text = '''
    This string was typed to be a demo
    on how could we write a multi-line
    text in Python.
'''

หากคุณต้องการลบช่องว่างที่น่ารำคาญในแต่ละบรรทัดคุณสามารถทำได้ดังนี้:

text = '\n'.join(line.lstrip() for line in text.splitlines())

2
ดูtextwrap.dedentฟังก์ชั่นของ Python ซึ่งอยู่ในไลบรารี่มาตรฐานมันมีฟังก์ชั่นที่คุณต้องการ
bjd2385

@ bjd2385: inspect.cleandocน้อยกว่าเล็กน้อย (จู้จี้จุกจิกน้อยกว่าเกี่ยวกับข้อความที่ปรากฏในบรรทัดเดียวกันกับคำพูดที่เปิดไม่ต้องใช้ตัวอักษรต่อเนื่องสายที่ชัดเจน)
ShadowRanger

3

รหัสที่แท้จริงของคุณไม่ควรทำงานคุณจะหายไปช่องว่างในตอนท้ายของ "เส้น" (เช่น: role.descr as roleFROM...)

มี triplequotes สำหรับสตริงหลายบรรทัด:

string = """line
  line2
  line3"""

มันจะมีตัวแบ่งบรรทัดและช่องว่างเพิ่มเติม แต่สำหรับ SQL ที่ไม่ใช่ปัญหา


3

นอกจากนี้คุณยังสามารถวางคำสั่ง sql ในไฟล์แยกaction.sqlและโหลดในไฟล์ py ด้วย

with open('action.sql') as f:
   query = f.read()

ดังนั้นคำสั่ง sql จะถูกแยกออกจากรหัสไพ ธ อน หากมีพารามิเตอร์ในคำสั่ง sql ซึ่งจำเป็นต้องเติมจากไพ ธ อนคุณสามารถใช้การจัดรูปแบบสตริง (เช่น% s หรือ {field})


3

"À la" วิธีScala (แต่ฉันคิดว่าเป็นวิธีที่ pythonic มากที่สุดตามความต้องการของ OQ):

description = """
            | The intention of this module is to provide a method to 
            | pass meta information in markdown_ header files for 
            | using it in jinja_ templates. 
            | 
            | Also, to provide a method to use markdown files as jinja 
            | templates. Maybe you prefer to see the code than 
            | to install it.""".replace('\n            | \n','\n').replace('            | ',' ')

หากคุณต้องการ str สุดท้ายโดยไม่ต้องข้ามบรรทัดเพียงใส่\nที่จุดเริ่มต้นของอาร์กิวเมนต์แรกของการแทนที่ที่สอง:

.replace('\n            | ',' ')`.

หมายเหตุ: เส้นสีขาวระหว่าง "... เทมเพลต" และ "นอกจากนี้ ..." |ต้องมีช่องว่างหลังจากที่


3

tl; dr: ใช้"""\และ"""เพื่อตัดสตริงเช่นเดียวกับใน

string = """\
This is a long string
spanning multiple lines.
"""

จากเอกสารไพ ธ อนอย่างเป็นทางการ :

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

print("""\
Usage: thingy [OPTIONS]
     -h                        Display this usage message
     -H hostname               Hostname to connect to
""")

สร้างเอาต์พุตต่อไปนี้ (โปรดทราบว่าบรรทัดใหม่เริ่มต้นไม่รวมอยู่):

Usage: thingy [OPTIONS]
     -h                        Display this usage message
     -H hostname               Hostname to connect to

2

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

"message": f'you have successfully inquired about '
           f'{enquiring_property.title} Property owned by '
           f'{enquiring_property.client}'

1

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

# Utility function to recursively resolve SQL statements.
# CAUTION: Use this function carefully, Pass correct SQL parameters {},
# TODO: This should never happen but check for infinite loops
def resolveSQL(sql_seed, sqlparams):
    sql = sql_seed % (sqlparams)
    if sql == sql_seed:
        return ' '.join([x.strip() for x in sql.split()])
    else:
        return resolveSQL(sql, sqlparams)

PS: ดูไลบรารี่ python-sqlparse ที่น่าประทับใจเพื่อพิมพ์คิวรี่ SQL หากจำเป็น http://sqlparse.readthedocs.org/en/latest/api/#sqlparse.format


"ฟังก์ชั่นวนซ้ำ" นั้นไม่เรียกว่าแลมบ์ดา?
m3nda

1

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

def some_method():

    long_string = """
a presumptuous long string 
which looks a bit nicer 
in a text editor when
written over multiple lines
""".strip('\n').replace('\n', ' ')

    return long_string 

1

ใช้เครื่องหมายอัญประกาศ ผู้คนมักใช้สิ่งเหล่านี้เพื่อสร้างเอกสารในตอนเริ่มต้นของโปรแกรมเพื่ออธิบายวัตถุประสงค์และข้อมูลอื่น ๆ ที่เกี่ยวข้องกับการสร้าง ผู้คนยังใช้สิ่งเหล่านี้ในฟังก์ชั่นเพื่ออธิบายวัตถุประสงค์และการใช้ฟังก์ชั่น ตัวอย่าง:

'''
Filename: practice.py
File creator: me
File purpose: explain triple quotes
'''


def example():
    """This prints a string that occupies multiple lines!!"""
    print("""
    This
    is 
    a multi-line
    string!
    """)

0

ฉันชอบวิธีการนี้เพราะสิทธิ์ในการอ่าน ในกรณีที่เรามีสายยาวไม่มีทาง! ขึ้นอยู่กับระดับของการเยื้องที่คุณอยู่และยัง จำกัด อยู่ที่ 80 อักขระต่อบรรทัด ... ดี ... ไม่จำเป็นต้องพูดอะไรอีก ในมุมมองของฉันคู่มือสไตล์หลามยังคงคลุมเครือมาก ฉันใช้วิธีการ @Eero Aaltonen เพราะให้สิทธิ์การอ่านและการใช้สามัญสำนึก ฉันเข้าใจว่าไกด์นำเที่ยวควรช่วยเราและไม่ทำให้ชีวิตเรายุ่งเหยิง ขอบคุณ!

class ClassName():
    def method_name():
        if condition_0:
            if condition_1:
                if condition_2:
                    some_variable_0 =\
"""
some_js_func_call(
    undefined, 
    {
        'some_attr_0': 'value_0', 
        'some_attr_1': 'value_1', 
        'some_attr_2': '""" + some_variable_1 + """'
    }, 
    undefined, 
    undefined, 
    true
)
"""

0

จากเอกสารไพ ธ อนอย่างเป็นทางการ :

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

print("""\
Usage: thingy [OPTIONS]
     -h                        Display this usage message
     -H hostname               Hostname to connect to
""")

สร้างเอาต์พุตต่อไปนี้ (โปรดทราบว่าบรรทัดใหม่เริ่มต้นไม่รวมอยู่):


0

สำหรับการกำหนดสตริงที่มีความยาวภายใน dict, รักษาบรรทัดใหม่ แต่เว้นช่องว่าง , ฉันสิ้นสุดการกำหนดสตริงในค่าคงที่เช่นนี้:

LONG_STRING = \
"""
This is a long sting
that contains newlines.
The newlines are important.
"""

my_dict = {
   'foo': 'bar',
   'string': LONG_STRING
}

0

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

_str = ' '.join('''Lorem ipsum dolor sit amet, consectetur adipiscing 
        elit, sed do eiusmod tempor incididunt ut labore et dolore 
        magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation 
        ullamco laboris nisi ut aliquip ex ea commodo.'''.split())

เอาท์พุท:

'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo.'

ในส่วนที่เกี่ยวกับคำถามของ OP ที่เกี่ยวข้องกับแบบสอบถาม SQL คำตอบด้านล่างนั้นไม่คำนึงถึงความถูกต้องของวิธีการนี้ในการสร้างแบบสอบถาม SQL และมุ่งเน้นเฉพาะการสร้างสตริงยาวในวิธีที่อ่านได้และสวยงามโดยไม่ต้องนำเข้าเพิ่มเติม นอกจากนี้ยังไม่คำนึงถึงภาระการคำนวณที่เกี่ยวข้อง

การใช้คำพูดที่สามที่เราสร้างสายยาวและสามารถอ่านได้ซึ่งเราก็เลิกลงในรายการที่ใช้จึงปอกช่องว่างและจากนั้นเข้าร่วมได้กลับมารวมกันด้วยsplit() ' '.join()ในที่สุดเราก็แทรกตัวแปรโดยใช้format()คำสั่ง:

account_id = 123
def_id = 321

_str = '''
    SELECT action.descr AS "action", role.id AS role_id, role.descr AS role 
    FROM public.role_action_def, public.role, public.record_def, public.action
    WHERE role.id = role_action_def.role_id 
    AND record_def.id = role_action_def.def_id 
    AND' action.id = role_action_def.action_id 
    AND role_action_def.account_id = {} 
    AND record_def.account_id = {} 
    AND def_id = {}
    '''

query = ' '.join(_str.split()).format(account_id, account_id, def_id)

ผลิต:

SELECT action.descr AS "action", role.id AS role_id, role.descr AS role FROM public.role_action_def, public.role, public.record_def, public.action WHERE role.id = role_action_def.role_id AND record_def.id = role_action_def.def_id AND\' action.id = role_action_def.action_id AND role_action_def.account_id = 123 AND record_def.account_id=123 AND def_id=321

แก้ไข: วิธีนี้ไม่สอดคล้องกับ PEP8 แต่ฉันพบว่ามีประโยชน์ในบางครั้ง


-7

โดยทั่วไปฉันใช้listและjoinสำหรับความคิดเห็น / สตริงหลายบรรทัด

lines = list()
lines.append('SELECT action.enter code here descr as "action", ')
lines.append('role.id as role_id,')
lines.append('role.descr as role')
lines.append('FROM ')
lines.append('public.role_action_def,')
lines.append('public.role,')
lines.append('public.record_def, ')
lines.append('public.action')
query = " ".join(lines)

คุณสามารถใช้สตริงใดก็ได้เพื่อเข้าร่วมองค์ประกอบรายการทั้งหมดเช่น ' \n' (ขึ้นบรรทัดใหม่) หรือ ' ,' (จุลภาค) หรือ ' ' (ช่องว่าง)

ไชโย .. !!


1
ทำไมอย่างน้อยคุณจะไม่ใช้ตัวอักษรแถวลำดับ?
Alexander - Reinstate Monica


ฉันคิดว่างานนี้ แต่คุณควรคิดถึงประสิทธิภาพและความสามารถในการอ่าน ...
Petro
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.