2012-03-17 20 views
8

Có một hạn chế về cú pháp của truy cập thuộc tính, bằng Python (ít nhất là trong việc thực hiện CPython 2.7.2):Tại sao không thể phân bổ tên là các từ khóa Python?

>>> class C(object): pass 
>>> o = C() 
>>> o.x = 123 # Works 
>>> o.if = 123 
    o.if = 123 
    ^
SyntaxError: invalid syntax 

Câu hỏi của tôi là hai khía cạnh:

  1. Có một lý do cơ bản tại sao sử dụng tên thuộc tính từ khóa Python (như trong o.if = 123) bị cấm?
  2. Có giới hạn ở trên đối với tên thuộc tính được ghi lại ở đâu?

Nó sẽ làm cho tinh thần để làm o.class = …, trong một trong những chương trình của tôi, và tôi là một chút thất vọng vì không có khả năng để làm điều đó (o.class_ sẽ làm việc, nhưng nó không giống như đơn giản).

PS: Vấn đề rõ ràng là ifclass là từ khóa Python. Câu hỏi là lý do tại sao sử dụng từ khóa làm tên thuộc tính sẽ bị cấm (Tôi không thấy bất kỳ sự mơ hồ nào trong biểu thức o.class = 123) và cho dù đây là được ghi lại.

+3

Do trình phân tích cú pháp đơn giản hơn khi từ khóa luôn là từ khóa và không theo ngữ cảnh. Vì vậy, mã thậm chí không đến điểm có quyền truy cập thuộc tính, nó chỉ đơn giản là một lỗi cú pháp ở cấp phân tích cú pháp (vì 'if' là một phần của ngữ pháp và nó không bao giờ xuất hiện ở nơi này). Nó giống nhau trong hầu hết các ngôn ngữ và ngữ pháp ngôn ngữ là tài liệu cho điều đó. –

+2

Ngoài ra, 'cls' thường được sử dụng cho các tên chứa tham chiếu đến các lớp. –

+0

Thậm chí nếu bạn có một trình phân tích cú pháp có thể phân biệt các từ khóa với các biến/tên hàm, nó không đảm bảo rằng một người có thể che giấu các từ khóa khác trong một trường hợp góc. Sẽ dễ dàng hơn nhiều để duy trì sự tỉnh táo nếu bạn chỉ thẳng ra cấm sử dụng vài chục cái tên. –

Trả lời

7

Bởi vì phân tích cú pháp đơn giản hơn khi từ khoá luôn từ khóa, và không theo ngữ cảnh (ví dụ if là một từ khóa khi trên cấp độ tuyên bố, nhưng chỉ là số nhận dạng khi bên trong một biểu thức - cho if nó sẽ khó gấp đôi vì X if C else Yfor được sử dụng trong danh sách hiểu và biểu thức trình tạo).

Vì vậy, mã thậm chí không đến điểm có quyền truy cập thuộc tính, nó bị từ chối phân tích cú pháp, giống như thụt lề không chính xác (đó là lý do tại sao nó là SyntaxError và không phải AttributeError hoặc thứ gì đó). Nó không phân biệt bạn có sử dụng if làm tên thuộc tính, tên biến, tên hàm hoặc tên loại hay không. Nó không bao giờ có thể là một định danh, đơn giản bởi vì trình phân tích cú pháp luôn gán nhãn "từ khóa" và làm cho nó trở thành một mã thông báo khác với các mã định danh.

Điều này giống nhau ở hầu hết các ngôn ngữ và ngữ pháp ngôn ngữ (đặc điểm kỹ thuật + lexer) là tài liệu cho điều đó. Language spec mentions it explicitly. Nó cũng không làm thay đổi bằng Python 3.

Ngoài ra, chỉ vì bạn có thể sử dụng setattr hoặc __dict__ để làm cho một thuộc tính với một tên dành riêng, không có nghĩa là bạn nên . Đừng ép buộc người dùng/người dùng API sử dụng getattr thay vì truy cập thuộc tính tự nhiên. getattr nên được dành riêng khi truy cập vào tên thuộc tính biến là cần thiết.

+1

Vì vậy, đó là cách giáo viên cho chúng tôi biết trong các lớp trình biên dịch. Đây là cách trình biên dịch được xây dựng theo kiểu cổ điển. Các thẻ được phân chia, phân thành các loại và sau đó được phân tích nếu chúng có ý nghĩa bởi trình phân tích cú pháp. Mỗi biểu tượng đặc biệt như + hoặc: có danh mục riêng (riêng), cũng như mọi từ dành riêng ("if", "hoặc", "class", "def", v.v.). Mỗi từ khác thuộc về một danh mục đặc biệt: số nhận dạng. Vì "nếu" không phải là một số nhận dạng, nó không thể đặt tên một thuộc tính, đơn giản như vậy. Tôi không nói rằng nó là không thể xây dựng một trình biên dịch/phân tích mã theo một cách khác, chỉ cần đây là cách mọi thứ được thực hiện những ngày này ... – lvella

+0

@ Ivella: 1 cho bình luận rất có liên quan. – EOL

+0

@CatPlusPlus: Đồng ý, về 'getattr' và' __dict__'. Tôi chỉ đề cập đến những điều này bởi vì chúng cho thấy rằng các tên thuộc tính có thể là các từ khóa mặc dù cú pháp object.attribute thông thường cấm nó. – EOL

1

if là từ khóa. Bạn có vấn đề tương tự với o.whileo.for:

pax> python 
>>> class C(object): pass 
... 

>>> o = C() 

>>> o.not_a_keyword = 123 

>>> o.if = 123 
    File "<stdin>", line 1 
    o.if = 123 
    ^
SyntaxError: invalid syntax 

>>> o.while = 123 
    File "<stdin>", line 1 
    o.while = 123 
     ^
SyntaxError: invalid syntax 

>>> o.for = 123 
    File "<stdin>", line 1 
    o.for = 123 
     ^
SyntaxError: invalid syntax 

từ khóa khác bằng Python có thể đạt được với:

>>> import keyword 
>>> keyword.kwlist 
['and', 'as', 'assert', 'break', 'class', 'continue', 'def', 
'del', 'elif', 'else', 'except', 'exec', 'finally', 'for', 
'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 
'not', 'or', 'pass', 'print', 'raise', 'return', 'try', 
'while', 'with', 'yield'] 

Bạn nên không thường sử dụng một từ khóa như tên biến bằng Python.

Tôi khuyên bạn nên chọn tên mô tả hơn, chẳng hạn như iface nếu đó là giao diện hoặc infld cho trường nhập và v.v.

Khi chỉnh sửa câu hỏi của bạn thành tại sao từ khóa không được phép, nó đơn giản hóa các trình phân tích cú pháp rất nhiều nếu các phần tử từ vựng không có ngữ cảnh. Phải xử lý mã từ vựng if làm từ khóa ở một số địa điểm và số nhận dạng ở những nơi khác sẽ giới thiệu tính phức tạp không thực sự cần thiết nếu bạn chọn số nhận dạng của mình một cách khôn ngoan hơn.

Ví dụ, C++ tuyên bố:

long int int = char[new - int]; 

thể (với một khó khăn nhỏ) được đánh giá với một phân tích cú pháp phức tạp dựa trên nơi những yếu tố từ vựng xảy ra (và những gì tồn tại ở hai bên của chúng). Nhưng, (ít nhất là một phần) vì lợi ích của sự đơn giản (và khả năng đọc), điều này không được thực hiện.

+1

Có, thực sự. Tôi đã cập nhật tiêu đề của câu hỏi để làm rõ thực tế rằng câu hỏi là tại sao từ khóa sẽ bị cấm làm tên thuộc tính. Trong thực tế, trong 'o.class = 123', rõ ràng là' class' phải là một tên thuộc tính; tuy nhiên, đây không phải là Python (C) hợp lệ; phải có lý do chính đáng tại sao điều này không nên rõ ràng với người phiên dịch CPython: những lý do này là gì? – EOL

3

Tôi không nghĩ rằng if có thể được sử dụng làm tên biến hoặc thuộc tính (rõ ràng), vì đó là từ khóa.

Bạn có thể, tuy nhiên, sử dụng setattrgetattr để làm được việc này một cách lộn xộn

>>> class C(object): pass 
... 
>>> o = C() 
>>> setattr(o, 'if', 123) 
>>> getattr(o, 'if') 
123 
+0

Vâng, thực sự. Điều này trông đẹp hơn truy cập 'o .__ dict__'. Tuy nhiên, câu hỏi đặt ra là về nguyên nhân của hạn chế này là gì và liệu hạn chế có được ghi chép hay không. – EOL

+0

Lý do là vì bạn không thể ghi đè từ khóa. Điều đó không cần phải được ghi lại. – Blender

+0

Tôi thích câu trả lời của @Cat Plus Plus trong phần bình luận chính. Đó là một quyết định thiết kế để làm cho trình phân tích cú pháp dễ dàng hơn. Thành ngữ python là để làm 'if_', hoặc' exec_', v.v. – jdi

Các vấn đề liên quan