ทำไมอัฒภาคจึงอนุญาตให้ใช้ในตัวอย่างงูหลามนี้


166

Python ไม่รับประกันการใช้เครื่องหมายอัฒภาคเพื่อสิ้นสุดข้อความสั่ง เหตุใดจึงอนุญาต (ด้านล่าง) นี้

import pdb; pdb.set_trace()

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

ฮ่า ๆ ฉันมาถึงคำถามนี้จากเว็บไซต์เดียวกัน: realpython.com/python-debugging-pdb
mackycheese21

คำตอบ:


226

Python ไม่ต้องการเซมิโคลอนเพื่อยกเลิกคำสั่ง Semi colons สามารถใช้เพื่อกำหนดขอบเขตคำสั่งหากคุณต้องการใส่หลาย statement ในบรรทัดเดียวกัน

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


16
มันมีประโยชน์สำหรับสิ่งต่าง ๆ เช่นtimeit a = 5; a*a
endolith

13
ดูเหมือนว่ามีประโยชน์สำหรับคำสั่ง exec เช่น exec ('สำหรับใน [1,2,3]: print a; print a + 1')
Phil C

76
ฉันมาที่ Python ด้วยพื้นหลังของ C, Obj-C, Javascript, PHP ฉันมักจะใส่เทอร์มินัล (ไร้ประโยชน์); ในตอนท้ายของบรรทัด แต่โชคดีที่ Python ให้อภัยฉัน
เปาโล

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

5
@endolith timeitหมายความว่าอย่างไร a = 2; a*aไม่มีประโยชน์เนื่องจากaยังคงเป็น 2; มันจะต้องเป็นa = 2; a *= a
Nearoo

59

http://docs.python.org/reference/compound_stmts.html

คำสั่งผสมประกอบด้วย 'อนุประโยค' หนึ่งรายการหรือมากกว่า ส่วนคำสั่งประกอบด้วยส่วนหัวและ 'ชุด' ส่วนหัวของ clause ของข้อความสั่งผสมเฉพาะทั้งหมดอยู่ในระดับการเยื้องเดียวกัน แต่ละส่วนหัวของส่วนคำสั่งเริ่มต้นด้วยคำหลักที่ระบุไม่ซ้ำกันและลงท้ายด้วยลำไส้ใหญ่ ชุดคือกลุ่มของคำสั่งควบคุมโดยประโยค ชุดสามารถเป็นคำสั่งง่าย ๆ ที่คั่นด้วยเครื่องหมายอัฒภาคอย่างน้อยหนึ่งรายการในบรรทัดเดียวกันกับส่วนหัวตามหลังเครื่องหมายจุดคู่ของส่วนหัวหรืออาจเป็นหนึ่งหรือมากกว่าหนึ่งย่อหน้าในบรรทัดถัดไป เฉพาะชุดรูปแบบหลังเท่านั้นที่สามารถมีชุดคำสั่งซ้อนกัน ต่อไปนี้เป็นสิ่งผิดกฎหมายส่วนใหญ่เป็นเพราะมันจะไม่ชัดเจนซึ่งถ้าข้ออื่นต่อไปนี้ข้อจะอยู่

if test1: if test2: print x

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

if x < y < z: print x; print y; print z 

สรุป:

compound_stmt ::=  if_stmt
                   | while_stmt
                   | for_stmt
                   | try_stmt
                   | with_stmt
                   | funcdef
                   | classdef
                   | decorated
suite         ::=  stmt_list NEWLINE | NEWLINE INDENT statement+ DEDENT
statement     ::=  stmt_list NEWLINE | compound_stmt
stmt_list     ::=  simple_stmt (";" simple_stmt)* [";"]

4
ไม่ทราบเกี่ยวกับลำดับความสำคัญของอัฒภาคที่น้อยกว่าลำไส้ใหญ่หลังจากถ้า ขอขอบคุณ!
gaborous

3
@gaborous ฉันรู้สึกถึงความคิดเห็นของคุณที่ไม่ชัดเจนพอที่จะทำให้ฉันคิดว่าคุณจะหมายถึงวิธีอื่น ดังนั้นเพื่อชี้แจงฉันอยากจะแนะนำให้ผู้อ่านคนอื่นยึดติดกับวลีอย่างเป็นทางการ: ในif cond: stmt1; stmt2; stmt3ตัวอย่างนั้นคำสั่งทั้งหมดหรือไม่มีการดำเนินการ "
RayLuo

ใช่นั่นคือสิ่งที่ฉันหมายถึงถ้าลำดับความสำคัญน้อยกว่า lexer จะไม่สามารถออกจากบล็อกหลัก (โคลอน) จนกว่าคำสั่งอัฒภาคทั้งหมดจะถูกดำเนินการ นั่นไม่ใช่สิ่งที่ชัดเจนจริงๆ
gaborous

38

Python ใช้;เป็นตัวคั่นไม่ใช่ตัวยุติ คุณสามารถใช้พวกมันที่ท้ายบรรทัดซึ่งทำให้ดูเหมือนเป็น statement terminator แต่นี่ถูกกฎหมายเพราะคำสั่ง blank เป็น legal ใน Python - บรรทัดที่มีเซมิโคลอนที่ท้ายคือสอง statement ที่สอง หนึ่งที่ว่างเปล่า


28
หากคุณใส่เครื่องหมายอัฒภาคสองครั้งที่ส่วนท้าย (หรือที่ใดก็ได้) คุณจะได้รับ SyntaxError ดังนั้นดูเหมือนว่างบที่ว่างเปล่าจะไม่ถูกกฎหมายทั้งหมด
Cucu

10
อาจเป็นไปได้ว่ามันมีเหตุผลเดียวกับรายการ tuples, dicts ที่มีเครื่องหมายจุลภาคต่อท้ายถูกต้องและเช่นเดียวกับคู่หูที่ถูกตัด (เช่น [1,2,3] == [1,2,3,]) แต่พวกเขาไม่สามารถมีเครื่องหมายจุลภาคคู่ . ดังนั้นโดยทั่วไปแล้ว Python นั้นมี "ตัวลบเปล่าที่ต่อท้าย" ซึ่งโดยวิธีการที่ชัดเจนจากนี้:stmt_list ::= simple_stmt (";" simple_stmt)* [";"]
Cucu

@Cucu คุณพูดถูก คุณไม่สามารถเริ่มต้นบรรทัดด้วยเครื่องหมายอัฒภาคหรือเริ่มรายการนิพจน์ด้วยเครื่องหมายจุลภาค ดังนั้นจึงแม่นยำกว่าที่จะบอกว่าเครื่องหมายอัฒภาคและเครื่องหมายจุลภาคเป็นตัวคั่นและตัวเลือกเทอร์มินัล
wjandrea

29

อัฒภาคในล่าม

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

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

ใช้การแสดงออกสำหรับผลข้างเคียง

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

ในกรณีนี้คุณ (อาจ) ไม่ได้ต้องการที่จะเห็นหน้าจอของreprของmatplotlibวัตถุที่บางครั้งกลับโดยโทรไปยังmatplotlibฟังก์ชั่นและใน IPython อย่างน้อยหนึ่งในความเป็นไปได้ที่คุณมีคือการผนวกอัฒภาคไปมากเกินไปคำสั่งverboseตอนนี้ IPython เห็นบรรทัดอินพุตที่ประกอบด้วยสองนิพจน์การmatplotlibเรียกใช้และคำสั่งที่เป็นโมฆะดังนั้นค่าของนิพจน์ผสมคือNoneอะไรและไม่มีอะไรถูกพิมพ์ไปที่หน้าจอโดยล่ามมอบหมายเช่นใน_ = plot(...)แต่ฉันพบว่าน่ารำคาญกว่าเล็กน้อย)

คำพูดส่วนตัว

IMHO การใช้เครื่องหมายอัฒภาคเพื่อยับยั้งเอาต์พุตที่ไม่ต้องการในล่ามนั้นมีความเกี่ยวข้องมากขึ้นหลังจากการเปิดตัวโน้ตบุ๊ค IPyton ที่อนุญาตให้บันทึกอินพุตและเอาต์พุตรวมถึงกราฟิกเอาต์พุตของเซสชันล่ามสำหรับเอกสารและการนำมาใช้ซ้ำในที่สุด .


ฉันเห็นขอบคุณสำหรับการแบ่งปัน! นี่เพิ่งแก้ไขปัญหาของฉันได้อย่างแน่นอนโดยที่เครื่องหมายอัฒภาคสามารถป้องกันการตอบโต้ด้วย matplotlib ในสมุดบันทึก ipython ได้
Napitupulu Jon

นี่เป็นฟีเจอร์เดียวของ IPython และไม่ใช่คำสั่ง null ซึ่งเป็นเพียงไวยากรณ์พิเศษ
wjandrea

@wjandrea คุณถูกต้องมันเป็นเพียงipython... ฉันได้แก้ไขคำตอบของคุณเพื่อสะท้อนความคิดเห็นของคุณ
gboffi

คำตอบนี้ควรจะสูงกว่าที่ฉันคิดว่ามันได้กลายเป็นกรณีที่ใช้บ่อยที่สุด (ด้วยการแพร่กระจายของโน๊ตบุ๊ค Jupyter + เวิร์กโฟลว์ IPython)
Josh Friedlander

12

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

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

python -c '<some python code>'แต่ก็เกือบจะเป็นความต้องการเมื่อคุณกำลังเรียกใช้งูหลามหนึ่งสมุทรจากเปลือกใช้ ที่นี่คุณไม่สามารถใช้การเยื้องเพื่อแยกคำสั่งดังนั้นถ้าหนึ่งซับของคุณเป็นสองซับจริงๆคุณจะต้องใช้เครื่องหมายอัฒภาค และถ้าคุณต้องการใช้ข้อโต้แย้งอื่นในหนึ่งซับของคุณคุณจะต้องนำเข้าsysเพื่อไปที่sys.argvซึ่งต้องมีimportคำสั่งแยกต่างหาก เช่น

python -c "import sys; print ' '.join(sorted(sys.argv[1:]))" 5 2 3 1 4
1 2 3 4 5

2
คุณสามารถใช้การเยื้องและการขึ้นบรรทัดใหม่เมื่อส่งคำสั่งผ่านpythonในเชลล์: เพียงแค่ขยายโค้ดที่ยกมาของคุณไปหลายบรรทัดหรือใช้ heredoc ยังคงล้มเหลวหากคุณต้องการให้เป็น "หนึ่งซับ" ;)
00dani

รวมถึงคุณลักษณะสำหรับคำตอบของรางด้วย-c
n611x007

6

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

บางครั้งความชัดเจนว่าเมื่อใดที่ข้อความหรือบล็อกนั้นมีประโยชน์มาก รหัสมาตรฐาน C มักจะอ่านดังนี้:

for(i=0; i<100; i++) {
    do something here;
    do another thing here;
}

continue doing things;

ที่ที่คุณใช้ช่องว่างเพื่อความกระจ่างมาก - และง่ายต่อการดูว่าลูปสิ้นสุดที่ไหน

Python อนุญาตให้คุณยุติด้วยเครื่องหมายอัฒภาค (เป็นทางเลือก) ตามที่ระบุไว้ข้างต้นนั่นไม่ได้หมายความว่ามีคำสั่งให้ดำเนินการตามด้วยคำสั่ง 'null' ตัวอย่างเช่น

print(x);
print(y);

เป็นเช่นเดียวกับ

print(x)
print(y)

หากคุณเชื่อว่าข้อความแรกมีคำสั่ง null ในตอนท้ายของแต่ละบรรทัดให้ลองทำตามที่แนะนำดังนี้

print(x);;

มันจะโยนข้อผิดพลาดทางไวยากรณ์

โดยส่วนตัวแล้วฉันพบเซมิโคลอนเพื่อให้โค้ดอ่านง่ายขึ้นเมื่อคุณมีการซ้อนและฟังก์ชันจำนวนมากที่มีอาร์กิวเมนต์จำนวนมากและ / หรือ args ที่มีชื่อยาว ดังนั้นสำหรับตาของฉันนี้ชัดเจนกว่าตัวเลือกอื่น ๆ :

if some_boolean_is_true:
    call_function(
        long_named_arg_1,
        long_named_arg_2,
        long_named_arg_3,
        long_named_arg_4
    );

สำหรับฉันแล้วมันช่วยให้คุณรู้ว่า ')' ปิดกั้น 'บล็อก' บางอันที่วิ่งผ่านหลายบรรทัด

โดยส่วนตัวแล้วฉันคิดว่ามีการทำตามแนวทางสไตล์ PEP, IDEs ที่บังคับใช้พวกเขาและความเชื่อที่ว่ามี 'วิธี Pythonic เพียงวิธีเดียวที่จะทำสิ่งต่างๆ' หากคุณเชื่อว่าอย่างหลังลองดูวิธีการจัดรูปแบบตัวเลข: ณ ตอนนี้ Python สนับสนุนวิธีที่แตกต่างกันสี่วิธี

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



5

คำพูดจาก " When Pythons Attack "

อย่ายุติงบทั้งหมดของคุณด้วยเซมิโคลอน เป็นเทคนิคทางกฎหมายที่จะทำสิ่งนี้ใน Python แต่ไร้ประโยชน์โดยสิ้นเชิงถ้าคุณไม่วางคำสั่งมากกว่าหนึ่งคำในบรรทัดเดียว (เช่น x = 1; y = 2; z = 3)


4
ทำไมx,y,z = 1,2,3ล่ะ
Anirban Nag 'tintinmj'

5
@ AnirbanNag'tintinmj 'ในกรณีนี้โดยเฉพาะฉันเชื่อว่าx, y, z = 1, 2, 3ช้ากว่าเพราะมันต้องใช้การสร้าง tuple แบบไปกลับโดยไม่จำเป็น (โดยวิธีการที่ฉันไม่คิดว่า @communistpancake แนะนำx=1; y=2; z=3รูปแบบแม้ว่าฉันคิดว่าเขา / เธอเป็นเพียงตัวอย่างให้เห็นว่าเครื่องหมายอัฒภาคเป็นตัวคั่นแทนที่จะเป็นตัวสิ้นสุด)
RayLuo

1
@AnirbanNag - เพราะนั่นจะเป็นตัวอย่างขยะของบรรทัดหลายข้อความ
cz

4

หลายงบในหนึ่งบรรทัดอาจรวมอัฒภาคเป็นตัวคั่น ตัวอย่างเช่น: http://docs.python.org/reference/compound_stmts.htmlในกรณีของคุณมันทำให้การแทรกจุดที่ง่ายต่อการเจาะเข้าสู่การดีบัก

นอกจากนี้ตามที่กล่าวไว้โดย Mark Lutz ในLearning Python Bookมันเป็นเรื่องถูกกฎหมายในทางเทคนิค (แม้ว่าจะไม่จำเป็นและน่ารำคาญ) ในการยกเลิกข้อความทั้งหมดของคุณด้วยเครื่องหมายอัฒภาค


3

Python อนุญาตให้คุณใช้เซมิโคลอนเพื่อแสดงถึงจุดสิ้นสุดของคำสั่งหากคุณรวมคำสั่งมากกว่าหนึ่งคำในบรรทัด


2

อัฒภาคสามารถใช้กับหนึ่งบรรทัดสองคำสั่งหรือมากกว่า ไม่จำเป็นต้องใช้ แต่ก็ไม่ได้ จำกัด

เซมิโคลอน (;) อนุญาตให้ใช้หลายคำสั่งในบรรทัดเดียวเนื่องจากคำสั่งทั้งสองไม่เริ่มบล็อกโค้ดใหม่

http://www.tutorialspoint.com/python/python_basic_syntax.htm


2

อัฒภาค (เช่นจุดเครื่องหมายจุลภาคและวงเล็บ) มีแนวโน้มที่จะก่อให้เกิดสงครามทางศาสนา ยังพวกเขา (หรือสัญลักษณ์ที่คล้ายกัน) มีประโยชน์ในภาษาการเขียนโปรแกรมด้วยเหตุผลต่างๆ

  • ในทางปฏิบัติ: ความสามารถในการใส่คำสั่งสั้น ๆ ที่เป็นแนวคิดร่วมกันในบรรทัดเดียวกัน ข้อความของโปรแกรมที่ดูเหมือนงูแคบ ๆ นั้นมีผลตรงกันข้ามกับสิ่งที่มีขึ้นโดยการขึ้นบรรทัดใหม่และการเยื้องซึ่งเป็นโครงสร้างการไฮไลต์

  • แนวคิด: การแยกข้อกังวลระหว่างวากยสัมพันธ์บริสุทธิ์ (ในกรณีนี้สำหรับลำดับของคำสั่ง) จากการนำเสนอ (เช่นการขึ้นบรรทัดใหม่) ในสมัยก่อนเรียกว่า "การพิมพ์แบบสวย"

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


1

ได้รับอนุญาตเพราะผู้เขียนตัดสินใจอนุญาต: https://docs.python.org/2/reference/simple_stmts.html

หากย้ายไปที่คำถามว่าทำไมผู้เขียนจึงตัดสินใจทำเช่นนั้นฉันเดาว่าเป็นเช่นนั้นเพราะอนุญาตให้มีการยกเลิกคำสั่งแบบกึ่งคอลัมน์อย่างน้อยที่สุดในภาษาต่อไปนี้: C ++, C, C #, R, Matlab, Perl, ...

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


1

เซมิโคลอน (";") เป็นสิ่งจำเป็นสำหรับการแยกคำสั่งภายในบล็อกเดียวกันเช่นถ้าเรามีรหัส C ต่อไปนี้:

if(a>b)
{
largest=a;  //here largest and count are integer variables
count+=1;
}

มันสามารถเขียนใน Python ในทั้งสองรูปแบบ:

if a>b:   
    largest=a
    count=count+1

หรือ

if a>b:    largest=a;count=count+1

ในตัวอย่างข้างต้นคุณสามารถมีจำนวนงบใด ๆ ภายใน ifบล็อกและสามารถคั่นด้วย ";" แทน.

หวังว่าไม่มีอะไรง่ายเหมือนคำอธิบายข้างต้น


0

เพิ่มความรู้มากมายที่นี่นี่
คือคำตอบที่เกี่ยวข้องกับห้องสมุด matplotlib

import numpy as np
import matplotlib as plt
%matplotlib notebook
linear_data = np.array([1, 2, 3, 4, 5, 6, 7, 8])
quadratic_data = linear_data**2
plt.figure()
xvals = range(len(linear_data))
plt.barh(xvals, linear_data, height = 0.3, color='b')
plt.barh(xvals, quadratic_data, height = 0.3, left=linear_data, color='r')

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

บางสิ่งบางอย่างเช่นนี้: การเปรียบเทียบ


3
นี่คือเฉพาะกับ IPython และไม่ได้ใช้กับ Python REPL มาตรฐาน
wjandrea

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