2014-08-29 21 views
16

Tôi có lớp này:Python - Truy cập lớp biến từ dụ

class ReallyLongClassName: 

    static_var = 5 

    def instance_method(self): 
     ReallyLongClassName.static_var += 1 

Có một số cách để truy cập các biến tĩnh bằng cách sử dụng biến tự? Tôi thích làm một cái gì đó như class(self).static_var += 1, bởi vì tên dài là không đọc được.

Trả lời

24

Sử dụng self.__class__.classAttr. Điều này sẽ hoạt động cho cả lớp học kiểu cũ & mới.

+0

Câu trả lời này nên được upvoted một số nhiều hơn ... nó tránh nguy cơ gõ toàn bộ tên lớp đặc biệt nếu nó dài để có được một thuộc tính. – repzero

+0

Đây có phải là bằng cách nào đó tốt hơn 'loại (tự)'? – Alexey

+0

@Alexey xem các nhận xét trên https://stackoverflow.com/a/25577642/5241481 –

23

Câu trả lời là "có, nhưng ..."

Cách tốt nhất để hiểu là để thực sự thử nó:

>>> class RLCN: 
...  static_var = 5 
...  def method1(self): 
...   RLCN.static_var += 1 
...  def method2(self): 
...   self.static_var += 1 
>>> rlcn = RLCN() 
>>> RLCN.static_var, rlcn.static_var 
(5, 5) 
>>> rlcn.static_var 
5 
>>> rlcn.method1() 
>>> RLCN.static_var, rlcn.static_var 
(6, 6) 
>>> rlcn.method2() 
>>> RLCN.static_var, rlcn.static_var 
(6, 7) 

gì đã xảy ra?

Vâng, truy cập thuộc tính lớp thông qua self chỉ hoạt động tốt. Nếu không có thuộc tính instance của cùng một tên, bạn sẽ có thuộc tính class.

Nhưng gán cho nó sẽ ẩn thuộc tính lớp với thuộc tính thể hiện mới có cùng tên. Mà có lẽ không phải là những gì bạn muốn.

Lưu ý rằng điều này có nghĩa là bạn có thể sử dụng thuộc tính lớp là "giá trị mặc định" hoặc "giá trị ban đầu" cho các thuộc tính mẫu. Nhưng tôi không chắc chắn nó là rất Pythonic để làm như vậy; những gì thực sự xảy ra, và những gì một người mới (đặc biệt là một người đến từ, ví dụ, C++ 11 hoặc Java) nghĩ rằng đang xảy ra, rất khác nhau.

(Mọi thứ trở nên hơi phức tạp hơn khi bạn đối phó với mô tả, giống như phương pháp hoặc @property s, nhưng chúng ta hãy bỏ qua đó;. Trong trường hợp đơn giản mà bạn đang thảo luận, nó không liên quan)


Tôi muốn làm một cái gì đó như lớp (self) .static_var + = 1, bởi vì tên dài là không đọc được.

Bạn có thể, bạn chỉ cần đánh vần đúng: type là hàm trả về loại đối tượng bất kỳ. Vì vậy:

type(self).static_var += 1 

này có lợi thế nhất của việc năng động (ví dụ, khi bạn có nhiều kế thừa và không biết được bên một @property đến từ đâu, có thể bạn không muốn liệt kê một cách rõ ràng tên lớp, về cơ bản cùng một lý do bạn muốn sử dụng super() thay vì gọi một cách rõ ràng phương thức lớp cơ sở).

Điều này có bất lợi khi không làm việc trên các lớp kiểu cũ trong Python 2.x, nhưng sau đó bạn không nên sử dụng những thứ đó. Đặc biệt trong các lớp có nhu cầu về thuộc tính lớp, vì đó là chính xác các loại bạn thường muốn sau này muốn thêm @classmethod s, @property s, v.v., và không có loại nào phù hợp với các lớp kiểu cũ (cùng với nhiều thứ khác). Nếu bạn thực sự cần xử lý các lớp kiểu cũ và kiểu mới một cách minh bạch vì một lý do nào đó, self.__class__ hoạt động với các lớp kiểu cũ. Tôi không chắc chắn rằng nó được đảm bảo để làm việc với các lớp học theo phong cách mới; các tài liệu nói rằng giá trị trả lại của type(object) là "thường là cùng một đối tượng như được trả về bởi object.__class__", nhưng không nói theo những điều kiện "chung" là không đúng sự thật. Nó cũng được ghi nhận là special attribute "added by the implementation" for "several object types" trong 3.x. Trong thực tế, tôi không biết bất kỳ trường hợp nào mà chúng khác nhau trong 3.x, và trong 2.x, trường hợp nổi bật nhất mà chúng khác nhau là các lớp kiểu cũ.

+0

Dường như 'loại (tự) .static_var + = 1' chỉ hoạt động trong Python3. –

+0

@AntonSavin: Không, nó hoạt động trong Python 2 tốt. Xem nó [ở đây] (http://repl.it/XrJ) trong Python 2.7.2. – abarnert

+0

Ah và [như thế này] (http://repl.it/XrJ/1) thì không. –

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