Nó không phải tốc ký.
Các +=
biểu tượng xuất hiện trong ngôn ngữ C vào những năm 1970, và - với ý tưởng C của "lắp ráp thông minh" tương ứng với một lệnh máy và adressing chế độ rõ ràng khác nhau:
Những thứ như " i=i+1
", "i+=1
"và" ++i
", mặc dù ở mức trừu tượng tạo ra hiệu ứng tương tự, tương ứng ở mức thấp với cách làm việc khác của bộ xử lý.
Cụ thể là ba biểu thức đó, giả sử i
biến nằm trong địa chỉ bộ nhớ được lưu trong thanh ghi CPU (hãy đặt tên cho nó D
- nghĩ về nó như một "con trỏ tới int") và ALU của bộ xử lý lấy tham số và trả về kết quả trong một "Bộ tích lũy" (hãy gọi nó là A - nghĩ về nó như một số nguyên).
Với những hạn chế này (rất phổ biến trong tất cả các bộ vi xử lý từ thời kỳ đó), bản dịch rất có thể sẽ là
;i = i+1;
MOV A,(D); //Move in A the content of the memory whose address is in D
ADD A, 1; //The addition of an inlined constant
MOV (D) A; //Move the result back to i (this is the '=' of the expression)
;i+=1;
ADD (D),1; //Add an inlined constant to a memory address stored value
;++i;
INC (D); //Just "tick" a memory located counter
Cách đầu tiên để thực hiện nó là không tối ưu, nhưng nó tổng quát hơn khi hoạt động với các biến thay vì hằng ( ADD A, B
hoặc ADD A, (D+x)
) hoặc khi dịch các biểu thức phức tạp hơn (tất cả đều sôi lên trong hoạt động đẩy mức độ ưu tiên thấp trong ngăn xếp, gọi mức độ ưu tiên cao, pop và lặp lại cho đến khi tất cả các đối số đã được loại bỏ).
Thứ hai là điển hình hơn của "máy trạng thái": chúng tôi không còn "đánh giá biểu thức", mà là "vận hành một giá trị": chúng tôi vẫn sử dụng ALU, nhưng tránh di chuyển các giá trị xung quanh là kết quả được phép thay thế tham số. Các loại hướng dẫn này không thể được sử dụng khi cần có biểu thức phức tạp hơn: i = 3*i + i-2
không thể được vận hành tại chỗ, vì i
được yêu cầu nhiều lần hơn.
Đơn giản thứ ba - thậm chí không xem xét ý tưởng "bổ sung", mà sử dụng một mạch "nguyên thủy" hơn (theo nghĩa tính toán) cho một bộ đếm. Lệnh được rút ngắn, tải nhanh hơn và thực thi ngay lập tức, do mạng kết hợp cần phải trang bị thêm một thanh ghi để làm cho nó trở thành một bộ đếm nhỏ hơn và do đó nhanh hơn so với một bộ cộng đầy đủ.
Với các trình biên dịch hiện đại (tham khảo C, bây giờ), cho phép tối ưu hóa trình biên dịch, sự tương ứng có thể được hoán đổi dựa trên sự thuận tiện, nhưng vẫn có một sự khác biệt về khái niệm trong ngữ nghĩa.
x += 5
có nghĩa
- Tìm địa điểm được xác định bởi x
- Thêm 5 vào nó
Nhưng x = x + 5
có nghĩa là:
- Đánh giá x + 5
- Tìm địa điểm được xác định bởi x
- Sao chép x vào một bộ tích lũy
- Thêm 5 vào bộ tích lũy
- Lưu trữ kết quả trong x
- Tìm địa điểm được xác định bởi x
- Sao chép bộ tích lũy vào nó
Tất nhiên, tối ưu hóa có thể
- nếu "tìm x" không có tác dụng phụ, hai "tìm" có thể được thực hiện một lần (và x trở thành địa chỉ được lưu trong thanh ghi con trỏ)
- hai bản sao có thể được tách ra nếu THÊM được áp dụng
&x
thay thế cho bộ tích lũy
do đó làm cho mã được tối ưu hóa trùng với mã x += 5
.
Nhưng điều này chỉ có thể được thực hiện nếu "tìm x" không có tác dụng phụ, nếu không
*(x()) = *(x()) + 5;
và
*(x()) += 5;
là khác nhau về mặt ngữ nghĩa, vì các x()
tác dụng phụ (thừa nhận x()
là một chức năng làm những điều kỳ lạ xung quanh và trả lại một int*
) sẽ được sản xuất hai lần hoặc một lần.
Sự tương đương giữa x = x + y
và x += y
do đó là do trường hợp cụ thể trong đó +=
và =
được áp dụng cho giá trị l trực tiếp.
Để chuyển sang Python, nó đã kế thừa cú pháp từ C, nhưng vì không có bản dịch / tối ưu hóa TRƯỚC KHI thực thi trong các ngôn ngữ được dịch, nên mọi thứ không nhất thiết phải liên quan mật thiết như vậy (vì có một bước ít phân tích cú pháp hơn). Tuy nhiên, một trình thông dịch có thể tham khảo các thói quen thực thi khác nhau cho ba loại biểu thức, lợi dụng mã máy khác nhau tùy thuộc vào cách biểu thức được hình thành và trên bối cảnh đánh giá.
Dành cho ai thích chi tiết hơn ...
Mỗi CPU đều có ALU (đơn vị logic số học), về bản chất, là một mạng tổ hợp có đầu vào và đầu ra được "cắm" vào các thanh ghi và / hoặc bộ nhớ tùy thuộc vào opcode của lệnh.
Các hoạt động nhị phân thường được triển khai như là "công cụ sửa đổi của thanh ghi tích lũy với đầu vào được lấy" ở đâu đó ", trong đó có thể ở đâu đó - bên trong dòng lệnh (điển hình cho contant kê khai: ADD A 5) - bên trong một sổ đăng ký khác (điển hình cho tính toán biểu thức với tạm thời: ví dụ ADD AB) - bên trong bộ nhớ, tại một địa chỉ được cung cấp bởi một thanh ghi (điển hình của việc tìm nạp dữ liệu, ví dụ: ADD A (H)) - H, trong trường hợp này, hoạt động như một con trỏ hội nghị.
Với mã giả này, x += 5
là
ADD (X) 5
trong khi x = x+5
là
MOVE A (X)
ADD A 5
MOVE (X) A
Nghĩa là, x + 5 cung cấp tạm thời được gán sau. x += 5
hoạt động trực tiếp trên x.
Việc triển khai thực tế phụ thuộc vào tập lệnh thực của bộ xử lý: Nếu không có ADD (.) c
opcode, mã đầu tiên sẽ trở thành mã thứ hai: không có cách nào.
Nếu có một opcode như vậy và tối ưu hóa được kích hoạt, biểu thức thứ hai, sau khi loại bỏ các bước di chuyển ngược và điều chỉnh opcode của thanh ghi, trở thành biểu thức đầu tiên.
x += 5
hơnx = x + 5
không? Hoặc nó thực sự chỉ là cú pháp đường như bạn đề nghị?