คำตอบ:
ไม่ใช่เพราะมันไม่สมเหตุสมผล มันเหมาะสมที่จะกำหนด "x ++" เป็น "x + = 1 ประเมินการรวมก่อนหน้าของ x"
หากคุณต้องการทราบเหตุผลดั้งเดิมคุณจะต้องลุยรายการส่งจดหมาย Python เก่าหรือถามคนที่อยู่ที่นั่น (เช่น Guido) แต่ก็ง่ายพอที่จะพิสูจน์ความจริง:
การเพิ่มและลดระดับอย่างง่ายไม่จำเป็นต้องมีมากเหมือนในภาษาอื่น ๆ คุณไม่ได้เขียนสิ่งต่าง ๆfor(int i = 0; i < 10; ++i)
ใน Python บ่อยนัก คุณทำสิ่งที่ชอบfor i in range(0, 10)
แทน
เนื่องจากไม่จำเป็นต้องใช้บ่อยบ่อยครั้งมีเหตุผลน้อยกว่าที่จะให้ไวยากรณ์พิเศษของมันเอง เมื่อคุณต้องการที่จะเพิ่มขึ้น+=
มักจะเป็นเรื่องปกติ
มันไม่ใช่การตัดสินใจว่ามันสมเหตุสมผลหรือไม่หรือสามารถทำได้ - ทำได้และทำได้ มันเป็นคำถามว่าผลประโยชน์คุ้มค่าที่จะเพิ่มในไวยากรณ์หลักของภาษาหรือไม่ โปรดจำไว้ว่านี่คือตัวดำเนินการสี่รายการได้แก่ postinc, postdec, preinc, predec และแต่ละตัวจะต้องมีคลาสของตัวเองมากเกินไป พวกเขาทั้งหมดจะต้องมีการระบุและทดสอบ; มันจะเพิ่ม opcodes ให้กับภาษา (หมายถึงตัวที่ใหญ่กว่าและช้ากว่ากลไก VM); ทุกคลาสที่รองรับการเพิ่มขึ้นแบบลอจิคัลจะต้องใช้มัน (ด้านบน+=
และ-=
)
ทั้งหมดนี้ซ้ำซ้อนกับ+=
และ-=
ดังนั้นมันจะกลายเป็นขาดทุนสุทธิ
i
โดยตรง - หากคุณต้องการและไม่สามารถใช้งานได้array.append()
i++
และ++i
...
++
และ--
การใช้งานในรูปแบบที่ทำให้ไม่ได้กำหนดหรือไม่เจาะจง พฤติกรรม. พวกมันทำให้มันเป็นไปได้ที่จะเขียนโค้ดที่ซับซ้อนและยากต่อการแยกวิเคราะห์อย่างถูกต้อง
คำตอบดั้งเดิมที่ฉันเขียนนี้เป็นตำนานจากนิทานคติของคอมพิวเตอร์ : debunked โดย Dennis Ritchie ว่า "เป็นไปไม่ได้ในอดีต" ตามที่ระบุไว้ในจดหมายถึงบรรณาธิการของCommunications of the ACM July 2012 Doi: 10.1145 / 2209249.2209251
ผู้ประกอบการเพิ่มขึ้น / ลดลง C ถูกประดิษฐ์ขึ้นในเวลาที่คอมไพเลอร์ C ไม่ได้ฉลาดมากและผู้เขียนต้องการที่จะระบุความตั้งใจโดยตรงที่ผู้ประกอบการภาษาเครื่องควรใช้ซึ่งช่วยประหยัดรอบหนึ่งสำหรับคอมไพเลอร์ซึ่ง อาจทำ
load memory
load 1
add
store memory
แทน
inc memory
และ PDP-11 ยังรองรับคำสั่ง "autoincrement" และ "autoincrement deferred" ซึ่งสอดคล้องกับ*++p
และ*p++
ตามลำดับ ดูส่วนที่ 5.3 ของคู่มือหากอยากรู้อยากเห็นอย่างน่ากลัว
เนื่องจากคอมไพเลอร์ฉลาดพอที่จะรับมือกับเทคนิคการเพิ่มประสิทธิภาพระดับสูงที่สร้างขึ้นในไวยากรณ์ของ C พวกเขาจึงเป็นเพียงความสะดวกสบายทางวากยสัมพันธ์ตอนนี้
Python ไม่มีลูกเล่นในการถ่ายทอดความตั้งใจไปยังแอสเซมเบลอร์เพราะมันไม่ได้ใช้
ฉันคิดเสมอว่ามันเกี่ยวข้องกับบรรทัดของ zen ของ python นี้:
ควรมีอย่างใดอย่างหนึ่ง - และดีกว่าเพียงหนึ่ง - วิธีที่ชัดเจนที่จะทำ
x ++ และ x + = 1 ทำสิ่งเดียวกันดังนั้นจึงไม่มีเหตุผลที่จะมีทั้งคู่
one--
เป็นศูนย์หรือไม่
one--
เป็นหนึ่งในประโยค แต่เป็นศูนย์ทันทีหลังจากนั้น ดังนั้น 'koan' นี้ยังบอกเป็นนัยว่าตัวดำเนินการเพิ่ม / ลดไม่ชัดเจน
แน่นอนเราอาจพูดว่า "กุยโด้เพิ่งตัดสินใจแบบนั้น" แต่ฉันคิดว่าคำถามนี้เกี่ยวกับเหตุผลของการตัดสินใจนั้นจริงๆ ฉันคิดว่ามีสาเหตุหลายประการ:
เพราะใน Python จำนวนเต็มไม่เปลี่ยนรูป (int's + = จริง ๆ แล้วส่งคืนออบเจ็กต์อื่น)
นอกจากนี้ด้วย ++ / - คุณจำเป็นต้องกังวลเกี่ยวกับการโพสต์ก่อนเมื่อเทียบกับการเพิ่มขึ้น / x+=1
ลดลงและจะใช้เวลาเพียงอีกหนึ่งการกดแป้นพิมพ์เขียน กล่าวอีกนัยหนึ่งก็คือหลีกเลี่ยงความสับสนที่อาจเกิดขึ้นโดยเสียค่าใช้จ่ายเล็กน้อย
42++
... บางอย่างเช่นนี้ (การแก้ไขค่าคงตัวอักษร) เป็นไปได้จริงในคอมไพเลอร์ Fortran เก่า ๆ (หรือฉันได้อ่าน): การใช้ในอนาคตทั้งหมด ของตัวอักษรนั้นในการรันโปรแกรมนั้นจะมีค่าแตกต่างกัน การแก้ไขข้อบกพร่องมีความสุข!
int
โดยทั่วไปจะไม่เปลี่ยนรูป A int
ใน C เพียงกำหนดสถานที่ในหน่วยความจำ และบิตในสถานที่นั้นไม่แน่นอนมากนัก ตัวอย่างเช่นคุณสามารถสร้างการอ้างอิงของint
และเปลี่ยนการอ้างอิงของการอ้างอิงนั้น การเปลี่ยนแปลงนี้สามารถมองเห็นได้ในการอ้างอิงทั้งหมด (รวมถึงint
ตัวแปรดั้งเดิม) ไปยังสถานที่นั้น สิ่งเดียวกันไม่ได้เก็บไว้สำหรับวัตถุจำนวนเต็ม Python
Python มีความชัดเจนมากและโปรแกรมเมอร์ไม่น่าจะเดาความหมายได้อย่างถูกต้อง--a
เว้นแต่ว่าเขา / เธอได้เรียนรู้ภาษาที่มีโครงสร้างนั้น
Python เป็นจำนวนมากเกี่ยวกับการหลีกเลี่ยงการสร้างที่เชิญความผิดพลาดและ++
ผู้ประกอบการเป็นแหล่งของข้อบกพร่องมากมาย เหตุผลสองข้อนี้ไม่เพียงพอที่จะไม่มีตัวดำเนินการเหล่านั้นใน Python
การตัดสินใจที่ Python ใช้การเยื้องในการทำเครื่องหมายบล็อกมากกว่าหมายถึงการสร้างประโยคเช่นรูปแบบของการเริ่มต้น / สิ้นสุดการถ่ายคร่อมหรือการทำเครื่องหมายจุดสิ้นสุดบังคับนั้นขึ้นอยู่กับการพิจารณาเดียวกัน
สำหรับภาพประกอบให้ดูที่การอภิปรายเกี่ยวกับการแนะนำตัวดำเนินการแบบมีเงื่อนไข (ใน C cond ? resultif : resultelse
:) ใน Python ในปี 2005 อ่านข้อความแรกอย่างน้อยและข้อความการตัดสินใจของการสนทนานั้น(ซึ่งมีผู้นำหลายคนในหัวข้อเดียวกันก่อนหน้านี้)
Trivia: PEP ที่กล่าวถึงบ่อยครั้งในนั้นคือ "งูใหญ่ขยายข้อเสนอ" PEP 308 LC หมายถึงความเข้าใจในรายการ , GE หมายถึงการแสดงออกของเครื่องกำเนิด (และไม่ต้องกังวลหากสิ่งเหล่านั้นทำให้คุณสับสน
ความเข้าใจของฉันเกี่ยวกับสาเหตุที่หลามไม่มี++
ตัวดำเนินการต่อไปนี้: เมื่อคุณเขียนสิ่งนี้ในไพ ธ อนa=b=c=1
คุณจะได้รับตัวแปรสามตัว (ฉลาก) ที่ชี้ไปที่วัตถุเดียวกัน (ค่าใดคือ 1) คุณสามารถตรวจสอบได้โดยใช้ฟังก์ชั่น id ซึ่งจะส่งคืนที่อยู่หน่วยความจำของวัตถุ:
In [19]: id(a)
Out[19]: 34019256
In [20]: id(b)
Out[20]: 34019256
In [21]: id(c)
Out[21]: 34019256
ตัวแปรทั้งสาม (ป้ายกำกับ) ชี้ไปที่วัตถุเดียวกัน ตอนนี้เพิ่มหนึ่งในตัวแปรและดูว่ามันมีผลต่อที่อยู่หน่วยความจำอย่างไร:
In [22] a = a + 1
In [23]: id(a)
Out[23]: 34019232
In [24]: id(b)
Out[24]: 34019256
In [25]: id(c)
Out[25]: 34019256
ท่านสามารถเข้าดูตัวแปรที่a
ตอนนี้ชี้ไปที่วัตถุอื่นเป็นตัวแปรและb
c
เพราะคุณใช้a = a + 1
มันชัดเจนแล้ว กล่าวอีกนัยหนึ่งคุณกำหนดวัตถุอื่นให้กับป้ายกำกับa
อย่างสมบูรณ์ ลองนึกภาพว่าคุณสามารถเขียนa++
ได้ขอแนะนำว่าคุณไม่ได้กำหนดให้กับa
วัตถุใหม่ที่แปรผัน ทุกสิ่งนี้คือ IMHO เพื่อลดความสับสน เพื่อความเข้าใจที่ดีขึ้นดูว่าตัวแปรไพ ธ อนทำงานอย่างไร:
ใน Python ทำไมฟังก์ชั่นสามารถแก้ไขข้อโต้แย้งบางอย่างตามที่รับรู้โดยผู้โทร แต่ไม่ใช่คนอื่น?
Python มีค่าโทรหรือค่าอ้างอิงโดยอ้างอิงหรือไม่? ทั้ง
Python ส่งผ่านค่าหรืออ้างอิงหรือไม่
Python pass-by-reference หรือ pass-by-value หรือไม่
Python: ฉันจะส่งผ่านตัวแปรโดยการอ้างอิงได้อย่างไร
ทำความเข้าใจกับตัวแปร Python และการจัดการหน่วยความจำ
การเลียนแบบพฤติกรรมแบบบายพาสในไพ ธ อน
มันถูกออกแบบมาอย่างนั้น x = x + 1
เพิ่มขึ้นและผู้ประกอบการลดลงเป็นทางลัดเพียงเพื่อ โดยทั่วไปแล้ว Python ได้นำกลยุทธ์การออกแบบมาใช้ซึ่งจะลดจำนวนวิธีการอื่นในการดำเนินการ การเพิ่มการเติมเป็นสิ่งที่ใกล้เคียงที่สุดกับตัวดำเนินการเพิ่ม / ลดใน Python และพวกมันไม่ได้ถูกเพิ่มจนกระทั่ง Python 2.0
return a[i++]
return a[i=i+1]
ฉันใหม่กับงูใหญ่ แต่ฉันคิดว่าเหตุผลก็เพราะความสำคัญระหว่างวัตถุที่เปลี่ยนแปลงไม่ได้และไม่เปลี่ยนรูปในภาษา ตอนนี้ฉันรู้ว่า x ++ สามารถตีความได้อย่างง่ายดายว่าเป็น x = x + 1 แต่มันดูเหมือนว่าคุณกำลังเพิ่มวัตถุในสถานที่ซึ่งอาจไม่เปลี่ยนรูปได้
แค่เดา / รู้สึก / ลางสังหรณ์ของฉัน
x++
นี้ใกล้เคียงx += 1
กว่าx = x + 1
สองสิ่งนี้สร้างความแตกต่างได้เช่นกันบนวัตถุที่ไม่แน่นอน
ประการแรก Python ได้รับอิทธิพลทางอ้อมจาก C เท่านั้น มันได้รับอิทธิพลอย่างมากจากABCซึ่งเห็นได้ชัดว่าไม่มีตัวดำเนินการเหล่านี้ดังนั้นจึงไม่น่าแปลกใจเลยที่จะไม่พบพวกมันใน Python
ประการที่สองอย่างที่คนอื่น ๆ พูดเพิ่มและลดลงได้รับการสนับสนุนโดย+=
และ-=
แล้ว
การสนับสนุนที่สามอย่างสมบูรณ์สำหรับชุดตัวดำเนินการ++
และ--
ตัวดำเนินการมักจะรวมถึงการสนับสนุนทั้งส่วนนำหน้าและเวอร์ชันหลังของพวกเขา ใน C และ C ++ สิ่งนี้สามารถนำไปสู่การสร้าง "ที่น่ารัก" ทุกชนิดที่ดูเหมือน (กับฉัน) เพื่อต่อต้านจิตวิญญาณแห่งความเรียบง่ายและความตรงไปตรงมาที่ Python รวบรวม
ตัวอย่างเช่นในขณะที่คำสั่ง C while(*t++ = *s++);
อาจดูเรียบง่ายและสง่างามสำหรับโปรแกรมเมอร์ที่มีประสบการณ์ แต่สำหรับคนที่กำลังเรียนรู้มันเป็นอะไรที่เรียบง่าย โยนการผสมผสานของคำนำหน้าและการเพิ่มขึ้นและการลดลง postfix และแม้แต่ผู้เชี่ยวชาญหลายคนจะต้องหยุดและคิดเล็กน้อย
ฉันเชื่อว่ามันเกิดจาก Python เชื่อว่า "ชัดเจนดีกว่าโดยนัย"
อาจเป็นเพราะ@GlennMaynardดูที่เรื่องนี้เมื่อเปรียบเทียบกับภาษาอื่น ๆ แต่ใน Python คุณทำสิ่งต่างๆด้วยวิธีของ Python มันไม่ใช่คำถาม 'ทำไม' x+=
มันมีและคุณสามารถทำสิ่งที่มีผลเช่นเดียวกันกับ ในThe Zen of Pythonจะได้รับ: "ควรมีวิธีเดียวเท่านั้นในการแก้ปัญหา" มีหลายตัวเลือกที่ยอดเยี่ยมในศิลปะ (อิสระในการแสดงออก) แต่มีหมัดในด้านวิศวกรรม
++
ระดับของผู้ประกอบการที่มีการแสดงออกที่มีผลข้างเคียง นี่คือสิ่งที่โดยทั่วไปไม่พบใน Python
ด้วยเหตุผลเดียวกันการมอบหมายไม่ใช่การแสดงออกใน Python ดังนั้นการป้องกันif (a = f(...)) { /* using a here */ }
สำนวนสามัญ
สุดท้ายฉันสงสัยว่ามีโอเปอเรเตอร์ไม่สอดคล้องกับความหมายของ Pythons โปรดจำไว้ว่า Python ไม่มีตัวแปร (หรือตัวชี้) ที่มีซีแมนทิกส์รู้จักจาก C / C ++
f(a)
ที่ไหนa
คือรายการวัตถุบางอย่างที่ไม่เปลี่ยนรูป
อาจเป็นคำถามที่ดีกว่าที่จะถามว่าทำไมตัวดำเนินการเหล่านี้มีอยู่ใน C. K&R เรียกการเพิ่มและลดลงของผู้ประกอบการ 'ผิดปกติ' (ส่วน 2.8 หน้า 46) บทนำนี้เรียกพวกเขาว่า 'กระชับและบ่อยขึ้นกว่าเดิม' ฉันสงสัยว่าความจริงที่ว่าการดำเนินการเหล่านี้มักจะเกิดขึ้นในการจัดการตัวชี้ยังมีส่วนร่วมในการแนะนำของพวกเขา ใน Python อาจมีการตัดสินใจว่าไม่มีเหตุผลที่จะพยายามเพิ่มประสิทธิภาพการเพิ่มประสิทธิภาพ (อันที่จริงฉันเพิ่งทำการทดสอบใน C และดูเหมือนว่าชุดประกอบที่สร้างโดย gcc ใช้ addl แทนที่จะรวมทั้งในทั้งสองกรณี) และไม่มี เลขคณิตของตัวชี้; ดังนั้นมันจึงเป็นเพียงอีกวิธีหนึ่งในการทำเช่นนั้นและเรารู้ว่า Python ไม่ชอบสิ่งนั้น
อย่างที่ฉันเข้าใจดังนั้นคุณจะไม่คิดว่ามูลค่าในหน่วยความจำจะเปลี่ยนไป ใน c เมื่อคุณทำ x ++ ค่าของ x ในการเปลี่ยนแปลงหน่วยความจำ แต่ในไพ ธ อนตัวเลขทั้งหมดจะไม่เปลี่ยนรูปดังนั้นที่อยู่ที่ x ชี้ยังคงมี x ไม่ใช่ x + 1 เมื่อคุณเขียน x ++ คุณจะคิดว่า x เปลี่ยนสิ่งที่เกิดขึ้นจริงคือ x refrence ถูกเปลี่ยนเป็นตำแหน่งในหน่วยความจำโดยที่ x + 1 ถูกเก็บไว้หรือสร้างตำแหน่งนี้ใหม่หากไม่มี doe อยู่
++
แตกต่างจาก+= 1
นี้
หากต้องการคำตอบที่ดีอยู่แล้วในหน้านั้น:
ลองสมมติว่าเราตัดสินใจทำสิ่งนี้คำนำหน้า ( ++i
) ที่จะทำลายเครื่องหมาย + และ - ตัวดำเนินการ unary
วันนี้นำหน้าด้วย++
หรือ--
ไม่ทำอะไรเลยเพราะช่วยให้ตัวดำเนินการยูนารีบวกสองครั้ง (ไม่ทำอะไรเลย) หรือนำหน้าคู่ลบสองครั้ง (สองครั้ง: ยกเลิกตัวเอง)
>>> i=12
>>> ++i
12
>>> --i
12
นั่นอาจจะเป็นการทำลายตรรกะนั้น
คำตอบอื่น ๆ ได้อธิบายว่าเหตุใดจึงไม่จำเป็นสำหรับตัววนซ้ำ แต่บางครั้งมันมีประโยชน์เมื่อกำหนดเพื่อเพิ่มตัวแปรในบรรทัดคุณสามารถได้รับผลเช่นเดียวกันโดยใช้ tuples และการกำหนดหลายอย่าง:
b = ++a
กลายเป็น:
a,b = (a+1,)*2
และb = a++
กลายเป็น:
a,b = a+1, a
Python 3.8 แนะนำ:=
ผู้ประกอบการที่ได้รับมอบหมายทำให้เราประสบความสำเร็จfoo(++a)
ด้วย
foo(a:=a+1)
foo(a++)
ยังคงเข้าใจยากว่า
ฉันคิดว่าสิ่งนี้เกี่ยวข้องกับแนวคิดเรื่องความผันแปรและการเปลี่ยนแปลงไม่ได้ของวัตถุ 2,3,4,5 ไม่เปลี่ยนแปลงในหลาม ดูภาพด้านล่าง 2 ได้รับการแก้ไข id จนกระทั่งกระบวนการหลามนี้
x ++ โดยพื้นฐานแล้วจะหมายถึงการเพิ่มขึ้นแบบแทนที่ C ใน C, x ++ ดำเนินการเพิ่มขึ้นแบบแทนที่ ดังนั้น x = 3 และ x ++ จะเพิ่มขึ้น 3 ในหน่วยความจำถึง 4 ซึ่งแตกต่างจากไพ ธ อนที่ 3 จะยังคงอยู่ในหน่วยความจำ
ดังนั้นในไพ ธ อนคุณไม่จำเป็นต้องสร้างค่าในหน่วยความจำใหม่ สิ่งนี้อาจนำไปสู่การปรับประสิทธิภาพให้เหมาะสม
นี่คือคำตอบตามลางสังหรณ์
ฉันรู้ว่านี่เป็นเธรดเก่า แต่กรณีการใช้งานทั่วไปสำหรับ ++ i ไม่ครอบคลุมนั่นคือการจัดทำดัชนีด้วยตนเองเมื่อไม่มีดัชนีที่จัดเตรียมไว้ให้ สถานการณ์นี้เป็นเหตุผลที่หลามให้แจกแจง ()
ตัวอย่าง: ในภาษาใดก็ตามเมื่อคุณใช้โครงสร้างเช่น foreach เพื่อย้ำข้ามชุด - เพราะตัวอย่างเราจะพูดว่ามันเป็นชุดที่ไม่มีการเรียงลำดับและคุณต้องการดัชนีเฉพาะสำหรับทุกสิ่งเพื่อบอกพวกเขาแยกกันพูด
i = 0
stuff = {'a': 'b', 'c': 'd', 'e': 'f'}
uniquestuff = {}
for key, val in stuff.items() :
uniquestuff[key] = '{0}{1}'.format(val, i)
i += 1
ในกรณีเช่นนี้ python ให้วิธีแจกแจงเช่น
for i, (key, val) in enumerate(stuff.items()) :