วิธีการแบ่งวิธีการโยงใน Python?


139

ฉันมีบรรทัดของรหัสต่อไปนี้ (ไม่ตำหนิสำหรับการตั้งชื่อการประชุมพวกเขาไม่ใช่ของฉัน):

subkeyword = Session.query(
    Subkeyword.subkeyword_id, Subkeyword.subkeyword_word
).filter_by(
    subkeyword_company_id=self.e_company_id
).filter_by(
    subkeyword_word=subkeyword_word
).filter_by(
    subkeyword_active=True
).one()

ฉันไม่ชอบว่ามันจะเป็นอย่างไร (ไม่สามารถอ่านได้มากเกินไป) แต่ฉันไม่มีความคิดที่ดีกว่าในการ จำกัด บรรทัดที่ 79 อักขระในสถานการณ์นี้ มีวิธีที่ดีกว่าในการทำลายมัน (ดีกว่าโดยไม่ใช้แบ็กสแลช)?

คำตอบ:


257

คุณสามารถใช้วงเล็บเพิ่มเติมได้:

subkeyword = (
        Session.query(Subkeyword.subkeyword_id, Subkeyword.subkeyword_word)
        .filter_by(subkeyword_company_id=self.e_company_id)
        .filter_by(subkeyword_word=subkeyword_word)
        .filter_by(subkeyword_active=True)
        .one()
    )

ฉันก็ชอบมันที่สุด ไม่ต้องเพิ่มรหัสเพิ่มเติมและมันจะไม่มีแบ็กสแลช
Juliusz Gonera

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

4
ในความคิดของฉันเยื้องคู่มีประโยชน์ที่นี่เพราะมันแตกต่างจากสายตาเยื้องบล็อกปกติ เมื่อล้อมรอบด้วยรหัสอื่น ๆ สิ่งนี้ทำให้ชัดเจนยิ่งขึ้นว่าเป็นเส้นเดี่ยวที่ล้อมรอบ
sth

1
คำตอบที่ดีที่สุดในแง่ของการใช้ parens ดังที่ได้กล่าวไว้ในข้อคิดเห็นโดย Shanimal ในคำตอบอื่นการใช้ความต่อเนื่องของบรรทัดโดยนัยผ่านวงเล็บคือPEP 8 เป็นที่ต้องการเทียบกับอักขระต่อเนื่อง ``
kevlarr

ฉันชอบแบ็กสแลช วงเล็บไม่ใช่คำใบ้สำหรับทุกสถานการณ์ เป็นตัวอย่างมันไม่ทำงานกับผู้ประกอบการที่ได้รับมอบหมาย ลองนึกภาพคุณต้องการที่จะทำลายสายในห่วงโซ่นี้:foo.set_default('bar', {}).set_default('spam', {}).set_default('eggs', {})['lol'] = 'yeah'
Loutre

56

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

subkeyword = Session.query(Subkeyword.subkeyword_id, Subkeyword.subkeyword_word) \
                    .filter_by(subkeyword_company_id=self.e_company_id)          \
                    .filter_by(subkeyword_word=subkeyword_word)                  \
                    .filter_by(subkeyword_active=True)                           \
                    .one()

PEP 8 ตั้งใจจะตีความด้วยการวัดสามัญสำนึกและเป็นตาสำหรับทั้งการใช้งานและความสวยงาม ฝ่าฝืนแนวทาง PEP 8 อย่างมีความสุขที่ส่งผลให้เกิดรหัสที่น่าเกลียดหรือยากต่อการอ่าน

ที่ถูกกล่าวว่าหากคุณพบว่าตัวเองมักจะขัดแย้งกับ PEP 8 อาจเป็นสัญญาณว่ามีปัญหาการอ่านที่อยู่เหนือที่คุณเลือกของช่องว่าง :-)


2
+1 ในแบ็กสแลชและจัดแนวตัวกรองที่ถูกล่ามโซ่ในกรณีนี้โดยเฉพาะ สถานการณ์เช่นนี้เกิดขึ้นใน Django เป็นอย่างดีและสามารถอ่านได้มากที่สุดด้วยวิธีนี้ - แต่ในใด ๆสถานการณ์อื่น ๆ ที่ฉันรู้สึกเหมือนวลีวงเล็บจะดีกว่า (ไม่ประสบจาก "จะมีช่องว่างหลังจากทับขวาของฉันได้อย่างไร" ปัญหา) ที่กล่าวว่าการใช้เครื่องหมายวงเล็บในประโยคเพื่อให้ได้ผลเหมือนกัน - แต่มันทำให้คุณอยู่ในโหมดการอ่าน Lisp ในช่วงกลางของการอ่าน Python ซึ่งฉันพบว่าสั่นสะเทือน
zxq9

11
ฉันไม่เห็นวิธีการแก้ปัญหานี้จะดีกว่าที่จะรับมือ "เป็นวิธีการที่ชื่อได้นานขึ้นและเป็นวิธีการเริ่มต้นการขัดแย้ง" กว่า "ห่อใน parens ภายนอก" หรือ "ตัวแบ่งบรรทัดหลังจากแต่ละ paren เปิดและก่อนแต่ละ paren ปิด" การแก้ปัญหา ในความเป็นจริงมันแย่กว่าที่จะจัดการสิ่งนั้นเนื่องจาก (อย่างน้อยดังที่แสดงไว้ที่นี่) จึงต้องมีการเยื้องที่ลึกกว่าสำหรับทุกบรรทัดที่แขวน
คาร์ลเมเยอร์

1
เยื้องมากเกินไปสำหรับการเรียกตัวกรอง หนึ่งแท็บหรือ 4 ช่องว่างน่าจะเพียงพอที่นี่ และการจัดตำแหน่งของ `` ... คุณกดปุ่ม space นั้นค้างไว้กี่วินาที? โดยทั่วไปแล้วฉันต่อสู้กับทุกวิถีทางที่คุณต้องใช้กุญแจอวกาศนั้นเหมือนไม่มีวันพรุ่งนี้
Zelphir Kaltstahl

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

อ้างอิงมากถึง PEP8! เป็นปัญหาที่น่ารำคาญที่นี่กับการจัดตำแหน่งทุก.filterสายคือว่าถ้าคุณเปลี่ยนsubkeywordไปsub_keywordตอนนี้คุณมีการแก้ไขการเยื้องของบรรทัดเดียวทุกเพียงเพราะคุณเปลี่ยนชื่อตัวแปร ไม่เมื่อรูปแบบที่ดีจริงเป็นอุปสรรคต่อการบำรุงรักษา ...
kevlarr

15

ทางเลือกส่วนตัวของฉันจะเป็น:

subkeyword = Session.query (
    Subkeyword.subkeyword_id,
    Subkeyword.subkeyword_word,
) .filter_by (
    subkeyword_company_id = self.e_company_id,
    subkeyword_word = subkeyword_word,
    subkeyword_active = True,
).หนึ่ง()

1
ฉันยอมรับว่ามีหลายพารามิเตอร์ที่ถูกส่งผ่าน แต่มันดูน่าเกลียดเมื่อพารามิเตอร์ 0 หรือ 1 เป็นเรื่องธรรมดา ตัวอย่างเช่น: gist.github.com/andybak/b23b6ad9a68c7e1b794d
Andy Baker

1
ใช่สไตล์นั้นมีเคสที่แย่ลง (เช่นสไตล์ใดก็ได้) ฉันจะไม่ทำลายการเปิดกว้างทั้งหมด ไม่มีสิ่งใดที่ทำให้ฉันมีความสุข แต่นี่คือบางกรณี: gist.github.com/pkoch/8098c76614765750f769
pkoch

12

เพียงเก็บผลลัพธ์ / วัตถุขั้นกลางแล้วเรียกใช้วิธีถัดไปที่อยู่ในนั้น

q = Session.query(Subkeyword.subkeyword_id, Subkeyword.subkeyword_word)
q = q.filter_by(subkeyword_company_id=self.e_company_id)
q = q.filter_by(subkeyword_word=subkeyword_word)
q = q.filter_by(subkeyword_active=True)
subkeyword = q.one()

10
สิ่งนี้ทำงานได้ดีสำหรับบางอย่างเช่นข้อความค้นหา แต่เป็นรูปแบบทั่วไปฉันไม่แน่ใจ ตัวอย่างเช่นเมื่อผูกมัดในสวยซุปเหมือนteam_members = soup.find(class_='section team').find_all('ul').find_all('li'), ค่าตอบแทนจากแต่ละ.find(...)โทรไม่พอดีกับความหมายของteam_membersเลย
Taylor Edmiston

1
@TaylorEdmiston คุณสามารถมีชื่อที่แตกต่างกันสำหรับผลลัพธ์บางส่วนของหลักสูตร สิ่งที่ต้องการและsection = soup.find(class_='section team') team_members = section.find_all('ul').find_all('li')
Jeyekomon

4

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


4

มันเป็นวิธีการแก้ปัญหาที่แตกต่างจากที่อื่น ๆ แต่เป็นที่ชื่นชอบของฉันเพราะมันนำไปสู่

base = [Subkeyword.subkeyword_id, Subkeyword_word]
search = {
    'subkeyword_company_id':self.e_company_id,
    'subkeyword_word':subkeyword_word,
    'subkeyword_active':True,
    }
subkeyword = Session.query(*base).filter_by(**search).one()

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


1

ดูเหมือนว่าคุณใช้ SQLAlchemy หากเป็นจริงsqlalchemy.orm.query.Query.filter_by()เมธอดจะรับอาร์กิวเมนต์คำหลักหลายคำดังนั้นคุณสามารถเขียนดังนี้:

subkeyword = Session.query(Subkeyword.subkeyword_id,
                           Subkeyword.subkeyword_word) \
                    .filter_by(subkeyword_company_id=self.e_company_id,
                               subkeyword_word=subkeyword_word,
                               subkeyword_active=True) \
                    .one()

แต่มันจะดีกว่า:

subkeyword = Session.query(Subkeyword.subkeyword_id,
                           Subkeyword.subkeyword_word)
subkeyword = subkeyword.filter_by(subkeyword_company_id=self.e_company_id,
                                  subkeyword_word=subkeyword_word,
                                  subkeyword_active=True)
subkeuword = subkeyword.one()

+1 สำหรับคำแนะนำ SQLAlchemy filter_by () เป็นเรื่องที่ดีสำหรับตัวอย่างนี้ แต่ฉันมักจะใช้ตัวกรอง () แทนซึ่งยอมรับเงื่อนไขเพียง 1 ข้อเท่านั้น
Juliusz Gonera

1

ฉันชอบเยื้องอาร์กิวเมนต์โดยสองบล็อกและคำสั่งโดยหนึ่งบล็อกเช่นนี้

for image_pathname in image_directory.iterdir():
    image = cv2.imread(str(image_pathname))
    input_image = np.resize(
            image, (height, width, 3)
        ).transpose((2,0,1)).reshape(1, 3, height, width)
    net.forward_all(data=input_image)
    segmentation_index = net.blobs[
            'argmax'
        ].data.squeeze().transpose(1,2,0).astype(np.uint8)
    segmentation = np.empty(segmentation_index.shape, dtype=np.uint8)
    cv2.LUT(segmentation_index, label_colours, segmentation)
    prediction_pathname = prediction_directory / image_pathname.name
    cv2.imwrite(str(prediction_pathname), segmentation)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.