2012-01-29 26 views
142

thể trùng lặp:
Variables inside and outside of a class __init__() functioncách chính xác để xác định các biến lớp trong Python

tôi nhận thấy rằng bằng Python, người khởi tạo lớp học của họ thuộc tính theo hai cách khác nhau.

Cách thứ nhất là như thế này:

class MyClass: 
    __element1 = 123 
    __element2 = "this is Africa" 

    def __init__(self): 
    #pass or something else 

Các phong cách khác trông giống như:

class MyClass: 
    def __init__(self): 
    self.__element1 = 123 
    self.__element2 = "this is Africa" 

Đó là cách chính xác để khởi tạo các thuộc tính lớp học?

+3

sự khác biệt không lớn nếu bạn sử dụng chuỗi ... nhưng nó sẽ nhận được một điều hoàn toàn khác nếu bạn sử dụng dicts hoặc danh sách được lưu trữ bằng tham chiếu – Bastian

Trả lời

355

Cả hai cách đều không đúng hoặc không chính xác, họ chỉ là hai loại khác nhau của các yếu tố lớp:

  • Elements ngoài phương pháp __init__ là những yếu tố tĩnh, nó có nghĩa là, họ thuộc về lớp.
  • Các phần tử bên trong phương thức __init__ là các phần tử của đối tượng (self), chúng không thuộc về lớp.

Bạn sẽ thấy nó rõ ràng hơn với một số mã:

class MyClass: 
    static_elem = 123 

    def __init__(self): 
     self.object_elem = 456 

c1 = MyClass() 
c2 = MyClass() 

# Initial values of both elements 
>>> print c1.static_elem, c1.object_elem 
123 456 
>>> print c2.static_elem, c2.object_elem 
123 456 

# Nothing new so far ... 

# Let's try changing the static element 
MyClass.static_elem = 999 

>>> print c1.static_elem, c1.object_elem 
999 456 
>>> print c2.static_elem, c2.object_elem 
999 456 

# Now, let's try changing the object element 
c1.object_elem = 888 

>>> print c1.static_elem, c1.object_elem 
999 888 
>>> print c2.static_elem, c2.object_elem 
999 456 

Như bạn có thể thấy, khi chúng ta thay đổi các yếu tố giai cấp, nó thay đổi cho cả hai đối tượng. Nhưng, khi chúng ta thay đổi phần tử đối tượng, đối tượng kia vẫn không thay đổi.

+2

nhưng __init__ luôn được thực thi sau khi đối tượng được tạo. để xác định các biến bên ngoài __init__, phải không? – jeanc

+0

sự khác biệt lớn là các phần tử tĩnh thuộc về lớp, không phải đối tượng. Tôi sẽ chỉnh sửa câu trả lời của mình với một chút giải thích thêm. – juliomalegria

+2

Nếu bạn thay đổi một thuộc tính lớp (một thuộc tính được định nghĩa bên ngoài '__init __()') nó thay đổi cho cả lớp. Nó cũng sẽ thay đổi cho các cá thể khác trong khi các thuộc tính instance (được định nghĩa trong '__init __()') là đặc trưng cho mỗi cá thể. – nitsas

7

Tôi nghĩ rằng mẫu này giải thích sự khác biệt giữa phong cách:

[email protected]:~$cat test.py 
#!/usr/bin/env python 

class MyClass: 
    element1 = "Hello" 

    def __init__(self): 
     self.element2 = "World" 

obj = MyClass() 

print dir(MyClass) 
print "--" 
print dir(obj) 
print "--" 
print obj.element1 
print obj.element2 
print MyClass.element1 + " " + MyClass.element2 
[email protected]:~$./test.py 
['__doc__', '__init__', '__module__', 'element1'] 
-- 
['__doc__', '__init__', '__module__', 'element1', 'element2'] 
-- 
Hello World 
Hello 
Traceback (most recent call last): 
    File "./test.py", line 17, in <module> 
    print MyClass.element2 
AttributeError: class MyClass has no attribute 'element2' 

element1 được ràng buộc với lớp, element2 là ràng buộc để một thể hiện của lớp.

+0

cảm ơn câu trả lời của bạn – jeanc

+3

Phát biểu cuối cùng của bạn không chính xác; đối tượng không nhận được * bản sao * của các biến lớp. Tất cả các cá thể của một lớp chia sẻ quyền truy cập vào cùng một biến lớp. – Ben

+1

@Ben Bạn nói đúng; Tôi đã xóa câu đó. –

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