Giới thiệu về Python

Prelude

Chào mừng bạn đến với hướng dẫn trực tuyến về Python của Google. Khoá học này dựa trên khoá học nhập môn về Python do chúng tôi cung cấp nội bộ. Như đã đề cập trên trang thiết lập, tài liệu này đề cập đến Python 3.

Nếu bạn đang tìm một khoá học MOOC đồng hành, hãy thử những khoá học ở Udacity và Coursera (giới thiệu về lập trình [người mới bắt đầu] hoặc giới thiệu về Python). Cuối cùng, nếu bạn đang tìm cách học trực tuyến theo tiến độ riêng mà không xem video, hãy thử những cách được liệt kê ở cuối bài đăng này. Mỗi tính năng có nội dung học tập và một trình thông dịch viên có tính tương tác cho Python mà bạn có thể thực hành. "Trình thông dịch" mà chúng ta đề cập đến là gì? Bạn sẽ tìm hiểu trong phần tiếp theo!

Giới thiệu về ngôn ngữ

Python là một ngôn ngữ động, được diễn giải (biên dịch mã byte). Không có nội dung khai báo loại biến, tham số, hàm hoặc phương thức trong mã nguồn. Điều này giúp mã ngắn gọn và linh hoạt, đồng thời bạn sẽ mất tính năng kiểm tra kiểu thời gian biên dịch của mã nguồn. Python theo dõi loại của tất cả giá trị trong thời gian chạy và gắn cờ mã không có ý nghĩa khi chạy.

Một cách tuyệt vời để xem cách hoạt động của mã Python là chạy trình thông dịch Python và nhập mã ngay vào trình thông dịch đó. Nếu bạn có câu hỏi như "Điều gì sẽ xảy ra nếu tôi thêm int vào list?", thì chỉ cần nhập câu hỏi đó vào trình thông dịch Python là cách nhanh nhất và có thể là cách tốt nhất để xem điều gì sẽ xảy ra. (Xem phần dưới đây để biết điều gì thực sự xảy ra!)

$ python3        ## Run the Python interpreter
Python 3.X.X (XXX, XXX XX XXXX, XX:XX:XX) [XXX] on XXX
Type "help", "copyright", "credits" or "license" for more information.
>>> a = 6       ## set a variable in this interpreter session
>>> a           ## entering an expression prints its value
6
>>> a + 2
8
>>> a = 'hi'    ## 'a' can hold a string just as well
>>> a
'hi'
>>> len(a)      ## call the len() function on a string
2
>>> a + len(a)  ## try something that doesn't work
Traceback (most recent call last):
  File "", line 1, in 
TypeError: can only concatenate str (not "int") to str
>>> a + str(len(a))  ## probably what you really wanted
'hi2'
>>> foo         ## try something else that doesn't work
Traceback (most recent call last):
  File "", line 1, in 
NameError: name 'foo' is not defined
>>> ^D          ## type CTRL-d to exit (CTRL-z in Windows/DOS terminal)

Hai dòng python in sau khi bạn nhập python và trước lời nhắc >>> cho bạn biết về phiên bản python bạn đang sử dụng và vị trí tạo phiên bản đó. Miễn là nội dung đầu tiên được in là "Python 3.", những ví dụ này sẽ phù hợp với bạn.

Như bạn có thể thấy ở trên, bạn có thể dễ dàng thử nghiệm với các biến và toán tử. Ngoài ra, trình thông dịch sẽ gửi ra (hoặc " chất lên") theo cách nói của Python, là một lỗi thời gian chạy nếu mã cố gắng đọc một biến chưa được gán giá trị. Giống như C++ và Java, Python phân biệt chữ hoa chữ thường nên "a" và "A" là hai biến khác nhau. Cuối dòng đánh dấu kết thúc câu lệnh, vì vậy, không giống như C++ và Java, Python không yêu cầu dấu chấm phẩy ở cuối mỗi câu lệnh. Nhận xét bắt đầu bằng dấu "#" và kéo dài đến cuối dòng.

Mã nguồn Python

Tệp nguồn Python sử dụng đuôi ".py" và được gọi là "mô-đun". Với mô-đun Python hello.py, cách dễ nhất để chạy mô-đun này là sử dụng lệnh shell "python hello.py Alice". Lệnh này sẽ gọi trình thông dịch Python để thực thi mã trong hello.py, truyền cho mã đó đối số dòng lệnh "Alice". Hãy xem trang tài liệu chính thức về tất cả các tuỳ chọn mà bạn có khi chạy Python từ dòng lệnh.

Đây là một chương trình hello.py rất đơn giản (lưu ý rằng các khối mã được phân tách nghiêm ngặt bằng dấu thụt đầu dòng thay vì dấu ngoặc nhọn – bạn sẽ tìm hiểu thêm ở phần sau!):

#!/usr/bin/python3

# import modules used here -- sys is a very standard one
import sys

# Gather our code in a main() function
def main():
    print('Hello there', sys.argv[1])
    # Command line args are in sys.argv[1], sys.argv[2] ...
    # sys.argv[0] is the script name itself and can be ignored

# Standard boilerplate to call the main() function to begin
# the program.
if __name__ == '__main__':
    main()

Cách chạy chương trình này từ dòng lệnh như sau:

$ python3 hello.py Guido
Hello there Guido
$ ./hello.py Alice  ## without needing 'python3' first (Unix)
Hello there Alice

Nội dung nhập, Đối số dòng lệnh và len()

Các câu lệnh ngoài cùng trong tệp Python hoặc "mô-đun" sẽ thực hiện việc thiết lập một lần — các câu lệnh đó chạy từ trên xuống dưới trong lần đầu tiên mô-đun được nhập vào một nơi nào đó, thiết lập các biến và hàm của mô-đun. Bạn có thể chạy trực tiếp một mô-đun Python (như python3 hello.py Bob ở trên) hoặc nhập và sử dụng mô-đun đó bằng một số mô-đun khác. Khi một tệp Python chạy trực tiếp, biến đặc biệt "__name__" được đặt thành "__main__". Do đó, thông thường, if __name__ ==... nguyên mẫu sẽ được hiển thị ở trên để gọi hàm main() khi chạy mô-đun trực tiếp, chứ không phải khi mô-đun được một số mô-đun khác nhập.

Trong một chương trình Python chuẩn, danh sách sys.argv chứa các đối số dòng lệnh theo cách chuẩn với sys.argv[0] là chính chương trình, sys.argv[1] là đối số đầu tiên, v.v. Nếu biết về argc hoặc số lượng đối số, bạn chỉ cần yêu cầu giá trị này từ Python bằng len(sys.argv), giống như cách chúng ta đã làm trong mã thông dịch tương tác ở trên khi yêu cầu độ dài của chuỗi. Nhìn chung, len() có thể cho bạn biết độ dài của một chuỗi, số lượng phần tử trong danh sách và các bộ dữ liệu (một cấu trúc dữ liệu khác giống như mảng) cũng như số lượng cặp khoá-giá trị trong từ điển.

Hàm do người dùng xác định

Hàm trong Python được xác định như sau:

# Defines a "repeat" function that takes 2 arguments.
def repeat(s, exclaim):
    """
    Returns the string 's' repeated 3 times.
    If exclaim is true, add exclamation marks.
    """

    result = s + s + s # can also use "s * 3" which is faster (Why?)
    if exclaim:
        result = result + '!!!'
    return result

Ngoài ra, hãy lưu ý cách các dòng tạo nên hàm hoặc câu lệnh if được nhóm lại với nhau bằng cách tất cả đều có cùng cấp độ thụt lề. Chúng tôi cũng đã trình bày 2 cách lặp lại chuỗi, sử dụng toán tử + thân thiện hơn với người dùng, nhưng * cũng hoạt động vì đây là toán tử "lặp lại" của Python, nghĩa là '-' * 10 cho '----------', một cách gọn gàng để tạo "dòng" trên màn hình. Trong chú thích mã, chúng tôi đã gợi ý rằng * hoạt động nhanh hơn +, lý do là * tính toán kích thước của đối tượng kết quả một lần, trong khi với +, phép tính đó được thực hiện mỗi khi + được gọi. Cả + và * đều được gọi là toán tử "nạp chồng" vì chúng có ý nghĩa khác nhau đối với số và chuỗi (cũng như các loại dữ liệu khác).

Từ khoá def xác định hàm có các tham số nằm trong dấu ngoặc đơn và mã được thụt lề. Dòng đầu tiên của hàm có thể là một chuỗi tài liệu ("docstring") mô tả chức năng của hàm. Dòng mô tả có thể là một dòng hoặc nội dung mô tả nhiều dòng như trong ví dụ trên. (Đúng, đó là "dấu ngoặc kép", một tính năng chỉ có ở Python!) Các biến được xác định trong hàm là cục bộ của hàm đó, do đó "kết quả" trong hàm trên tách biệt với biến "kết quả" trong một hàm khác. Câu lệnh return có thể nhận một đối số, trong trường hợp đó, giá trị được trả về cho phương thức gọi.

Dưới đây là mã gọi hàm repeat() ở trên, in ra nội dung trả về:

def main():
    print(repeat('Yay', False))      ## YayYayYay
    print(repeat('Woo Hoo', True))   ## Woo HooWoo HooWoo Hoo!!!

Trong thời gian chạy, các hàm phải được xác định bằng cách thực thi "def" trước khi chúng được gọi. Thông thường, bạn sẽ khai báo hàm main() ở cuối tệp với các hàm mà hàm này gọi ở phía trên.

Thụt lề

Một đặc điểm bất thường của Python là khoảng trắng thụt lề của một đoạn mã ảnh hưởng đến ý nghĩa của đoạn mã đó. Một khối logic của các câu lệnh, chẳng hạn như các câu lệnh tạo nên một hàm, phải có cùng một khoảng thụt lề, được đặt từ khoảng thụt lề của hàm mẹ hoặc "if" hoặc bất kỳ câu lệnh nào khác. Nếu một trong các dòng trong một nhóm có dấu thụt lề khác, thì dòng đó sẽ bị gắn cờ là lỗi cú pháp.

Việc sử dụng khoảng trắng của Python có vẻ hơi lạ lúc đầu, nhưng nó rất hợp lý và tôi thấy mình đã nhanh chóng quen với việc này. Tránh sử dụng TAB vì chúng làm phức tạp hoá đáng kể lược đồ thụt lề (chưa kể đến việc TAB có thể có nhiều nghĩa trên các nền tảng khác nhau). Thiết lập trình chỉnh sửa của bạn để chèn dấu cách thay vì TAB đối với mã Python.

Một câu hỏi thường gặp của người mới bắt đầu là "Tôi nên thụt lề bao nhiêu dấu cách?" Theo hướng dẫn quy tắc Python chính thức (PEP 8), bạn nên thụt lề 4 dấu cách. (Thông tin thú vị: Nguyên tắc nội bộ của Google quy định cách thụt lề bằng 2 dấu cách!)

Đã kiểm tra mã trong thời gian chạy

Python thực hiện rất ít hoạt động kiểm tra tại thời điểm biên dịch, trì hoãn hầu hết các hoạt động kiểm tra loại, tên, v.v. trên mỗi dòng cho đến khi dòng đó chạy. Giả sử main() ở trên gọi repeat() như sau:

def main():
    if name == 'Guido':
        print(repeeeet(name) + '!!!')
    else:
        print(repeat(name))

Câu lệnh if chứa một lỗi rõ ràng, trong đó hàm repeat() vô tình được nhập dưới dạng repeeeet(). Điều thú vị trong Python ... mã này biên dịch và chạy tốt miễn là tên trong thời gian chạy không phải là "Guido". Chỉ khi một lần chạy thực sự cố gắng thực thi repeeeet(), thì lần chạy đó mới nhận thấy không có hàm như vậy và báo lỗi. Ngoài ra, còn có một lỗi thứ hai trong đoạn mã này. tên chưa được chỉ định giá trị trước khi so sánh với 'Guido'. Python sẽ báo lỗi "NameError" nếu bạn cố gắng đánh giá một biến chưa được chỉ định. Sau đây là một số ví dụ minh hoạ rằng khi bạn chạy chương trình Python lần đầu tiên, một số lỗi đầu tiên bạn thấy sẽ là lỗi chính tả đơn giản hoặc các biến chưa được khởi tạo như sau. Đây là một lĩnh vực mà các ngôn ngữ có hệ thống kiểu chi tiết hơn, như Java, có lợi thế ... chúng có thể phát hiện được các lỗi như vậy tại thời điểm biên dịch (nhưng tất nhiên bạn phải duy trì tất cả thông tin về kiểu đó ... đó là một sự đánh đổi).

Python 3 đã giới thiệu gợi ý kiểu. Gợi ý kiểu cho phép bạn chỉ định loại của từng đối số trong một hàm cũng như loại của đối tượng mà hàm trả về. Ví dụ: trong hàm được chú thích def is_positive(n: int) -> bool:, đối số nint và giá trị trả về là bool. Chúng ta sẽ tìm hiểu ý nghĩa của các loại này sau. Tuy nhiên, gợi ý kiểu là hoàn toàn không bắt buộc. Bạn sẽ thấy ngày càng nhiều mã sử dụng gợi ý kiểu vì nếu bạn sử dụng các gợi ý kiểu này, một số trình chỉnh sửa như cider-v và VS.code có thể chạy các bước kiểm tra để xác minh rằng các hàm của bạn được gọi bằng các loại đối số phù hợp. Thậm chí, các tính năng này còn có thể đề xuất và xác thực đối số khi bạn chỉnh sửa mã. Hướng dẫn này sẽ không đề cập đến gợi ý kiểu dữ liệu, nhưng chúng tôi muốn đảm bảo rằng bạn biết về các gợi ý kiểu dữ liệu nếu nghe thấy hoặc thấy các gợi ý kiểu dữ liệu trong thực tế.

Tên biến

Vì các biến Python không có loại nào được viết trong mã nguồn, nên việc đặt tên có ý nghĩa cho các biến sẽ rất hữu ích để nhắc bạn về những gì đang diễn ra. Vì vậy, hãy sử dụng "name" nếu là tên đơn lẻ và "name" nếu là danh sách tên và "tuples" nếu là danh sách các bộ dữ liệu. Nhiều lỗi Python cơ bản là do quên loại giá trị trong mỗi biến, vì vậy, hãy sử dụng tên biến (tất cả những gì bạn có) để giúp mọi thứ trở nên rõ ràng.

Đối với việc đặt tên thực tế, một số ngôn ngữ ưu tiên underscore_parts cho tên biến bao gồm "nhiều từ", nhưng các ngôn ngữ khác lại ưu tiên camelCasing. Nhìn chung, Python ưu tiên phương thức dấu gạch dưới nhưng sẽ hướng dẫn nhà phát triển tuân theo camelCasing nếu tích hợp vào mã Python hiện có đã sử dụng kiểu đó. Mức độ dễ đọc rất quan trọng. Đọc thêm trong phần về quy ước đặt tên trong PEP 8.

Như bạn có thể đoán, các từ khoá như "if" và "while" không được dùng làm tên biến — bạn sẽ gặp lỗi cú pháp nếu làm như vậy. Tuy nhiên, hãy cẩn thận không sử dụng các hàm tích hợp sẵn làm tên biến. Ví dụ: mặc dù "str", "list" và "print" có vẻ giống như các tên hay nhưng bạn sẽ ghi đè các biến hệ thống đó. Các thành phần tích hợp không phải là từ khoá, do đó, các nhà phát triển Python mới có thể vô tình sử dụng.

Thông tin khác về Mô-đun và Không gian tên của mô-đun

Giả sử bạn có một mô-đun "binky.py" chứa "def foo()". Tên đủ điều kiện của hàm foo đó là "binky.foo". Bằng cách này, các mô-đun Python khác nhau có thể đặt tên cho hàm và biến theo ý muốn, đồng thời tên biến sẽ không xung đột — module1.foo khác với module2.foo. Trong từ vựng Python, chúng ta có thể nói rằng binky, module1 và module2 đều có "không gian tên" riêng. Như bạn có thể đoán, đó là các liên kết tên biến với đối tượng.

Ví dụ: chúng ta có mô-đun "sys" chuẩn chứa một số cơ sở hệ thống chuẩn, chẳng hạn như danh sách argv và hàm exit(). Với câu lệnh "import sys", bạn có thể truy cập vào các định nghĩa trong mô-đun sys và cung cấp các định nghĩa đó theo tên đủ điều kiện, ví dụ: sys.exit(). (Có, "sys" cũng có không gian tên!)

  import sys

  # Now can refer to sys.xxx facilities
  sys.exit(0)

Có một biểu mẫu nhập khác giống như sau: "from sys import argv, exit". Điều đó giúp argv và exit() có sẵn theo tên ngắn; tuy nhiên, bạn nên sử dụng biểu mẫu ban đầu với các tên đủ điều kiện vì sẽ dễ dàng hơn rất nhiều trong việc xác định nguồn gốc của một hàm hoặc thuộc tính.

Có nhiều mô-đun và gói được đóng gói cùng với quá trình cài đặt trình thông dịch Python chuẩn, vì vậy, bạn không cần làm gì thêm để sử dụng các mô-đun và gói đó. Các hàm này được gọi chung là "Thư viện chuẩn Python". Các mô-đun/gói thường dùng bao gồm:

  • sys – truy cập vào exit(), argv, stdin, stdout, ...
  • re — biểu thức chính quy
  • os — giao diện hệ điều hành, hệ thống tệp

Bạn có thể tìm thấy tài liệu về tất cả các mô-đun và gói Thư viện chuẩn tại http://docs.python.org/library.

Trợ giúp trực tuyến, help()dir()

Có nhiều cách để yêu cầu trợ giúp về Python.

  • Tìm kiếm trên Google, bắt đầu bằng từ "python", chẳng hạn như "danh sách python" hoặc "chuỗi python viết thường". Lần truy cập đầu tiên thường là câu trả lời. Vì một số lý do, kỹ thuật này có vẻ hoạt động hiệu quả hơn cho Python so với các ngôn ngữ khác.
  • Trang web tài liệu chính thức của Python – docs.python.org – có tài liệu chất lượng cao. Tuy nhiên, tôi thường thấy việc tìm kiếm một vài từ trên Google sẽ nhanh hơn.
  • Ngoài ra, còn có danh sách gửi thư chính thức của Người hướng dẫn dành riêng cho những người mới làm quen với Python và/hoặc lập trình!
  • Bạn có thể tìm thấy nhiều câu hỏi (và câu trả lời) trên StackOverflowQuora.
  • Sử dụng các hàm help() và dir() (xem bên dưới).

Bên trong trình thông dịch Python, hàm help() sẽ kéo lên chuỗi tài liệu cho nhiều mô-đun, hàm và phương thức. Các chuỗi tài liệu này tương tự như javadoc của Java. Hàm dir() cho bạn biết các thuộc tính của một đối tượng. Dưới đây là một số cách gọi help() và dir() từ trình thông dịch:

  • help(len) – chuỗi trợ giúp cho hàm len() tích hợp; lưu ý rằng chuỗi này là "len" chứ không phải "len()", đây là một lệnh gọi đến hàm mà chúng ta không muốn
  • help(sys) – chuỗi trợ giúp cho mô-đun sys (phải thực hiện import sys trước)
  • dir(sys)dir() giống như help() nhưng chỉ cung cấp một danh sách nhanh các ký hiệu đã xác định hoặc "thuộc tính"
  • help(sys.exit) – chuỗi trợ giúp cho hàm exit() trong mô-đun sys
  • help('xyz'.split) – chuỗi trợ giúp cho phương thức split() cho các đối tượng chuỗi. Bạn có thể gọi help() bằng chính đối tượng đó hoặc ví dụ về đối tượng đó cùng với thuộc tính của đối tượng đó. Ví dụ: việc gọi help('xyz'.split) cũng giống như việc gọi help(str.split).
  • help(list) – chuỗi trợ giúp cho các đối tượng list
  • dir(list) – hiển thị các thuộc tính đối tượng list, bao gồm cả các phương thức của đối tượng đó
  • help(list.append) – chuỗi trợ giúp cho phương thức append() dành cho các đối tượng list