'id' là tên biến xấu trong Python


141

Tại sao nó là xấu khi đặt tên một biến idtrong Python?


33
Hầu hết mọi người nối một dấu gạch dưới vào các số nhận dạng xung đột với nội dung / từ khóa: id_, map_, list_, filter_, v.v.
cdleary

3
Một giải pháp lén lút hơn sẽ là sử dụng một biến ID.
Simon Kuang

45
Một câu hỏi tốt hơn sẽ là ... Những thiên tài nghĩ gì khi sử dụng một tên chung, chung cho chức năng tích hợp như vậy là một ý tưởng tốt?
Cơ bản

Câu trả lời:


143

id() là một tích hợp cơ bản:

Trợ giúp về chức năng tích hợp idtrong mô-đun __builtin__:

id(...)

    id(object) -> integer

    Return the identity of an object.  This is guaranteed to be unique among
    simultaneously existing objects.  (Hint: it's the object's memory
    address.)

Nói chung, sử dụng tên biến làm lu mờ từ khóa hoặc hàm tích hợp trong bất kỳ ngôn ngữ nào là một ý tưởng tồi, ngay cả khi nó được cho phép.


3
OK, với 'id' bạn đúng, nhưng nhận xét "nói chung ..." vẫn được áp dụng, bạn có nghĩ vậy không?
Kevin Little

5
Tôi sẽ tránh nó cho mô-đun toàn cầu chắc chắn. Đối với các biến bị giới hạn trong phạm vi cục bộ, do đó bạn có thể thấy chức năng tương tự sẽ không bao giờ cần sử dụng nội dung, đó không phải là điều tôi lo lắng.
bobince

@Caramdir: Bắt tốt, iddự kiến ​​sẽ loại bỏ cùng một lúc, nhưng cuối cùng họ quyết định không xóa nó. Tôi không còn có thể chỉnh sửa nhận xét ban đầu của mình, vì vậy tôi sẽ xóa nó để tránh gây nhầm lẫn cho mọi người trong tương lai.
Eli Courtwright

20
@EliCourtwright Tôi ước họ đã gỡ bỏ nó. Thật là một phương pháp được đặt tên kém! Một tên chung, phổ biến được sử dụng ở hàng ngàn nơi (trong đó bối cảnh mang lại ý nghĩa). Vì vậy, ai đó đã quyết định sử dụng nó như một tên toàn cầu, nơi không có bối cảnh?
Cơ bản

2
Thật đáng ngạc nhiên, hướng dẫn regex Python riêng của Google ( developers.google.com/edu/python/THER-expressions ) sử dụng str = 'an example word:cat!!'. Có bất cứ điều gì trong bất kỳ PEP nào nói không làm điều này không?
wordsforthewise

57

Trong PEP 8 - Hướng dẫn kiểu cho mã Python , hướng dẫn sau sẽ xuất hiện trong phần Mô tả: Kiểu đặt tên :

  • single_trailing_underscore_ : được sử dụng bởi quy ước để tránh xung đột với từ khóa Python, vd

    Tkinter.Toplevel(master, class_='ClassName')

Vì vậy, để trả lời câu hỏi, một ví dụ áp dụng hướng dẫn này là:

id_ = 42

Việc bao gồm dấu gạch dưới trong tên biến làm cho ý định rõ ràng (với những người quen thuộc với hướng dẫn trong PEP 8).


1
Điều này không trả lời câu hỏi thực tế, nhưng +1 cho quy ước đặt tên PEP-8
ege

Lời khuyên tốt, nhưng idlà một nội dung, không phải là một từ khóa và điều này không giải thích tại sao nó xấu khi che giấu một nội dung.
wjandrea

51

idlà một hàm tích hợp cung cấp danh tính của một đối tượng (cũng là địa chỉ bộ nhớ của nó trong CPython). Nếu bạn đặt tên cho một trong các chức năng của mình id, bạn sẽ phải nói builtins.idđể lấy bản gốc (hoặc __builtins__.idbằng CPython). Đổi tên idtoàn cầu là khó hiểu trong bất cứ điều gì ngoại trừ một kịch bản nhỏ.

Tuy nhiên, việc sử dụng lại các tên dựng sẵn dưới dạng các biến không phải là quá tệ, miễn là việc sử dụng là cục bộ. Python có rất nhiều hàm dựng sẵn mà (1) có tên chung và (2) dù sao bạn cũng sẽ không sử dụng nhiều. Sử dụng chúng làm biến cục bộ hoặc làm thành viên của một đối tượng đều ổn vì rõ ràng từ ngữ cảnh bạn đang làm:

Thí dụ:

def numbered(filename):
    with open(filename) as file:
        for i, input in enumerate(file):
            print("%s:\t%s" % (i, input), end='')

Một số tích hợp với tên hấp dẫn:

  • id
  • file
  • list, dict
  • map
  • all, any
  • complex, int
  • dir
  • input
  • slice
  • buffer
  • sum
  • min, max
  • object

8
PEP 8 , được cập nhật ngày 01 tháng 8 năm 2013, hiện khuyên bạn nên tránh sự nhầm lẫn tiềm ẩn bằng cách chỉ cần thêm _vào tên biến. Xin vui lòng xem câu trả lời của tôi .
DavidRR

1
Cần lưu ý rằng idhàm trả về địa chỉ bộ nhớ của đối tượng là chi tiết triển khai CPython. Cũng đáng lưu ý rằng hàm chỉ được yêu cầu trả về một số khác nhau cho bất kỳ hai đối tượng còn lại nào . Nếu một đối tượng là rác được thu thập, id của nó có thể được tái chế.
Zac Crites

@Zac Cảm ơn! Tôi đã chỉnh sửa câu trả lời để thêm điểm đó về địa chỉ bộ nhớ và một liên kết để mọi người có thể đọc thêm.
wjandrea

42

Tôi có thể nói một cái gì đó không phổ biến ở đây: id()là một hàm tích hợp khá chuyên dụng hiếm khi được sử dụng trong logic kinh doanh. Do đó, tôi không thấy vấn đề gì khi sử dụng nó làm tên biến trong hàm chặt chẽ và được viết tốt, trong đó rõ ràng id không có nghĩa là hàm tích hợp.


1
Đáp lại:> id là một hàm tích hợp> khá chuyên dụng hiếm khi được sử dụng trong> logic nghiệp vụ. Do đó, tôi không thấy> vấn đề trong việc sử dụng nó như một biến> tên trong một hàm chặt chẽ và được viết tốt, vì vậy rõ ràng id> không có nghĩa là hàm tích hợp. Mặc dù điều này là đúng, nhưng có lẽ nên cụ thể hơn với tên biến này hơn là "id". Rất nhiều thứ có ID (đặc biệt là nếu bạn đang làm việc với RDBMS) và như dòng thứ hai của Tim Peters, Zen of Python nói với chúng tôi:> Rõ ràng là tốt hơn là ẩn. Xem phần còn lại bằng cách chạy:import this
Ross

9
Tôi vẫn sẽ tránh nó nếu có thể. Ngay cả khi không có lý do nào khác ngoài việc không nghe đồng nghiệp phàn nàn. :-)
Jason Baker

1
Tôi hoàn toàn đồng ý: việc đặt tên một biến "id" trong một hàm nhỏ (và do đó phạm vi) là vô hại. Rất ít người sử dụng idnội dung dựng sẵn. Điều đó nói rằng tôi phải mất một thời gian khi một đồng nghiệp vượt qua phần listdựng sẵn với một biến cục bộ. Vì vậy, quy tắc chung mà người khác đề cập vẫn có ý nghĩa.
silviot

5

Thật tệ khi đặt tên cho bất kỳ biến nào sau hàm tích hợp. Một trong những lý do là bởi vì nó có thể gây nhầm lẫn cho người đọc không biết tên bị ghi đè.


2

idlà một hàm tích hợp trong Python. Gán một giá trị idsẽ ghi đè hàm. Tốt nhất là thêm tiền tố vào some_idhoặc sử dụng nó trong một cách viết hoa khác như trong ID.

Hàm dựng sẵn nhận một đối số duy nhất và trả về một số nguyên cho địa chỉ bộ nhớ của đối tượng mà bạn đã truyền (trong CPython).

>>> id(1)
9787760
>>> x = 1
>>> id(x)
9787760

2
lưu ý rằng bạn có thể đặt tên cho một thuộc tính lớp hoặc phương thức 'id', sẽ không chạm vào hàm tích hợp.
Toni Ruža


0

Những người khác đã đề cập rằng nó khó hiểu, nhưng tôi muốn mở rộng lý do tại sao . Đây là một ví dụ, dựa trên một câu chuyện có thật. Về cơ bản, tôi viết một lớp có một idtham số nhưng sau đó cố gắng sử dụng nội dung dựng idsau.

class Employee:
    def __init__(self, name, id):
        """Create employee, with their name and badge id."""
        self.name = name
        self.id = id
        # ... lots more code, making you forget about the parameter names
        print('Created', type(self).__name__, repr(name), 'at', hex(id(self)))

tay = Employee('Taylor Swift', 1985)

Sản lượng dự kiến:

Created Employee 'Taylor Swift' at 0x7efde30ae910

Sản lượng thực tế:

Traceback (most recent call last):
  File "company.py", line 9, in <module>
    tay = Employee('Taylor Swift', 1985)
  File "company.py", line 7, in __init__
    print('Created', type(self).__name__, repr(name), 'at', hex(id(self)))
TypeError: 'int' object is not callable

Huh? Tôi đang cố gọi một int ở đâu? Đó là tất cả các nội dung ...

Nếu tôi đặt tên cho nó badge_idhoặc id_, tôi sẽ không có vấn đề này.


-6

Bởi vì python là một ngôn ngữ động, nên thường không nên đưa ra một biến và một hàm cùng tên. id () là một hàm trong python, vì vậy chúng tôi khuyên bạn không nên sử dụng biến có tên id. Lưu ý rằng, áp dụng cho tất cả các hàm mà bạn có thể sử dụng ... một biến không nên có cùng tên với một hàm.


3
"Bởi vì python là một ngôn ngữ động, nên thường không nên đưa ra một biến và một hàm cùng tên." - Bạn không thể đặt một biến và một hàm cùng tên. Không có gì để làm với nó là một ngôn ngữ năng động. Nếu bạn có nghĩa là cho các thuộc tính cùng tên với các đối tượng khác trong cùng phạm vi, tôi cũng không đồng ý. Bạn có thể có một lớp được gọi là "Khóa", một thể hiện của lớp đó được gọi là "khóa" và một thuộc tính của một đối tượng khác gọi là "khóa", ví dụ: "door.key".
Purrell
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.