2012-10-18 23 views
21

Làm thế nào để python phân biệt một thuộc tính lớp, thuộc tính instance và phương thức khi các tên giống nhau?python: Điều gì xảy ra khi thuộc tính lớp, thuộc tính instance và phương thức tất cả đều có cùng tên?

class Exam(object): 

    test = "class var" 

    def __init__(self, n): 
     self.test = n 

    def test(self): 
     print "method : ",self.test 

test_o = Exam("Fine") 

print dir(test_o) 

print Exam.test 
print test_o.test 
test_o.test() 

Output:

['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'test'] 
<unbound method load.test> 
Fine 
Traceback (most recent call last): 
    File "example.py", line 32, in <module> 
    test_o.test() 
TypeError: 'str' object is not callable 

Làm thế nào để gọi

  1. thuộc tính lớp, Exam.test -><unbound method load.test> đầu ra cho thấy phương pháp
  2. dụ thuộc tính test_o.test ->"Fine"
  3. phương pháp test_o.test() ->TypeError: 'str' object is not callable

Trả lời

2

Bạn có thể viết

Exam.test(test_o) 

hoặc

Exam.test.__get__(test_o)() 

Trong trường hợp sau bạn đang sử dụng thực tế là phương pháp descriptors để chuyển đổi <unbound method load.test> đến một ràng buộc phương pháp, vì vậy bạn có thể gọi nó bằng dấu ngoặc đơn.

Khi bạn viết test_o.test(), Python không biết rằng bạn đang cố gọi một phương thức; bạn có thể đang cố gắng gọi một hàm hoặc một đối tượng có thể gọi được đã được cài đặt trên đối tượng như một thành viên dữ liệu cá thể. Thay vào đó nó tìm kiếm thuộc tính test, đầu tiên trên đối tượng và sau đó trên lớp của nó, nhưng vì thuộc tính tồn tại trên đối tượng, nó ẩn phương thức trên lớp.

Các thành viên lớp

test = "class var" 

không truy cập được (trong thực tế nó không tồn tại bất cứ nơi nào), bởi vì nó được ghi đè bởi các phương pháp test; khi một class statement được thực hiện, không gian tên của nó được thu thập thành một dict trước khi được chuyển tới metaclass của nó, và sau đó các tên ghi đè lên những cái trước đó.

+0

gì sai với gọi test_o.test()? – naren

+0

@naren bạn đang cố gắng gọi cho thành viên cá thể; xem ở trên. – ecatmur

1

Bạn có thể gọi phương pháp như phương pháp lớp học và vượt qua ví dụ của bạn vào nó:

Exam.test(test_o) 

Hoặc, nếu bạn không muốn sử dụng Exam:

type(test_o).test(test_o) 
17

thuộc tính lớp có thể truy cập thông qua các lớp :

YourClass.clsattribute 

hoặc thông qua trường hợp (nếu cá thể chưa được ghi đè ritten thuộc tính lớp):

instance.clsattribute 

Phương pháp, như đã nêu by ecatmur in his answer, là các bộ mô tả và được đặt làm thuộc tính lớp.

Nếu bạn truy cập một phương thức thông qua cá thể, thì cá thể được chuyển thành tham số self cho bộ mô tả. Nếu bạn muốn gọi một phương thức từ lớp, thì bạn phải chuyển một đối tượng rõ ràng làm đối số đầu tiên. Vì vậy, đây là những tương đương:

instance.method() 
MyClass.method(instance) 

Sử dụng cùng tên cho một thuộc tính ví dụ và một phương pháp sẽ làm cho các phương pháp ẩn qua các ví dụ, nhưng phương pháp này vẫn còn có sẵn thông qua các lớp:

#python3 
>>> class C: 
...  def __init__(self): 
...   self.a = 1 
...  def a(self): 
...   print('hello') 
... 
>>> C.a 
<function a at 0x7f2c46ce3c88> 
>>> instance = C() 
>>> instance.a 
1 
>>> C.a(instance) 
hello 

Kết luận : không đưa cùng tên cho các thuộc tính và phương thức mẫu. Tôi tránh điều này bằng cách đặt tên có ý nghĩa. Phương pháp là hành động, vì vậy tôi thường sử dụng động từ hoặc câu cho chúng. Thuộc tính là dữ liệu, vì vậy tôi sử dụng danh từ/tính từ cho chúng, và điều này tránh sử dụng cùng tên cho cả hai phương thức và thuộc tính. Lưu ý rằng bạn chỉ đơn giản là không thể có một thuộc tính lớp có cùng tên như một phương thức, bởi vì phương thức sẽ ghi đè hoàn toàn nó (cuối cùng, các phương thức chỉ là các thuộc tính lớp có thể gọi được và tự động nhận một thể hiện của lớp đó). như thuộc tính đầu tiên).

0

Làm thế nào để gọi
lớp thuộc tính, Exam.test

Bạn có thể không phải vì khi thực hiện def test(self) tên test được ràng buộc với phương thức trong lớp và tham chiếu đến "class var" bị mất. thuộc tính

dụ test_o.test -> "Fine"

Bạn đã làm điều đó.

phương pháp test_o.test()

Bạn không thể gọi nó như vậy vì khi thực hiện self.test = n tên test là ràng buộc để bất cứ điều gì đối tượng tài liệu tham khảo n trong trường hợp và tham chiếu đến phương pháp trong trường hợp bị mất .

Nhưng khi chỉ trong câu trả lời khác bạn có thể gọi phương thức trong lớp và truyền thể hiện với nó: Exam.test(test_o)

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