Giới thiệu về Python

Lời mở đầu

Chào mừng bạn đến với hướng dẫn trực tuyến về Python của Google. Chương trình này dựa trên khoá học Python nhập môn được 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ử các khoá học của 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 muốn học trực tuyến theo tốc độ của riêng mình mà không phải xem video, hãy thử xem các video trong danh sách ở cuối bài đăng này. Mỗi tính năng sẽ có một nội dung học tập cũng như một trình thông dịch tương tác Python mà bạn có thể thực hành. "Diễn giải" mà chúng tôi đề cập đến là gì? Bạn sẽ được tìm hiểu trong phần tiếp theo!

Giới thiệu ngôn ngữ

Python là một ngôn ngữ động, thông dịch (được biên dịch bằng mã byte). Không có phần khai báo kiểu biến, tham số, hàm hoặc phương thức trong mã nguồn. Điều này làm cho mã ngắn và linh hoạt, đồng thời bạn sẽ mất việc kiểm tra loại thời gian biên dịch của mã nguồn. Python theo dõi các loại 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 phiên dịch Python và nhập mã ngay vào đó. Nếu bạn đã từng có câu hỏi như "Điều gì sẽ xảy ra nếu tôi thêm int vào list?" Chỉ cần nhập câu hỏi đó vào trình phiên dịch Python là cách nhanh chóng và có thể là cách tốt nhất để xem điều gì sẽ xảy ra. (Xem bên dưới để xem đ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 lệnh 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à nơi xây dựng nó. Các ví dụ này sẽ phù hợp với bạn, miễn là nội dung đầu tiên được xuất ra là "Python 3".

Như bạn có thể thấy ở trên, bạn có thể dễ dàng thử nghiệm các biến và toán tử. Ngoài ra, trình thông dịch sẽ gửi hoặc "tăng" theo cách nói Python, một lỗi thời gian chạy nếu mã cố gắng đọc một biến chưa được chỉ định giá trị. Giống như C++ và Java, Python phân biệt chữ hoa chữ thường nên "a" và "A" là các biến khác nhau. Kết thúc dòng đánh dấu sự kết thúc của một 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

Các tệp nguồn Python sử dụng đuôi ".py" và được gọi là "modules". Với mô-đun Python hello.py, cách dễ nhất để chạy mô-đun này là 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 vào đối số dòng lệnh "Alice". Hãy xem trang tài liệu chính thức để biết 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 (hãy lưu ý rằng các khối mã được phân tách bằng cách sử dụng thụt đầu dòng thay vì dấu ngoặc nhọn một cách nghiêm ngặt – sẽ nói thêm về điều này ở 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()

Quá trình chạy chương trình này từ dòng lệnh sẽ có dạng như sau:

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

Dữ liệu nhập, đối số dòng lệnh và len()

Các câu lệnh ngoài cùng trong tệp Python, hay còn gọi là "mô-đun", thực hiện quy trình 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 ở đâu đó, thiết lập các biến và hàm của mô-đun. Mô-đun Python có thể chạy trực tiếp – như ở trên python3 hello.py Bob – hoặc có thể được một số mô-đun khác nhập và sử dụng. Khi một tệp Python chạy trực tiếp, biến đặc biệt "__name__" sẽ được đặt thành "__main__". Do đó, thông thường, bạn sẽ dùng if __name__ ==... nguyên mẫu như trên để gọi hàm main() khi mô-đun chạy trực tiếp, chứ không phải khi mô-đun được nhập bởi một số mô-đun khác.

Trong một chương trình Python tiêu chuẩn, danh sách sys.argv chứa các đối số dòng lệnh theo cách tiêu 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 một chuỗi. Nhìn chung, len() có thể cho bạn biết độ dài của một chuỗi, số phần tử trong danh sách và bộ dữ liệu (một cấu trúc dữ liệu khác giống mảng) và số cặp khoá-giá trị trong từ điển.

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

Các hàm trong Python được định nghĩa 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 tất cả có cùng mức thụt đầu dòng. 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 tốt vì đây là toán tử "lặp lại" của Python, có nghĩa là '-' * 10 cung cấp cho '----------', một cách gọn gàng để tạo một "dòng" trên màn hình. Trong phần chú thích mã, chúng tôi gợi ý rằng * hoạt động nhanh hơn +, lý do là * tính 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ả hai + và * đều được gọi là toán tử "overload" (quá tải) vì chúng có ý nghĩa khác nhau đối với số và cho chuỗi (và các kiểu dữ liệu khác).

Từ khoá def xác định hàm bằng các tham số 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. Chuỗi tài liệu có thể là một dòng hoặc nhiều dòng mô tả như trong ví dụ trên. (Đúng, đó là "dấu ngoặc kép 3 lần", một tính năng chỉ có trên 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 hàm khác. Câu lệnh return có thể nhận một đối số, trong trường hợp đó, đó là giá trị được trả về cho phương thức gọi.

Đây là mã gọi hàm repeat() ở trên để in 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 lệnh "def" trước khi chúng được gọi. Thường thì bạn nên định nghĩa một hàm main() ở cuối tệp bằng các hàm mà hàm đó gọi phía trên nó.

Thụt lề

Một tính năng bất thường của Python là thụt đầu dòng bằng khoảng trắng của một đoạn mã ảnh hưởng đến ý nghĩa của đoạn mã. 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, đều phải có cùng khoảng thụt đầu dòng, được đặt từ khoảng thụt đầu dòng 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 nhóm có mức thụt lề khác, thì dòng đó sẽ bị gắn cờ là lỗi cú pháp.

Việc Python sử dụng khoảng trắng thoạt đầu có vẻ hơi lạ, nhưng nó logic và tôi nhận thấy tôi đã nhanh chóng làm quen với nó. Tránh sử dụng TAB vì chúng làm phức tạp đáng kể quá trình thụt lề (chưa kể đến TAB có thể có ý nghĩa khác nhau 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ì TABs cho mã Python.

Một câu hỏi mà người mới bắt đầu thường đặt ra 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 văn phong nội bộ của Google chỉ ra thụt lề 2 dấu cách!)

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

Python thực hiện rất ít kiểm tra tại thời điểm biên dịch, trì hoãn hầu hết các loại, tên, v.v. kiểm tra trên mỗi dòng cho đến khi dòng đó chạy. Giả sử các lệnh 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 là 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(), hệ thống mới nhận thấy rằng không có hàm nào như vậy và phát sinh lỗi. Ngoài ra còn có lỗi thứ hai trong đoạn mã này. name chưa được gán giá trị trước khi được 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. Đây là một số ví dụ minh hoạ rằng trong lần đầu chạy chương trình Python, một số lỗi đầu tiên bạn gặp sẽ là lỗi chính tả đơn giản hoặc biến chưa khởi tạo giống như các lỗi này. Đâ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 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ề loại đó ... đó là một sự đánh đổi).

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

Tên biến

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

Theo cách đặt tên thực tế, một số ngôn ngữ thích dùng dấu gạch dưới cho các tên biến được tạo thành từ "nhiều từ", nhưng các ngôn ngữ khác lại thích sử dụng kiểu lạc đà (camelCasing). Nói chung, Python ưu tiên phương thức dấu gạch dưới nhưng hướng dẫn các nhà phát triển tuân theo quy tắc camelCasing nếu tích hợp vào mã Python hiện có đã sử dụng kiểu đó. Số lượng mức độ dễ đọc. Vui lòng đọc thêm trong phần về quy ước đặt tên trong PEP 8.

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

Thông tin thêm 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 các hàm và biến của chúng theo bất cứ cách nào họ 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 tôi sẽ nói rằng binky, module1 và module2 đều có "không gian tên" riêng mà bạn có thể đoán là các liên kết tên biến đổi với đối tượng.

Ví dụ: chúng ta có mô-đun "sys" tiêu chuẩn chứa một số tiện ích hệ thống tiêu chuẩn, chẳng hạn như danh sách argv và hàm exit(). Với câu lệnh "import sys", sau đó 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 này làm cho argv và exit() sử dụng tên ngắn; tuy nhiên, bạn nên dùng biểu mẫu gốc với các tên đủ điều kiện vì việc xác định nguồn hoặc thuộc tính đến từ đâu sẽ dễ dàng hơn nhiều.

Có nhiều mô-đun và gói đi kèm với bản cài đặt tiêu chuẩn của trình thông dịch Python, vì vậy, bạn không phải làm gì thêm để sử dụng chúng. Những thư viện này được gọi chung là "Thư viện chuẩn Python". Các mô-đun/gói thường được sử 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 của 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.

  • Thực hiện tìm kiếm trên Google, bắt đầu bằng từ "python", chẳng hạn như "python list" hoặc "python string thun" (danh sách python chữ thường). Lượt truy cập đầu tiên thường là câu trả lời. Kỹ thuật này có vẻ hiệu quả đối với Python hơn so với các ngôn ngữ khác vì một số lý do.
  • Trang web chính thức về tài liệu Python – docs.python.org – có các tài liệu chất lượng cao. Tuy nhiên, tôi thường tìm kiếm trên Google một vài từ để làm việc nhanh hơn.
  • Ngoài ra, chúng tôi còn có một danh sách gửi thư chính thức cho Gia sư 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.
  • Hãy dùng 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 các chuỗi tài liệu cho nhiều mô-đun, hàm và phương thức lên. 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 hàm trợ giúp() và dir() qua trình thông dịch:

  • help(len) – chuỗi trợ giúp cho hàm len() tích hợp sẵn; lưu ý rằng đó là "len" chứ không phải "len()", đây là 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() có dạng như help() nhưng chỉ đưa ra một danh sách nhanh gồm những ký hiệu hoặc "thuộc tính" được xác đị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() dành cho đối tượng chuỗi. Bạn có thể gọi help() bằng chính đối tượng đó hoặc bằng ví dụ về đối tượng đó, cùng với thuộc tính của đối tượng đó. Ví dụ: cách gọi help('xyz'.split) cũng giống như cách 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 của đố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 đối tượng list