2010-04-26 31 views
95

Tôi có các lớp Python, trong đó tôi chỉ cần một cá thể trong thời gian chạy, do đó, nó sẽ đủ để chỉ có các thuộc tính một lần cho mỗi lớp chứ không phải từng trường hợp. Nếu có nhiều hơn một trường hợp (điều này sẽ không xảy ra), tất cả các cá thể sẽ có cùng cấu hình. Tôi tự hỏi những lựa chọn nào sau đây sẽ tốt hơn hoặc nhiều hơn là "thành ngữ" Python.Biến cá thể so với biến lớp trong Python

biến Class:

class MyController(Controller): 

    path = "something/" 
    children = [AController, BController] 

    def action(self, request): 
    pass 

biến Instance:

class MyController(Controller): 

    def __init__(self): 
    self.path = "something/" 
    self.children = [AController, BController] 

    def action(self, request): 
    pass 
+4

Sau khi đọc câu hỏi này và thấy câu trả lời, một trong những câu hỏi đầu tiên của tôi là, "Vậy làm thế nào để tôi truy cập các biến lớp?" - đó là vì đến thời điểm này tôi chỉ sử dụng các biến mẫu. Trong câu trả lời cho câu hỏi của riêng tôi, bạn làm điều đó thông qua tên lớp chính nó, mặc dù về mặt kỹ thuật bạn có thể làm điều đó thông qua một ví dụ quá. Đây là liên kết để đọc cho bất kỳ ai khác có cùng câu hỏi: http://stackoverflow.com/a/3434596/4561887 –

Trả lời

138

Nếu bạn chỉ có một trường hợp nào, tốt nhất là để làm cho tất cả các biến mỗi ví dụ, đơn giản chỉ vì họ sẽ được truy cập (một ít hơn) (nhanh hơn một chút "tra cứu" do "kế thừa" từ lớp này sang thể hiện khác), và không có nhược điểm nào để cân nhắc lợi thế nhỏ này.

+6

Không bao giờ nghe nói về mẫu Borg? Chỉ có một ví dụ là sai lầm để có nó ở nơi đầu tiên. –

+378

@Devin, vâng, tôi đã nghe nói về mẫu Borg, vì tôi là người giới thiệu nó (năm 2001, cfr http://code.activestate.com/recipes/66531-singleton-we-dont-need -no-stinkin-singleton-the-bo/;-). Nhưng không có gì sai, trong những trường hợp đơn giản, chỉ đơn giản là có một cá thể đơn lẻ không có sự thi hành. –

+0

Có điểm chuẩn nào không? – user1767754

18

Khi nghi ngờ, bạn có thể muốn có thuộc tính đối tượng.

Thuộc tính lớp được dành riêng tốt nhất cho các trường hợp đặc biệt khi chúng có ý nghĩa. Trường hợp sử dụng rất phổ biến là các phương thức. Không phải là không phổ biến để sử dụng thuộc tính lớp cho các chỉ đọc mà các trường hợp cần biết (mặc dù lợi ích duy nhất cho điều này là nếu bạn cũng muốn truy cập từ bên ngoài lớp), nhưng bạn nên thận trọng về việc lưu trữ bất kỳ trạng thái nào trong chúng, điều này hiếm khi bạn muốn. Ngay cả khi bạn sẽ chỉ có một thể hiện, bạn nên viết lớp như bạn sẽ làm bất kỳ trường hợp nào khác, thường có nghĩa là sử dụng các thuộc tính instance.

+0

Các biến lớp là một loại hằng số chỉ đọc. Nếu Python cho phép tôi định nghĩa các hằng số, tôi đã viết nó thành hằng số. – deamon

+1

@ deamon, tôi có nhiều khả năng đặt các hằng số của mình hoàn toàn bên ngoài định nghĩa lớp và đặt tên chúng trong tất cả các mũ. Đặt chúng vào trong lớp cũng tốt. Làm cho chúng thuộc tính thể hiện sẽ không làm tổn thương bất cứ điều gì, nhưng có thể là một chút kỳ lạ. Tôi không nghĩ rằng đây là một vấn đề mà cộng đồng được đằng sau một trong các tùy chọn quá nhiều. –

+0

@MikeGraham FWIW, [Hướng dẫn về kiểu Python của Google] (http://google-styleguide.googlecode.com/svn/trunk/pyguide.html?showone=Global_variables#Global_variables) đề xuất để tránh các biến toàn cục có lợi cho các biến lớp. Có ngoại lệ mặc dù. – Dennis

36

tiếp tục lặp lại lời khuyên của mike và alex và thêm màu của riêng tôi ...

sử dụng thuộc tính ví dụ là Python điển hình, độc đáo hơn. các thuộc tính lớp không được sử dụng - ít nhất là không có trong mã sản xuất trong 13 năm liên tiếp của tôi về Python. điều tương tự cũng đúng đối với các phương thức tĩnh và lớp ... không phổ biến lắm trừ khi có một ca sử dụng cụ thể hoặc một lập trình viên không muốn hiển thị chúng biết một số góc tối nghĩa của lập trình Python.

alex đề cập đến câu trả lời của mình rằng quyền truy cập sẽ nhanh hơn một chút do mức độ tra cứu ít hơn ... hãy để tôi làm rõ thêm cho những người chưa biết về cách hoạt động này, nó rất giống để truy cập biến - việc tìm kiếm sẽ xảy ra theo thứ tự này:

  1. người dân địa phương
  2. nonlocals
  3. globals
  4. built-in

để truy cập thuộc tính, thứ tự là:

  1. dụ
  2. lớp
  3. lớp cơ sở được xác định bởi MRO (phương pháp để giải quyết)

trong ví dụ của bạn ở trên, giả sử bạn' đang tìm kiếm thuộc tính path. khi nó gặp một tham chiếu như "self.path", Python sẽ xem xét các thuộc tính đối tượng đầu tiên cho phù hợp; khi thất bại, nó sẽ kiểm tra lớp mà từ đó đối tượng được khởi tạo từ đó.cuối cùng, nó sẽ tìm kiếm các lớp cơ sở. như alex đã nói, nếu thuộc tính của bạn được tìm thấy trong trường hợp, nó sẽ không trì hoãn lớp, do đó bạn tiết kiệm chút thời gian.

Tuy nhiên, nếu bạn nhấn mạnh vào các thuộc tính lớp, bạn sẽ phải từ bỏ chút này về hiệu suất, hoặc, thay thế khác của bạn là để tham khảo các đối tượng thông qua các lớp thay vì dụ, ví dụ, MyController.path thay của self.path. đó là một tra cứu trực tiếp mà sẽ nhận được xung quanh tra cứu trả chậm, nhưng như đề cập bên dưới, đó là biến toàn cục, vì vậy bạn mất bit mà bạn nghĩ bạn sẽ lưu (trừ khi bạn tạo tham chiếu cục bộ cho tên lớp [toàn cục]).

+0

@wescpy, nhưng 'MyController' được tra cứu trong các hình cầu, vì vậy tổng chi phí cao hơn' self.path' trong đó 'path' là một biến cá thể (vì' self' là _local_ đến method == super-fast tra cứu). –

+0

ah, đúng. nắm bắt tốt. tôi đoán cách giải quyết duy nhất là tạo một tham chiếu cục bộ ... vào thời điểm này, nó không thực sự đáng giá. – wescpy

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