Hướng dẫn python static typing performance

Python is dynamically typed, so it can store different types. This makes code easier to write, but also slower.

You seem to assume that Python is slow because of its dynamic nature. I'd say that belies a fundamental misunderstanding: speed and performance are not features of the language but of its implementations. Yes, the attributes of a language might make it easier or harder to write a performant implementation — but that only matters to those implementing the language.

As an example, several very fast implementations of JavaScript exist. Simply put, some very clever people put quite a lot of effort into wringing every little bit of performance out of it — even though doing so was very hard due to the idiosyncrasies of the language and its highly dynamic nature. As a result, many now consider it a “fast” language.

So, why is Python slow? Probably because you're using its reference implementation, CPython, which is indeed a rather slow and straightforward interpreter. PyPy, on the other hand, offers a modern Just-in-Time compiler, making raw, repetitive Python code run much faster.

Oh, and even the implementations of “fast” languages perform many tricks nowadays, whether performing compilation ahead of time or not. There's nothing straightforward about what a C compiler or the JVM does to make code run fast.

(Lua might be a different case, but I don't know all that much about it.)

Khi mình quyết định mình phải hiểu điều gì đó, mình bị ám ảnh cho đến khi cuối cùng mình hiểu ra.

Và gần đây nhất, mình quyết định phải hiểu Static với Dynamic Typing.

Mình cũng đã tìm kiếm các câu trả lời trên Stack Overflow nhưng các giải thích về Static Dynamic gây nhầm lẫn, dài và thậm chí trái ngược nhau.

Hướng dẫn python static typing performance

Static Vs Dynamic

Hóa ra những thuật ngữ này cũng rất thường bị hiểu lầm, vì thế, quá trình tìm kiếm của mình gặp khá nhiều khó khăn.

Do đó,

Mình đọc bất cứ thứ gì mình có thể tìm thấy nhưng vẫn chưa có gì có thể giải thích thật ngắn gọn, súc tích để mình hiểu được.

Nhưng cuối cùng mình đã ngộ đạo.

Và bây giờ mình sẽ giải thích cho bạn theo cách mà mình đã ngộ ra.

Được biên dịch so với thông dịch

Mã chúng ta viết máy không thể hiểu được.

Do đó, để chạy được, mã cần phải được dịch cho máy hiểu.

Vậy,

khi nào mã được dịch?

  • Source Code: Mã nguồn (Đây là các đoạn mã bạn viết)
  • Translation: Chuyển đổi mã nguồn thành thứ mà máy tính có thể đọc (nghĩa là mã máy.
  • Run-time: Khoảng thời gian khi chương trình đang thực thi các lệnh (sau khi biên dịch, nếu nó được biên dịch)
  • Compiled (Biên dịch): Mã được dịch trước khi tiến hành thực thi (run-time)
  • Interpreted (Thông dịch): Mã được dịch khi đang thực thi

Typing là gì?

Khi nào các kiểu được kiểm tra??

"3" + 5 sẽ gây ra lỗi trong ngôn ngữ kiểu strong type, như Java.

Bởi vì ngôn ngữ kiểu strong type không cho phép "ép buộc kiểu" (tự thay đổi kiểu giá trị trong bối cảnh nhất định)

Nhưng trong ngôn ngữ kiểu Weakly type như JavaScript thì lỗi không xảy ra, bạn nhận được kết quả là '35'

  • Static: Kiểm tra kiểu trước thời gian thực thi
  • Dynamic: Kiểm được kiểm tra khi đang thực thi

Các định nghĩa của "Static vs Compiled" và "Dynamic & Interpreted" được giải thích trên google khá giống nhau nhưng bạn chỉ cần nhớ:

  • Khi nào mã được dịch?
  • Khi nào kiểu được kiểm tra?

Lưu ý!

Kiểm tra kiểu không liên quan gì đến ngôn ngữ được biên dịch hoặc thông dịch! Bạn cần tách các thuật ngữ này về mặt khái niệm.

Ví dụ với ngôn ngữ Python

Kết hợp Dynamic và Thông dịch


def myFunction(a):
    if a > 0:
        print ("Xin chào")
    else:
        print ("3" + 5)

myFunction(2)

Bởi vì Python được thông dịch và dynamic, nó chỉ dịch và kiểm tra kiểu mã mà nó thực thi.

Thế nên,

Khi gọi myFuntion(2)

Khối else

không bao giờ thực thi, vì vậy "3" + 5 thậm chí không bao giờ được xem xét đến!

Vậy, sẽ ra sao nếu nó là kiểu static?

Một lỗi kiểu sẽ được ném ra trước khi mã chạy.

Nó vẫn thực hiện kiểm tra kiểu trước run-time mặc dù nó được thông dịch.

Vậy, nếu nó được biên dịch thì sao?

Nếu được biên dịch.

Khối else sẽ được dịch / xem xét trước run-time, nhưng vì nó là kiểu dynamic nên nó sẽ không gây ra lỗi.

Vì các ngôn ngữ kiểu Dynamic không kiểm tra các kiểu cho đến khi thực thi và dòng đó không bao giờ thực thi.

Ví dụ với ngôn ngữ Go

Kết hợp kiểu Static với Biên dịch.

package mainimport ("fmt")
func myFunc(a int) {
  if (a > 0) {
      fmt.Println("Xin chào")
  } else {
      fmt.Println("3" + 5)
  }
}
myFunc main() {
  foo(2)
}

Các kiểu được kiểm tra trước khi chạy (static) và lỗi kiểu (type error) ngay lập tức bị bắt!

Các kiểu vẫn sẽ được kiểm tra trước run-time nếu nó được thông dịch, và kết quả tương tự.

Nếu nó là dynamic, nó sẽ không ném bất kỳ lỗi nào mặc dù mã sẽ được xem xét trong quá trình biên dịch.

So sánh về hiệu suất

Một ngôn ngữ được biên dịch sẽ có hiệu suất tốt hơn trong run-time nếu nó viết kiểu static bởi vì thông tin về kiểu giúp tối ưu mã máy.

Các ngôn ngữ được viết kiểu static có hiệu suất tốt hơn vào run-time về bản chất do không cần phải kiểm tra các kiểu trong khi thực thi (nó đã kiểm tra trước khi chạy).

Tương tự, các ngôn ngữ được biên dịch sẽ nhanh hơn trong run-time vì mã đã được dịch thay vì cần phải thông dịch tại thời điểm run-time.

Giống như bạn có thể nghe hiểu ngoại ngữ khi giao tiếp so với phải nghe qua phiên dịch vậy.

Lưu ý rằng cả hai ngôn ngữ được biên dịch và static sẽ có độ trễ trước khi chạy để dịch và kiểm tra kiểu.

Java là một điển hình về ngôn ngữ được biên dịch và kiểu static do đó hiệu suất của Java rất cao và rất nhiều người chọn Học Java vì điều này.

Một điều khác biệt nữa giữa kiểu Static và Dynamic

Kiểu static bắt lỗi sớm, thay vì tìm thấy chúng trong khi run-time (đặc biệt hữu ích đối với các chương trình lớn).

Nói cách khác, nó nghiêm ngặt hơn kiểu Dynamic.

Nó không cho phép lỗi kiểu ở bất cứ đâu trong chương trình của bạn và thường ngăn các biến tự thay đổi kiểu dữ liệu.

Điều này góp phần kiểm soát các lỗi ngoài ý muốn khi lập trình.

num = 2
num = '3' // ERROR

Kiểu Dynamic linh hoạt hơn giúp tăng hiệu suất công việc cũng như dễ học hơn.

Nhưng kiểu Dynamic không tường minh, nó cho phép các biến tự thay đổi kiểu trong một số bối cảnh nhất định.

Điều này dẫn tới lỗi xảy ra ngoài ý muốn, khó kiểm soát hơn.

Bạn đã hiểu về Static và Dynamic chưa?

Nếu như bạn chưa từng học 2 ngôn ngữ này, bạn có thể sẽ hơi khó hiểu về kiểu Static Dynamic.

Nhưng mình tin rằng, chỉ cần trả lời được hai câu hỏi "

Khi nào mã được dịch?" và "Khi nào các kiểu được kiểm tra?"

Là bạn sẽ hiểu về Static và Dynamic ngay thôi.

---

HỌC VIỆN ĐÀO TẠO CNTT NIIT - ICT HÀ NỘI

Dạy học Lập trình chất lượng cao (Since 2002). Học làm Lập trình viên. Hành động ngay!

Đc: Tầng 3, 25T2, N05, Nguyễn Thị Thập, Cầu Giấy, Hà Nội

SĐT: 02435574074 - 0914939543 - 0353655150 

Email:

Fanpage: https://facebook.com/NIIT.ICT/

#niit #niithanoi niiticthanoi #hoclaptrinh #khoahoclaptrinh #hoclaptrinhjava #hoclaptrinhphp #java #php #python