2013-03-20 35 views
5
// t: current time, b: begInnIng value, c: change In value, d: duration 

def: 'easeOutQuad', 
swing: function (x, t, b, c, d) { 
    //alert(jQuery.easing.default); 
    return jQuery.easing[jQuery.easing.def](x, t, b, c, d); 
}, 
easeInQuad: function (x, t, b, c, d) { 
    return c*(t/=d)*t + b; 
}, 
easeOutQuad: function (x, t, b, c, d) { 
    return -c *(t/=d)*(t-2) + b; 
}, 

Tôi đang cố gắng chuyển đổi Chức năng giảm bớt của Robert Penner thành python và bị kẹt! Bất kỳ trợ giúp nào hoặc bất kỳ ai khác đã thực hiện việc này trước đây?T/= d có nghĩa là gì? Python và gặp lỗi

https://github.com/danro/jquery-easing/blob/master/jquery.easing.js

+2

'a/= b' bằng 'a = a/b; '. –

+1

Đó là viết tắt [* phân chia và gán * toán tử] (https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/Assignment_Operators) – Bergi

+1

Điều đáng chú ý là, trong khi Python cũng có '/ =' thực hiện phân chia và gán như JS, gán một _statement_ thay vì một _expression_ trong Python, vì vậy '-c * (t/= d) * (t-2) + b sẽ là một' Cú pháp Cú pháp ' . – abarnert

Trả lời

6

Trong cả hai JavaScript và Python, /= là một "nhiệm vụ tăng cường" nhà điều hành, với khá nhiều ý nghĩa tương tự.

Trong JS:

var i = 10; 
i /= 2; 

... tương đương với:

var i = 10; 
i = i/2; 

Và, bằng Python:

i = 10 
i /= 2 

... là tương tự như vậy tương đương (không hoàn toàn giống hệt nhau, nhưng đóng đủ số) tới:

i = 10 
i = i/2 

Tuy nhiên, có một sự khác biệt rất lớn.

Trong JavaScript, gán là biểu thức — nó có giá trị và giá trị đó là giá trị được gán cho biến. Vì vậy:

var i = 10; 
var j = i /= 2; 

... là tương đương với:

var i = 10; 
i /= 2; 
var j = i; 

Trong Python, chuyển nhượng là một tuyên bố. Nó không có giá trị, và không thể được sử dụng trong một biểu thức.Vì vậy:

i = 10 
j = i /= 2 

… tăng SyntaxError.


Porting mã có sử dụng chuyển nhượng (augmented hay cách khác) ở giữa một biểu hiện thường đòi hỏi phá vỡ biểu hiện mà ra thành nhiều dòng và/hoặc tìm một cách để viết lại biểu thức để không đòi hỏi bất kỳ bài tập. (Nhưng thông thường, đó không phải là điều xấu, bởi vì các biểu thức ban đầu không dễ đọc lắm…)

Ví dụ, giả sử JS đánh giá toán hạng từ trái sang phải (mà tôi không chắc chắn được đảm bảo?):

def easeInQuad(x, t, b, c, d): 
    t /= d 
    return c*t*t+b 

Tổng quát hơn, bạn làm như sau:

old_t = t 
t /= d 

và sau đó bạn thay thế bất kỳ trường hợp của t trước đó t/=d với old_t, và để lại tất cả các trường từ t/=d và sau đó một mình. May mắn thay, trong trường hợp này, không có trường hợp nào trước đó, vì vậy chúng tôi không cần công cụ đó old_t.

Và nếu bạn nghĩ về nó, bạn có thể dễ dàng có được tác dụng tương tự mà không bao giờ thay đổi t, trong một dòng, nhiều hơn nữa readably, trong bất kỳ trong các cách sau:

return c * (t/d) * (t/d) + b 
return c * (t/d)**2 + b 
return c * t*t/d*d + b 

Một người nào đó nghĩ rằng trong C sẽ ngay lập tức phàn nàn rằng đây là tất cả "quá chậm". Sau khi tất cả, đầu tiên không một phân chia thêm, thứ hai không một số mũ thay vì một phép nhân, và thứ ba hiện hai phép nhân thay vì một. Horrors!

Tất nhiên bạn luôn có thể sử dụng một biến tạm thời:

t_over_d = t/d 
return c * t_over_d * t_over_d + b 

... nhưng một lần nữa, để một lập trình viên C, mà ngụ ý rằng bạn đang sử dụng một đăng ký có giá trị. Chắc chắn, mọi trình biên dịch được viết sau, nói, 1985 sẽ phát hiện rằng t đã chết ngay khi t_over_d xuất hiện và sử dụng lại cùng một thanh ghi, nhưng tại sao không buộc nó để sử dụng lại thanh ghi nếu có thể, đặc biệt nếu nó cũng tiết kiệm một vài lần nhấn phím ?

Trong JS hoặc Python, chi phí của phép nhân là một phần nhỏ của chi phí gọi hàm, và giải thích bytecode, và cứ thế bạn thậm chí không bao giờ chú ý đến nó. Trong khi đó, chi phí của việc rebinding một biến địa phương (đặc biệt là trong một phiên bản V8 kiểu hoặc PyPy kiểu JIT thông dịch viên) có thể là nhiều, cao hơn nhiều so với chi phí đi qua xung quanh một kết quả tạm thời chưa được đặt tên. Vì vậy, đây là một trường hợp mô hình sai lầm "tối ưu hóa" làm cho mã khó hiểu hơn, trong khi có thể làm chậm nó xuống thay vì tăng tốc nó, và trong một khu vực mà không thể là một nút cổ chai giá trị tối ưu anyway.


Kể từ gnibbler lớn lên câu hỏi liệu JavaScript thực sự không đảm bảo trật tự đánh giá này ...

Đầu tiên, JavaScript được định nghĩa là, một cách hiệu quả, "những gì Firefox không" (và "những gì SpiderMonkey làm", nhưng điều đó phải giống nhau - và nếu không, thì JavaScript sẽ làm 2 thứ, vậy là gấp đôi, đúng không?).Nhưng ECMAScript được xác định theo tiêu chuẩn và đó là những tiêu chuẩn mà mọi triển khai JS (mặc dù tên) trả tiền cho dịch vụ môi và chúng tôi có thể giả định rằng ECMAScript 5.1 là tiêu chuẩn mà mọi triển khai tuân thủ (điều này đúng với điều kiện là " tất cả triển khai "có nghĩa là" Opera "). Bạn có thể tìm thấy nó here.

Vì vậy, trong ES 5.1: 11,5 chất nhân khai thác đảm bảo rằng kết quả của (t/=d) sẽ được đánh giá trước t, và 11.13.2 Compound Assignment đảm bảo rằng đánh giá t/=d sẽ thiết lập giá trị của t trước khi nó kết thúc. (Bạn phải đọc về những gì "đánh giá" có nghĩa là gì và những gì GetValue một nghĩa là SetValue, nhưng tôi chắc chắn điều này thực sự được đảm bảo.)

+0

Một số người nghĩ rằng gây nhiễu nó tất cả trong một dòng làm cho nó kỳ diệu chạy nhanh hơn. –

+0

Cảm ơn @abarnert vì đã giải thích. Là một câu hỏi chung, tôi đoán không ai biết tương đương python? Tôi không thể là người đầu tiên cố gắng sử dụng chúng trong python ... – justachap

+0

@gnibbler: Trên thực tế, tôi nghĩ rằng tôi biết tại sao ai đó nghĩ rằng nó sẽ nhanh hơn, không chỉ là "ít nhân vật để giải thích" sai lầm, nhưng "JS giống như C trên PDP-11, đúng không?" sai lầm ... – abarnert

0

Chia và chỉ định.

>>> p = 6 
>>> p /= 2 
>>> p 
3 
1

/= là toán tử gán tăng cường. t /= d giống với t = t/d. +=, -=*= cũng tồn tại, trong số những người khác ...

1

Cũng là nhà khai thác ngắn của nó giống như += nhưng thay vì thêm nó chia. Dưới đây là hình thức lâu

t = t/d 
1
c*(t/=d)*t + b; 

là tương đương với

t /= d   # or t = t/d 
c * t * t + b 

Bởi vì Python không thể để assigment bên trong biểu thức

Hãy nhớ rằng nếu td đều int/long, đây sẽ là một phần cắt ngắn trong Python2

Tương tự như vậy easeOutQuad sẽ

def easeOutQuad (x, t, b, c, d): 
    t /= d 
    return -c * t * (t - 2) + b 
+1

JavaScript có xác định khi nào việc gán cho t xảy ra không? Việc sử dụng toán tử '/ =' làm tôi lo lắng. – mkb

+2

Không, không phải. 't = t/d' được đánh giá trước! – Bergi

+0

@Bergi, ok, hãy để tôi sửa lỗi –