Mục lục bài viết:
- Cú pháp không hợp lệ trong Python
- SyntaxError Exception và Traceback
- Các vấn đề về cú pháp thường gặp
- Lạm dụng Toán tử Chuyển nhượng [=]
- Từ khóa Python sai chính tả, thiếu hoặc sử dụng sai
- Thiếu dấu ngoặc đơn, dấu ngoặc đơn và dấu ngoặc kép
- Sai cú pháp từ điển
- Sử dụng thụt lề sai
- Xác định và gọi các chức năng
- Thay đổi phiên bản Python
- Phần kết luận
Python được biết đến với cú pháp đơn giản. Tuy nhiên, khi bạn học Python lần đầu tiên hoặc khi bạn đã làm quen với Python với nền tảng vững chắc về một ngôn ngữ lập trình khác, bạn có thể gặp phải một số điều mà Python không cho phép. Nếu bạn đã từng nhận được SyntaxError
khi cố gắng chạy mã Python của mình, thì hướng dẫn
này có thể giúp bạn. Trong suốt hướng dẫn này, bạn sẽ thấy các ví dụ phổ biến về cú pháp không hợp lệ trong Python và tìm hiểu cách giải quyết vấn đề.
Đến cuối hướng dẫn này, bạn sẽ có thể:
- Xác định cú pháp không hợp lệ trong Python
- Tạo cảm giác truy
SyntaxError
ngược - Giải quyết cú pháp không hợp lệ hoặc ngăn chặn nó hoàn toàn
Cú pháp không hợp lệ trong Python
Khi bạn chạy mã Python của mình, trình thông dịch trước tiên sẽ phân tích cú pháp nó để chuyển nó thành mã byte Python, mã này sau đó sẽ thực thi. Trình thông dịch sẽ tìm thấy bất kỳ cú pháp không hợp lệ nào trong Python trong giai đoạn đầu tiên của quá trình thực thi chương trình, còn được gọi là giai đoạn phân tích cú pháp . Nếu trình thông dịch không thể phân tích cú pháp mã Python của bạn thành công, thì điều này có nghĩa là bạn đã sử dụng cú pháp không hợp lệ ở đâu đó trong mã của mình. Thông dịch viên sẽ cố gắng cho bạn biết lỗi đó xảy ra ở đâu.
Khi bạn học Python lần đầu tiên, có thể khó chịu khi nhận được một SyntaxError
. Python sẽ cố gắng giúp bạn xác định nơi cú pháp không hợp lệ là trong mã của bạn, nhưng zzztraceback nó cung cấp có thể là một chút khó hiểu. Đôi khi, mã mà nó trỏ đến là hoàn toàn tốt.
Lưu ý: Nếu mã của bạn đúng về mặt cú pháp , thì bạn có thể nhận được các ngoại lệ khác không
phải là a SyntaxError
. Để tìm hiểu thêm về các ngoại lệ khác của Python và cách xử lý chúng, hãy xem Ngoại lệ Python: Giới thiệu .
Bạn không thể xử lý cú pháp không hợp lệ trong Python như các trường hợp ngoại lệ khác. Ngay cả khi bạn đã cố gắng bọc một try
và except
chặn xung quanh mã bằng cú pháp không hợp lệ, bạn vẫn thấy trình thông dịch tăng a SyntaxError
.
SyntaxError
Exception
và Traceback
Khi trình thông dịch gặp cú pháp không hợp lệ trong mã Python, nó sẽ đưa ra một SyntaxError
ngoại lệ và cung cấp một truy xuất với một số thông tin hữu ích để giúp bạn gỡ lỗi. Đây là một số mã chứa cú pháp không hợp lệ trong Python:
1# theofficefacts.py
2ages = {
3 'pam': 24,
4 'jim': 24
5 'michael': 43
6}
7print[f'Michael is {ages["michael"]} years old.']
Bạn có thể thấy cú pháp không hợp lệ trong từ điển theo
nghĩa đen ở dòng 4. Mục nhập thứ hai 'jim'
, thiếu dấu phẩy. Nếu bạn đã cố gắng chạy mã này như hiện tại, thì bạn sẽ nhận được dấu vết sau:
$ python theofficefacts.py
File "theofficefacts.py", line 5
'michael': 43
^
SyntaxError: invalid syntax
Lưu ý rằng thông báo tìm lại lỗi định vị lỗi ở dòng 5, không phải dòng 4. Trình thông dịch Python đang cố gắng chỉ ra đâu là cú pháp không hợp lệ. Tuy nhiên, nó chỉ có thể thực sự chỉ ra nơi đầu tiên nó nhận thấy một vấn đề. Khi bạn nhận được một truy xuất SyntaxError
và mã mà truy xuất đang trỏ đến có vẻ ổn,
thì bạn sẽ muốn bắt đầu quay lại mã cho đến khi bạn có thể xác định được điều gì sai.
Trong ví dụ trên, không có vấn đề gì với việc bỏ dấu phẩy, tùy thuộc vào điều gì đứng sau dấu phẩy. Ví dụ, không có vấn đề gì với việc thiếu dấu phẩy sau 'michael'
dòng 5. Nhưng một khi trình thông dịch gặp điều gì đó không hợp lý, nó chỉ có thể chỉ cho bạn điều đầu tiên mà nó phát hiện ra rằng nó không thể hiểu được.
Có một số yếu tố của truy xuất nguồn gốc SyntaxError
có thể giúp bạn xác
định vị trí của cú pháp không hợp lệ trong mã của bạn:
- Tên tệp gặp phải cú pháp không hợp lệ
- Số dòng và dòng mã được sao chép lại nơi gặp phải sự cố
- Dấu mũ [
^
] trên dòng bên dưới mã được sao chép, cho bạn biết điểm trong mã có vấn đề - Thông báo lỗi xuất hiện sau loại ngoại lệ
SyntaxError
, có thể cung cấp thông tin để giúp bạn xác định sự cố
Trong ví dụ trên, tên tệp đã cho là theofficefacts.py
, số dòng là 5 và dấu mũ
trỏ đến dấu ngoặc kép của khóa từ điển michael
. Việc truy xuất SyntaxError
có thể không chỉ ra vấn đề thực sự, nhưng nó sẽ chỉ ra nơi đầu tiên mà trình thông dịch không thể hiểu cú pháp.
Có hai trường hợp ngoại lệ khác mà bạn có thể thấy Python tăng lên. Chúng tương đương với SyntaxError
nhưng có tên khác:
IndentationError
TabError
Cả hai ngoại lệ này đều kế thừa từ SyntaxError
lớp, nhưng chúng là những trường hợp đặc biệt khi có liên quan đến thụt
lề. An IndentationError
được nâng lên khi mức độ thụt lề của mã của bạn không khớp với nhau. A TabError
được nâng lên khi mã của bạn sử dụng cả tab và dấu cách trong cùng một tệp. Bạn sẽ xem xét kỹ hơn các ngoại lệ này trong phần sau.
Các vấn đề về cú pháp thường gặp
Khi bạn gặp phải SyntaxError
lần đầu tiên, sẽ rất hữu ích nếu bạn biết lý do tại sao có sự cố và bạn có thể làm gì để sửa cú pháp không hợp lệ trong mã Python của mình. Trong các phần bên dưới, bạn
sẽ thấy một số lý do phổ biến hơn khiến a SyntaxError
có thể tăng lên và cách bạn có thể khắc phục chúng.
Lạm dụng Toán tử Chuyển nhượng [ =
]
Có một số trường hợp trong Python mà bạn không thể gán các đối tượng. Một số ví dụ đang gán cho các chữ và lời gọi hàm. Trong khối mã bên dưới, bạn có thể thấy một vài ví dụ cố gắng thực hiện việc này và kết quả truy xuất SyntaxError
:
>>>
>>> len['hello'] = 5
File "", line 1
SyntaxError: can't assign to function call
>>> 'foo' = 1
File "", line 1
SyntaxError: can't assign to literal
>>> 1 = 'foo'
File "", line 1
SyntaxError: can't assign to literal
Ví dụ đầu tiên cố gắng gán
giá trị 5
cho len[]
cuộc gọi. Các SyntaxError
thông điệp là rất hữu ích trong trường hợp này. Nó cho bạn biết rằng bạn không thể gán giá trị cho một lệnh gọi hàm.
Ví dụ thứ hai và thứ ba cố gắng gán một chuỗi và một số nguyên cho các ký tự. Quy tắc tương tự cũng đúng với các giá trị chữ khác. Một lần nữa, các thông báo theo dõi lại chỉ ra rằng sự cố xảy ra khi bạn cố gắng gán giá trị cho một ký tự.
Lưu ý: Các ví dụ trên thiếu dòng mã lặp lại và dấu mũ [ ^
] trỏ đến sự cố trong truy xuất. Ngoại lệ và theo dõi mà bạn thấy sẽ khác khi bạn đang ở trong REPL so với việc cố gắng thực thi mã này từ một tệp. Nếu mã này nằm trong một tệp, thì bạn sẽ nhận được dòng mã lặp lại và dấu mũ trỏ đến vấn đề, như bạn đã thấy trong các trường hợp khác trong suốt hướng dẫn này.
Có thể ý định của bạn không phải là gán một giá trị cho một lệnh gọi
theo nghĩa đen hoặc hàm. Ví dụ: điều này có thể xảy ra nếu bạn vô tình bỏ qua dấu bằng phụ [ =
], điều này sẽ biến bài tập thành phép so sánh. Một so sánh, như bạn có thể thấy bên dưới, sẽ hợp lệ:
>>>
>>> len['hello'] == 5
True
Hầu hết thời gian, khi Python nói với bạn rằng bạn đang thực hiện một nhiệm vụ cho một thứ gì đó không thể được giao, trước tiên bạn có thể muốn kiểm tra để đảm bảo rằng thay vào đó câu lệnh không phải là biểu thức Boolean . Bạn cũng có thể gặp phải vấn đề này khi bạn đang cố gắng chỉ định một giá trị cho một từ khóa Python , bạn sẽ đề cập đến vấn đề này trong phần tiếp theo.
Từ khóa Python sai chính tả, thiếu hoặc sử dụng sai
Từ khóa Python là một tập hợp các từ được bảo vệ có ý nghĩa đặc biệt trong Python. Đây là những từ bạn không thể sử dụng làm số nhận dạng, biến hoặc tên hàm trong mã của mình. Chúng là một phần của ngôn ngữ và chỉ có thể được sử dụng trong ngữ cảnh mà Python cho phép.
Có ba cách phổ biến mà bạn có thể sử dụng nhầm từ khóa:
- Viết sai chính tả một từ khóa
- Thiếu một từ khóa
- Sử dụng sai từ khóa
Nếu bạn viết sai chính
tả một từ khóa trong mã Python của mình, thì bạn sẽ nhận được SyntaxError
. Ví dụ: đây là những gì sẽ xảy ra nếu bạn đánh vần từ khóa for
không chính xác:
>>>
>>> fro i in range[10]:
File "", line 1
fro i in range[10]:
^
SyntaxError: invalid syntax
Tin nhắn đã đọc SyntaxError: invalid syntax
, nhưng điều đó không hữu ích lắm. Việc truy xuất chỉ ra nơi đầu tiên mà Python có thể phát hiện ra rằng có điều gì đó không ổn. Để khắc phục loại lỗi này, hãy đảm bảo rằng tất cả các từ khóa Python của bạn được viết đúng chính
tả.
Một vấn đề phổ biến khác với các từ khóa là khi bạn bỏ lỡ chúng hoàn toàn:
>>>
>>> for i range[10]:
File "", line 1
for i range[10]:
^
SyntaxError: invalid syntax
Một lần nữa, thông báo ngoại lệ không phải là hữu ích, nhưng theo dõi lại cố gắng chỉ cho bạn đi đúng hướng. Nếu bạn di chuyển trở lại từ dấu mũ, thì bạn có thể thấy rằng in
từ khóa bị thiếu trong cú pháp for
vòng lặp .
Bạn cũng có
thể sử dụng sai một từ khóa Python được bảo vệ. Hãy nhớ rằng, từ khóa chỉ được phép sử dụng trong những trường hợp cụ thể. Nếu bạn sử dụng chúng không chính xác, thì bạn sẽ có cú pháp không hợp lệ trong mã Python của mình. Một ví dụ phổ biến về điều này là việc sử dụng continue
hoặcbreak
bên ngoài một vòng lặp. Điều này có thể dễ dàng xảy ra trong quá
trình phát triển khi bạn đang triển khai mọi thứ và tình cờ di chuyển logic ra ngoài một vòng lặp:
>>>
>>> names = ['pam', 'jim', 'michael']
>>> if 'jim' in names:
... print['jim found']
... break
...
File "", line 3
SyntaxError: 'break' outside loop
>>> if 'jim' in names:
... print['jim found']
... continue
...
File "", line 3
SyntaxError: 'continue' not properly in loop
Ở đây, Python thực hiện rất tốt việc cho bạn biết chính xác điều gì sai. Các thông báo "'break' outside loop"
và "'continue' not properly in loop"
giúp bạn tìm ra chính xác những gì cần làm. Nếu mã này nằm trong một tệp, thì Python cũng sẽ có dấu mũ trỏ ngay đến từ khóa được sử dụng sai.
Một ví dụ khác là nếu bạn cố gắng gán một từ khóa Python cho một biến hoặc sử dụng một từ khóa để xác định một hàm :
>>>
>>> pass = True
File "", line 1
pass = True
^
SyntaxError: invalid syntax
>>> def pass[]:
File "", line 1
def pass[]:
^
SyntaxError: invalid syntax
Khi bạn cố gắng gán một giá trị cho pass
hoặc khi bạn cố gắng xác định một hàm mới được gọi pass
, bạn sẽ
nhận được một SyntaxError
và thấy lại "invalid syntax"
thông báo.
Có thể khó hơn một chút để giải quyết loại cú pháp không hợp lệ này trong mã Python vì mã trông đẹp từ bên ngoài. Nếu mã của bạn trông ổn, nhưng bạn vẫn nhận được SyntaxError
, thì bạn có thể cân nhắc kiểm tra tên biến hoặc tên hàm bạn muốn sử dụng so với danh sách từ khóa cho phiên bản Python mà bạn đang sử dụng.
Danh sách các từ khóa được bảo vệ đã thay đổi với mỗi phiên bản Python mới. Ví dụ: trong Python
3.6, bạn có thể sử dụng await
làm tên biến hoặc tên hàm, nhưng kể từ Python 3.7, từ đó đã được thêm vào danh sách từ khóa. Bây giờ, nếu bạn cố gắng sử dụng await
làm tên biến hoặc hàm, điều này sẽ gây ra SyntaxError
nếu mã của bạn dành cho Python 3.7 trở lên.
Một ví dụ khác về điều này là print
, khác nhau trong Python 2 so với Python 3:
print
là một từ khóa trong Python 2, vì vậy bạn
không thể gán giá trị cho nó. Tuy nhiên, trong Python 3, đó là một hàm tích hợp có thể được gán giá trị.
Bạn có thể chạy đoạn mã sau để xem danh sách các từ khóa trong bất kỳ phiên bản Python nào bạn đang chạy:
import keyword
print[keyword.kwlist]
keyword
cũng cung cấp các hữu ích keyword.iskeyword[]
. Nếu bạn chỉ cần một cách nhanh chóng để kiểm tra pass
biến, thì bạn có thể sử dụng một lớp lót sau:
>>>
>>> import keyword; keyword.iskeyword['pass']
True
Mã này sẽ nhanh chóng cho bạn biết liệu số nhận dạng mà bạn đang cố gắng sử dụng có phải là từ khóa hay không.
Thiếu dấu ngoặc đơn, dấu ngoặc đơn và dấu ngoặc kép
Thông thường, nguyên nhân của cú pháp không hợp lệ trong mã Python là dấu ngoặc đơn, dấu ngoặc nhọn hoặc dấu ngoặc kép bị thiếu hoặc không khớp. Chúng có thể khó phát hiện trong các dòng dấu ngoặc đơn lồng nhau rất dài hoặc các khối nhiều dòng dài hơn. Bạn có thể phát hiện các dấu ngoặc kép không khớp hoặc bị thiếu với sự trợ giúp của tính năng theo dõi của Python:
>>>
>>> message = 'don't'
File "", line 1
message = 'don't'
^
SyntaxError: invalid syntax
Ở đây, dấu vết trỏ đến mã không hợp lệ, nơi có một t'
dấu ngoặc kép đóng sau một dấu ngoặc kép. Để khắc phục điều này, bạn có thể thực hiện một trong hai thay đổi:
- Thoát khỏi trích dẫn đơn bằng dấu gạch chéo ngược [
'don\'t'
] - Đắm toàn
bộ chuỗi trong dấu nháy kép thay vì [
"don't"
]
Một lỗi phổ biến khác là quên đóng chuỗi. Với cả chuỗi được trích dẫn kép và được trích dẫn đơn, tình huống và truy xuất nguồn gốc đều giống nhau:
>>>
>>> message = "This is an unclosed string
File "", line 1
message = "This is an unclosed string
^
SyntaxError: EOL while scanning string literal
Lần này, dấu mũ trong dấu vết trỏ ngay đến mã sự cố. Các SyntaxError
tin nhắn, "EOL while scanning string literal"
là một chút cụ thể hơn và
hữu ích trong việc xác định vấn đề. Điều này có nghĩa là trình thông dịch Python đã đến cuối dòng [EOL] trước khi một chuỗi mở được đóng lại. Để khắc phục điều này, hãy đóng chuỗi bằng một câu trích dẫn khớp với câu bạn đã sử dụng để bắt đầu nó. Trong trường hợp này, đó sẽ là một dấu ngoặc kép [ "
].
Dấu ngoặc kép bị thiếu trong các câu lệnh bên trong chuỗi f cũng có thể dẫn đến cú pháp không hợp lệ trong Python:
1# theofficefacts.py
2ages = {
3 'pam': 24,
4 'jim': 24,
5 'michael': 43
6}
7print[f'Michael is {ages["michael]} years old.']
Ở đây, tham chiếu đến ages
từ điển bên trong chuỗi f được in thiếu dấu ngoặc kép đóng từ tham chiếu khóa. Quá trình truy xuất kết quả như sau:
$ python theofficefacts.py
File "theofficefacts.py", line 7
print[f'Michael is {ages["michael]} years old.']
^
SyntaxError: f-string: unterminated string
Python xác định vấn đề và cho bạn biết rằng nó tồn tại bên trong chuỗi f. Thông báo "unterminated string"
cũng cho biết vấn đề là gì. Dấu mũ trong trường hợp
này chỉ trỏ đến phần đầu của chuỗi f.
Điều này có thể không hữu ích bằng khi dấu mũ trỏ đến vùng có vấn đề của chuỗi f, nhưng nó sẽ thu hẹp nơi bạn cần tìm. Có một chuỗi chưa kết thúc ở đâu đó bên trong chuỗi f đó. Bạn chỉ cần tìm ra nơi. Để khắc phục sự cố này, hãy đảm bảo rằng tất cả các dấu ngoặc kép và dấu ngoặc kép f-string đều có mặt.
Tình hình hầu hết giống nhau đối với dấu ngoặc đơn và dấu ngoặc đơn. Ví dụ: nếu bạn bỏ dấu ngoặc vuông đóng khỏi danh sách , thì Python sẽ phát hiện ra điều đó và chỉ ra. Tuy nhiên, có một vài biến thể của điều này. Đầu tiên là bỏ dấu ngoặc đóng khỏi danh sách:
# missing.py
def foo[]:
return [1, 2, 3
print[foo[]]
Khi bạn chạy mã này, bạn sẽ được thông báo rằng có sự cố với lệnh gọi tới print[]
:
$ python missing.py
File "missing.py", line 5
print[foo[]]
^
SyntaxError: invalid syntax
Gì đang xảy ra ở đây là Python nghĩ danh sách
chứa ba yếu tố: 1
, 2
, và 3 print[foo[]]
. Python sử dụng khoảng trắng để điều nhóm một cách logic, và vì không có dấu phẩy hoặc khung tách 3
từ print[foo[]]
, Python cục u chúng lại với nhau là yếu tố thứ ba trong danh sách.
Một biến thể khác là thêm dấu phẩy vào sau phần tử cuối cùng trong danh sách trong khi vẫn bỏ dấu ngoặc vuông đóng:
# missing.py
def foo[]:
return [1, 2, 3,
print[foo[]]
Bây giờ bạn nhận được một dấu vết khác:
$ python missing.py
File "missing.py", line 6
^
SyntaxError: unexpected EOF while parsing
Trong ví dụ trước, 3
và print[foo[]]
được gộp lại với nhau thành một phần tử, nhưng ở đây bạn sẽ thấy dấu phẩy ngăn cách hai phần tử. Bây giờ, lệnh gọi print[foo[]]
được thêm vào làm phần tử thứ tư của danh sách và Python đến cuối tệp mà không có dấu ngoặc đóng. Theo dõi lại cho bạn biết rằng Python đã đến cuối tệp [EOF], nhưng nó đang mong đợi một thứ khác.
Trong ví dụ này, Python mong đợi một dấu ngoặc đóng [ ]
], nhưng dòng lặp lại và dấu mũ không hữu ích lắm. Python bị thiếu dấu ngoặc và ngoặc rất khó xác định. Đôi khi điều duy nhất bạn có thể làm là bắt đầu từ dấu mũ và lùi lại phía sau cho đến khi bạn có thể xác định được điều gì bị thiếu hoặc sai.
Sai cú pháp từ điển
Bạn đã thấy trước đó rằng bạn có thể nhận được SyntaxError
nếu bạn bỏ dấu phẩy của một phần tử từ điển. Một dạng cú pháp không hợp lệ khác với từ điển Python là việc sử dụng dấu bằng [ =
] để phân tách các khóa và giá trị, thay vì dấu hai chấm:
>>>
>>> ages = {'pam'=24}
File "", line 1
ages = {'pam'=24}
^
SyntaxError: invalid syntax
Một lần nữa, thông báo lỗi này không hữu ích lắm. Tuy nhiên, dòng lặp lại và dấu mũ rất hữu ích! Họ đang chỉ thẳng vào nhân vật vấn đề.
Loại sự cố này thường gặp nếu bạn nhầm lẫn cú pháp Python với cú pháp của các ngôn ngữ lập trình khác. Bạn cũng sẽ thấy điều này nếu bạn nhầm lẫn giữa hành động xác định từ điển với một dict[]
cuộc gọi. Để khắc phục điều này, bạn có thể thay thế dấu bằng bằng dấu hai chấm. Bạn cũng có thể chuyển sang
sử dụng dict[]
:
>>>
>>> ages = dict[pam=24]
>>> ages
{'pam': 24}
Bạn có thể sử dụng dict[]
để định nghĩa từ điển nếu cú pháp đó hữu ích hơn.
Sử dụng thụt lề sai
Có hai lớp SyntaxError
con giải quyết vấn đề thụt lề cụ thể:
IndentationError
TabError
Trong khi các ngôn ngữ lập trình khác sử dụng dấu ngoặc nhọn để biểu thị các khối mã thì Python sử dụng khoảng trắng . Điều đó có nghĩa là Python mong đợi khoảng trắng trong mã của bạn hoạt động có thể đoán trước được. Nó sẽ tăng lên IndentationError
nếu có một dòng trong khối mã có số khoảng trắng không chính xác:
1# indentation.py
2def foo[]:
3 for i in range[10]:
4 print[i]
5 print['done']
6
7foo[]
Điều này có thể khó thấy, nhưng dòng 5 chỉ được
thụt vào 2 khoảng trắng. Nó phải phù hợp với for
câu lệnh lặp, có 4 dấu cách trên. Rất may, Python có thể phát hiện ra điều này một cách dễ dàng và sẽ nhanh chóng cho bạn biết vấn đề là gì.
Tuy nhiên, cũng có một chút mơ hồ ở đây. Là print['done']
dòng dự định được sau khi các for
vòng lặp hoặc bên trong các for
khối vòng lặp? Khi bạn chạy mã trên, bạn sẽ thấy lỗi sau:
$ python indentation.py
File "indentation.py", line 5
print['done']
^
IndentationError: unindent does not match any outer indentation level
Mặc dù theo
dõi trông rất giống theo dõi SyntaxError
, nhưng nó thực sự là một IndentationError
. Thông báo lỗi cũng rất hữu ích. Nó cho bạn biết rằng mức độ thụt lề của dòng không khớp với bất kỳ mức độ thụt lề nào khác. Nói cách khác, print['done']
được thụt lề 2 khoảng trắng, nhưng Python không thể tìm thấy bất kỳ dòng mã nào khác phù hợp với mức độ thụt lề này. Bạn có thể khắc phục điều này một cách nhanh chóng bằng cách đảm bảo mã dòng phù hợp với mức độ thụt lề mong đợi.
Loại SyntaxError
còn
lại là TabError
, bạn sẽ thấy bất cứ khi nào có một dòng chứa tab hoặc khoảng trắng cho phần thụt lề của nó, trong khi phần còn lại của tệp chứa dòng kia. Điều này có thể bị ẩn cho đến khi Python chỉ ra cho bạn!
Nếu kích thước tab của bạn có cùng chiều rộng với số khoảng trắng trong mỗi mức thụt lề, thì có thể giống như tất cả các dòng đều ở cùng một mức. Tuy nhiên, nếu một dòng được thụt lề bằng cách sử dụng dấu cách và dòng còn lại được thụt vào bằng các tab, thì Python sẽ chỉ ra đây là một vấn đề:
1# indentation.py
2def foo[]:
3 for i in range[10]:
4 print[i]
5 print['done']
6
7foo[]
Ở đây, dòng 5 được thụt lề bằng một tab thay vì 4 dấu cách. Khối mã này có thể trông hoàn toàn ổn đối với bạn hoặc có thể trông hoàn toàn sai, tùy thuộc vào cài đặt hệ thống của bạn.
Tuy nhiên, Python sẽ nhận thấy vấn đề ngay lập tức. Nhưng trước khi bạn chạy mã để xem điều gì Python sẽ cho bạn biết là sai, có thể hữu ích cho bạn khi xem ví dụ về mã trông như thế nào trong các cài đặt chiều rộng tab khác nhau:
$ tabs 4 # Sets the shell tab width to 4 spaces
$ cat -n indentation.py
1 # indentation.py
2 def foo[]:
3 for i in range[10]
4 print[i]
5 print['done']
6
7 foo[]
$ tabs 8 # Sets the shell tab width to 8 spaces [standard]
$ cat -n indentation.py
1 # indentation.py
2 def foo[]:
3 for i in range[10]
4 print[i]
5 print['done']
6
7 foo[]
$ tabs 3 # Sets the shell tab width to 3 spaces
$ cat -n indentation.py
1 # indentation.py
2 def foo[]:
3 for i in range[10]
4 print[i]
5 print['done']
6
7 foo[]
Lưu ý sự khác biệt về hiển thị giữa ba ví dụ trên. Hầu hết mã sử dụng 4 dấu cách cho mỗi mức thụt lề, nhưng dòng 5 sử dụng một tab duy nhất trong cả ba ví dụ. Chiều rộng của tab thay đổi, dựa trên cài đặt chiều rộng tab :
- Nếu chiều rộng tab là 4 , thì
print
câu lệnh sẽ giống như nó nằm ngoàifor
vòng lặp. Bảng điều khiển sẽ in'done'
ở cuối vòng lặp. - Nếu chiều rộng tab là 8 , là tiêu chuẩn cho nhiều hệ thống, thì
print
câu lệnh sẽ giống như bên trongfor
vòng lặp. Bàn điều khiển sẽ in'done'
sau mỗi số. - Nếu chiều rộng tab là 3 , thì
print
câu lệnh có vẻ không đúng chỗ. Trong trường hợp này, dòng 5 không khớp với bất kỳ mức thụt lề nào.
Khi bạn chạy mã, bạn sẽ gặp lỗi sau và theo dõi lại:
$ python indentation.py
File "indentation.py", line 5
print['done']
^
TabError: inconsistent use of tabs and spaces in indentation
Chú
ý TabError
thay vì thông thường SyntaxError
. Python chỉ ra dòng vấn đề và cung cấp cho bạn một thông báo lỗi hữu ích. Nó cho bạn biết rõ ràng rằng có một hỗn hợp các tab và khoảng trắng được sử dụng để thụt lề trong cùng một tệp.
Giải pháp cho điều này là làm cho tất cả các dòng trong cùng một tệp mã Python sử dụng tab hoặc dấu cách, nhưng không sử dụng cả hai. Đối với các khối mã ở trên, cách khắc phục sẽ là xóa tab và thay thế bằng 4 khoảng trắng, sẽ in 'done'
sau
khi for
vòng lặp kết thúc.
Xác định và gọi các chức năng
Bạn có thể gặp phải cú pháp không hợp lệ trong Python khi bạn đang định nghĩa hoặc gọi các hàm. Ví dụ: bạn sẽ thấy SyntaxError
nếu bạn sử dụng dấu chấm phẩy thay vì dấu hai chấm ở cuối định nghĩa hàm:
>>>
>>> def fun[];
File "", line 1
def fun[];
^
SyntaxError: invalid syntax
Việc truy xuất ở đây rất hữu ích, với dấu mũ trỏ ngay đến ký tự vấn đề. Bạn có thể xóa cú pháp không hợp lệ này trong Python bằng cách chuyển dấu chấm phẩy cho dấu hai chấm.
Ngoài ra, các đối số từ khóa trong cả định nghĩa hàm và lệnh gọi hàm cần phải theo đúng thứ tự. Đối số từ khóa luôn đứng sau đối số vị trí. Việc không sử dụng lệnh này sẽ dẫn đến SyntaxError
:
>>>
>>> def fun[a, b]:
... print[a, b]
...
>>> fun[a=1, 2]
File "", line 1
SyntaxError: positional argument follows keyword argument
Ở đây, một lần nữa, thông báo lỗi rất hữu ích trong việc cho bạn biết chính xác điều gì xảy ra với dòng.
Thay đổi phiên bản Python
Đôi khi, mã hoạt động hoàn toàn tốt trong một phiên bản Python bị hỏng trong phiên bản mới hơn. Điều này là do những thay đổi chính thức trong cú pháp ngôn ngữ. Ví dụ nổi tiếng nhất về điều này là print
câu lệnh, đi từ một từ khóa trong
Python 2 thành một hàm tích hợp sẵn trong Python 3:
>>>
>>> # Valid Python 2 syntax that fails in Python 3
>>> print 'hello'
File "", line 1
print 'hello'
^
SyntaxError: Missing parentheses in call to 'print'. Did you mean print['hello']?
Đây là một trong những ví dụ trong đó thông báo lỗi được cung cấp cùng với SyntaxError
ánh sáng! Nó không chỉ cho bạn biết rằng bạn đang thiếu dấu ngoặc đơn trong print
cuộc gọi, mà còn cung cấp mã chính xác để giúp bạn sửa câu lệnh.
Một vấn đề khác mà bạn có thể gặp phải là khi bạn đang đọc hoặc tìm hiểu về cú pháp là cú pháp hợp lệ trong phiên bản Python mới hơn, nhưng không hợp lệ trong phiên bản bạn đang viết. Một ví dụ về điều này là cú pháp f-string , không tồn tại trong các phiên bản Python trước 3.6:
>>>
>>> # Any version of python before 3.6 including 2.7
>>> w ='world'
>>> print[f'hello, {w}']
File "", line 1
print[f'hello, {w}']
^
SyntaxError: invalid syntax
Trong các phiên bản Python trước 3.6, trình thông dịch không biết gì về cú pháp chuỗi f và sẽ chỉ cung cấp
một "invalid syntax"
thông báo chung . Trong trường hợp này, vấn đề là mã trông hoàn toàn ổn, nhưng nó được chạy với phiên bản Python cũ hơn. Khi nghi ngờ, hãy kiểm tra kỹ phiên bản Python mà bạn đang chạy!
Cú pháp Python đang tiếp tục phát triển và có một số tính năng mới thú vị được giới thiệu trong Python 3.8 :
- Toán tử hải mã [biểu thức gán]
- Cú pháp chuỗi F để gỡ lỗi
- Đối số chỉ vị trí
Nếu bạn muốn thử một số tính năng mới này, thì bạn cần
đảm bảo rằng bạn đang làm việc trong môi trường Python 3.8. Nếu không, bạn sẽ nhận được một SyntaxError
.
Python 3.8 cũng cung cấp tính năng mới SyntaxWarning
. Bạn sẽ thấy cảnh báo này trong các trường hợp cú pháp hợp lệ nhưng vẫn có vẻ đáng ngờ. Một ví dụ về điều này sẽ là nếu bạn thiếu dấu phẩy giữa hai bộ giá trị trong danh sách. Đây sẽ là cú pháp hợp lệ trong các phiên bản Python trước 3.8, nhưng mã sẽ tăng a TypeError
vì một tuple không thể gọi được:
>>>
>>> [[1,2][2,3]]
Traceback [most recent call last]:
File "", line 1, in
TypeError: 'tuple' object is not callable
Điều này TypeError
có nghĩa là bạn không thể gọi một tuple như một hàm, đó là điều mà trình thông dịch Python nghĩ rằng bạn đang làm.
Trong Python 3.8, mã này vẫn tăng TypeError
, nhưng bây giờ bạn cũng sẽ thấy một mã SyntaxWarning
cho biết cách bạn có thể khắc phục sự cố:
>>>
>>> [[1,2][2,3]]
:1: SyntaxWarning: 'tuple' object is not callable; perhaps you missed a comma?
Traceback [most recent call last]:
File "", line 1, in
TypeError: 'tuple' object is not callable
Thông
báo hữu ích đi kèm với cái mới SyntaxWarning
thậm chí còn cung cấp một gợi ý [ "perhaps you missed a comma?"
] để chỉ bạn đi đúng hướng!
Phần kết luận
Trong hướng dẫn này, bạn đã thấy thông tin mà theo dõi SyntaxError
cung cấp cho bạn. Bạn cũng đã thấy nhiều ví dụ phổ biến về cú pháp không hợp lệ trong Python và giải pháp cho những vấn đề đó là gì. Điều này không chỉ giúp tăng tốc quy trình làm việc của bạn mà còn giúp bạn trở thành người đánh giá mã hữu ích hơn!
Khi bạn đang viết mã, hãy cố gắng sử dụng IDE hiểu cú pháp Python và cung cấp phản hồi. Nếu bạn đặt nhiều ví dụ mã Python không hợp lệ từ hướng dẫn này vào một IDE tốt, thì chúng sẽ làm nổi bật các dòng vấn đề trước khi bạn thực thi mã của mình.
SyntaxError
Bạn đang học Python trong một thời gian có thể khiến bạn bực bội, nhưng bây giờ bạn đã biết cách hiểu các thông báo tìm lại và các dạng cú pháp
không hợp lệ trong Python mà bạn có thể gặp phải. Lần tới khi bạn gặp lỗi SyntaxError
, bạn sẽ được trang bị tốt hơn để khắc phục sự cố một cách nhanh chóng!