RE Python không theo nguyên tắc này. Nói chung, nó không theo nguyên tắc. Ví dụ cơ bản:
>>> x = ['foo']
>>> x
['foo']
>>> x = (lambda: ['foo'])()
>>> x
['foo']
Tuy nhiên, Python định nghĩa các biểu thức và câu lệnh riêng biệt. Vì if
các nhánh, while
vòng lặp, gán hủy và các câu lệnh khác hoàn toàn không thể được sử dụng trong các lambda
biểu thức, nên chữ cái của nguyên tắc Tennent không áp dụng cho chúng. Mặc dù vậy, việc hạn chế bản thân chỉ sử dụng các biểu thức Python vẫn tạo ra một hệ thống hoàn chỉnh Turing. Vì vậy, tôi không thấy điều này là vi phạm nguyên tắc; hay đúng hơn, nếu nó vi phạm nguyên tắc, thì không có ngôn ngữ nào định nghĩa các câu và biểu thức riêng biệt có thể phù hợp với nguyên tắc này.
Ngoài ra, nếu phần thân của lambda
biểu thức đang ghi lại dấu vết ngăn xếp hoặc thực hiện phần hướng nội khác trong VM, điều đó có thể gây ra sự khác biệt. Nhưng theo tôi thì điều này không nên được coi là vi phạm. Nếu expr
và (lambda: expr)()
nhất thiết phải biên dịch theo cùng mã byte, thì nguyên tắc thực sự liên quan đến trình biên dịch không phải là ngữ nghĩa; nhưng nếu chúng có thể biên dịch thành mã byte khác nhau, chúng ta không nên mong đợi trạng thái VM giống hệt nhau trong từng trường hợp.
Một bất ngờ có thể gặp phải khi sử dụng cú pháp hiểu, mặc dù tôi tin rằng điều này cũng không vi phạm nguyên tắc Tennent. Thí dụ:
>>> [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]
Điều ngạc nhiên là kết quả của cách hiểu danh sách được xác định. Cách hiểu "bất ngờ" ở trên tương đương với mã này:
>>> 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]
Nhìn theo cách này, sự hiểu biết 'bất ngờ' ở trên ít gây ngạc nhiên hơn và không vi phạm nguyên tắc Tennent.