เหตุใดจึงต้องใส่วงเล็บในการพิมพ์โดยสมัครใจใน Python 2.7


98

ใน Python 2.7 ทั้งสองสิ่งต่อไปนี้จะทำเช่นเดียวกัน

print("Hello, World!") # Prints "Hello, World!"

print "Hello, World!" # Prints "Hello, World!"

อย่างไรก็ตามต่อไปนี้จะไม่

print("Hello,", "World!") # Prints the tuple: ("Hello,", "World!")

print "Hello,", "World!" # Prints the words "Hello, World!"

ในวงเล็บ Python 3.x บนprintเป็นสิ่งที่จำเป็นโดยพื้นฐานแล้วทำให้เป็นฟังก์ชัน แต่ใน 2.7 ทั้งสองจะทำงานกับผลลัพธ์ที่ต่างกัน ฉันควรรู้อะไรอีกบ้างprintใน Python 2.7


7
ใน Python 2.x printเป็นคำสั่งพิเศษไม่ใช่ฟังก์ชัน นี่คือสาเหตุที่ไม่สามารถใช้งานได้เช่น: lambda x: print xหมายเหตุที่(expr)ไม่ได้สร้าง Tuple (ผลลัพธ์เป็นexpr) แต่,ทำ

ฉันคิดว่าการรองรับการพิมพ์เป็นฟังก์ชันและพิมพ์เป็นคำสั่งคือการรักษาความเข้ากันได้แบบย้อนหลังกับ python เวอร์ชันเก่าในขณะที่สนับสนุนให้ผู้ใช้ใช้ไวยากรณ์ใหม่เพื่อย้ายไปยัง python 3
GWW

11
ps ในการเปิดใช้งานฟังก์ชันการพิมพ์ใน 2.7 (และไม่มีลักษณะการทำงานของคำสั่งพิมพ์) คุณต้องนำเข้าในอนาคต:from __future__ import print_function
Jeff Mercado

ตัวอย่างที่สองจะพิมพ์ "Hello, World!" หรือไม่ (ไม่เว้นวรรค) หรือจะพิมพ์ "Hello, World!" (มีช่องว่าง) ดังตัวอย่าง
kapad

คำตอบ:


107

ใน Python 2.x printเป็นคำสั่งพิเศษไม่ใช่ฟังก์ชัน *

นี่คือสาเหตุที่ไม่สามารถใช้เช่น: lambda x: print x

โปรดทราบ(expr)ว่าไม่ได้สร้าง Tuple (ผลลัพธ์expr) แต่,สร้าง ซึ่งอาจส่งผลให้เกิดความสับสนระหว่างprint (x)และprint (x, y)ใน Python 2.7

(1)   # 1 -- no tuple Mister!
(1,)  # (1,)
(1,2) # (1, 2)
1,2   # 1 2 -- no tuple and no parenthesis :) [See below for print caveat.]

อย่างไรก็ตามเนื่องจากprintเป็นคำสั่งไวยากรณ์พิเศษ / โครงสร้างไวยากรณ์ใน Python 2.x ดังนั้นหากไม่มีวงเล็บจึงถือว่า,'s ในลักษณะพิเศษ - และไม่สร้าง Tuple การปฏิบัติตามprintคำแถลงเป็นพิเศษนี้ช่วยให้สามารถทำหน้าที่แตกต่างออกไปได้หากมีการต่อท้าย,หรือไม่

มีความสุขในการเขียนโค้ด


* printพฤติกรรมนี้ใน Python 2 สามารถเปลี่ยนเป็น Python 3 ได้:

from __future__ import print_function

3
ขอบคุณสำหรับ(expr) != tupleคำอธิบาย :-)
Hubro

5

ทุกอย่างง่ายมากและไม่มีอะไรเกี่ยวข้องกับความเข้ากันได้แบบเดินหน้าหรือถอยหลัง

รูปแบบทั่วไปสำหรับprintคำสั่งใน Python ทุกเวอร์ชันก่อนเวอร์ชัน 3 คือ:

print expr1, expr2, ... exprn

(แต่ละนิพจน์จะได้รับการประเมินแปลงเป็นสตริงและแสดงโดยเว้นวรรคระหว่างกัน)

แต่จำไว้ว่าการใส่วงเล็บรอบนิพจน์ยังคงเป็นนิพจน์เดิม

ดังนั้นคุณสามารถเขียนสิ่งนี้เป็น:

print (expr1), (expr2), ... (expr3)

สิ่งนี้ไม่เกี่ยวข้องกับการเรียกใช้ฟังก์ชัน


นี่เป็นคำตอบที่ถูกต้องอย่างสมบูรณ์ฉันไม่แน่ใจว่าทำไมมันจึงถูกลดลงมากเช่นกัน
Martijn Pieters

มันไม่เกี่ยวprint (expr1), (expr2), ... (expr3)กับว่าทำไมprint (expr1, expr2, ... , expr3)ถูกกฎหมายใน python 2.x ในขณะที่ไม่ควรเป็นไปตามมาตรฐาน 2.x
vinnief

5

ที่นี่เรามีผลข้างเคียงที่น่าสนใจเมื่อพูดถึง UTF-8

>> greek = dict( dog="σκύλος", cat="γάτα" )
>> print greek['dog'], greek['cat']
σκύλος γάτα
>> print (greek['dog'], greek['cat'])
('\xcf\x83\xce\xba\xcf\x8d\xce\xbb\xce\xbf\xcf\x82', '\xce\xb3\xce\xac\xcf\x84\xce\xb1')

การพิมพ์ครั้งสุดท้ายคือทูเพิลที่มีค่าไบต์ฐานสิบหก


7
ฉันคิดว่านั่นเป็นเพราะการพิมพ์พิมพ์ UTF-8 ได้อย่างถูกต้อง แต่เมื่อได้รับทูเปิลเช่นการพิมพ์ครั้งล่าสุดของคุณมันจะทำงานreprบนนั้น ณ จุดนั้นอาจเข้ารหัสสตริงทั้งหมดใน dict เป็น ASCII
Hubro

3
@Codemonkey คุณมีสิทธิเกี่ยวกับRepr คุณคิดผิดเกี่ยวกับ ASCII ASCII เป็นการเข้ารหัสเริ่มต้นสำหรับ Python แต่ผมมีจุดเริ่มต้นของงูหลามสคริปต์#encoding=utf-8, Linux LANG=en_US.UTF-8env ดังนั้นการเข้ารหัสreprจึงไม่ใช้ ASCII เริ่มต้น แต่เป็นการเข้ารหัส utf-8
Karlo Smid

1
Repr เข้ารหัสstrด้วยการstring_escapeเข้ารหัสพิเศษ สตริงถูกเข้ารหัส Unicode เป็น UTF-8 แล้ว
tzot

@KarloSmid: สิ่งที่ฉันตั้งใจจะพูดคือreprอาจต้องใช้ขั้นตอนเพื่อให้แน่ใจว่าข้อความสามารถแสดงโดย ASCII ได้ (โดยการหลีกเลี่ยงสัญลักษณ์ที่ไม่ใช่ ASCII) ไม่จำเป็นว่าสตริงจะถูกเข้ารหัสเป็น ASCII ฉันยังไม่รู้ว่ามันถูกต้องหรือไม่
Hubro

คอนเทนเนอร์ Python ทั้งหมด (list, dict, tuple, set) รวมเนื้อหาเป็นrepr()เอาต์พุตเมื่อแปลงเป็นสตริง (ไม่ได้ใช้งาน__str__เท่านั้น__repr__) สิ่งที่คุณเห็นไม่พิเศษสำหรับ UTF-8; repr()ของสตริงที่ถูกต้องจะช่วยให้คุณอักษรของสตริงหลามที่มี ASCII ปลอดภัย
Martijn Pieters

2

โดยทั่วไปใน Python ก่อน Python 3 การพิมพ์เป็นคำสั่งพิเศษที่พิมพ์สตริงทั้งหมดหากมีเป็นอาร์กิวเมนต์ ดังนั้นprint "foo","bar"หมายถึง "พิมพ์" foo "ตามด้วย" bar "" ปัญหาที่เกิดขึ้นคือมันอยากให้ทำราวกับว่าการพิมพ์เป็นฟังก์ชันและไวยากรณ์ของ Python นั้นคลุมเครือเนื่องจาก(a,b)เป็นทูเพิลที่มีaและbแต่foo(a,b)เป็นการเรียกใช้ฟังก์ชันของสองอาร์กิวเมนต์

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

(อันที่จริงฉันคิดว่า 2.7 ทำงานตามที่ 2.6 ทำในสิ่งนี้ แต่ฉันไม่แน่ใจ)


ไม่มันไม่ได้ "ดึงดูด" ที่จะใช้เป็นฟังก์ชัน :) อย่างไรก็ตามมันเป็นไปไม่ได้ที่จะใช้เป็นฟังก์ชันดังนั้นคุณจึงไม่สามารถทำ [พิมพ์ x สำหรับ x in alist] ได้
Lennart Regebro
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.