RE Python ไม่ปฏิบัติตามหลักการนี้ โดยทั่วไปจะปฏิบัติตามหลักการ ตัวอย่างพื้นฐาน:
>>> x = ['foo']
>>> x
['foo']
>>> x = (lambda: ['foo'])()
>>> x
['foo']
อย่างไรก็ตาม Python กำหนดนิพจน์และข้อความสั่งแยกกัน เนื่องจากif
กิ่งก้านwhile
ลูปการมอบหมายการทำลายล้างและข้อความอื่น ๆ ไม่สามารถใช้ในlambda
การแสดงออกได้เลยจดหมายของหลักการ Tennent จึงไม่สามารถใช้กับพวกเขาได้ ถึงกระนั้นการ จำกัด ตัวเองให้ใช้เพียงการแสดงออกของงูหลามยังคงสร้างระบบทัวริงที่สมบูรณ์ ดังนั้นฉันไม่เห็นสิ่งนี้เป็นการละเมิดหลักการ; หรือหากเป็นการละเมิดหลักการก็ไม่มีภาษาใดที่กำหนดข้อความและสำนวนแยกกันอาจเป็นไปตามหลักการ
นอกจากนี้หากเนื้อความของlambda
นิพจน์ถูกดักจับการติดตามสแต็กหรือทำวิปัสสนาอื่น ๆ ใน VM ซึ่งอาจทำให้เกิดความแตกต่าง แต่ในความคิดของฉันนี้ไม่ควรนับเป็นการละเมิด ถ้าexpr
และ(lambda: expr)()
จำเป็นต้องคอมไพล์ด้วยรหัสไบต์เดียวกันหลักการก็เกี่ยวข้องกับคอมไพเลอร์ไม่ใช่ซีแมนติก แต่ถ้าพวกเขาสามารถคอมไพล์โค้ดไบต์ที่แตกต่างกันได้เราไม่ควรคาดหวังว่าสถานะ VM จะเหมือนกันในแต่ละกรณี
ความประหลาดใจสามารถพบได้โดยใช้ไวยากรณ์ความเข้าใจแม้ว่าฉันเชื่อว่านี่ไม่ใช่การละเมิดหลักการ Tennent เช่นกัน ตัวอย่าง:
>>> [x for x in xrange(10)]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> [f() for f in [lambda: x for x in xrange(10)]] # surprise!
[9, 9, 9, 9, 9, 9, 9, 9, 9, 9]
>>> # application of Tennent principle to first expression
... [(lambda: x)() for x in xrange(10)]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> [f() for f in [(lambda x: lambda: x)(x) for x in xrange(10)]] # force-rebind x
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> map(lambda f:f(), map(lambda x: lambda: x, xrange(10))) # no issue with this form
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
ความประหลาดใจเป็นผลมาจากวิธีการกำหนดรายการความเข้าใจ ความเข้าใจ 'ประหลาดใจ' ข้างต้นเทียบเท่ากับรหัสนี้:
>>> result = []
>>> for x in xrange(10):
... # the same, mutable, variable x is used each time
... result.append(lambda: x)
...
>>> r2 = []
>>> for f in result:
... r2.append(f())
...
>>> r2
[9, 9, 9, 9, 9, 9, 9, 9, 9, 9]
เห็นด้วยวิธีนี้ความเข้าใจ 'ประหลาดใจ' ข้างต้นไม่น่าแปลกใจและไม่เป็นการละเมิดหลักการ Tennent