2009-06-29 59 views
35

Sự khác nhau giữa type(obj)obj.__class__ là gì? Có bao giờ một khả năng của type(obj) is not obj.__class__?Sự khác biệt giữa loại (obj) và obj .__ class__

Tôi muốn viết một hàm hoạt động chung trên các đối tượng được cung cấp, sử dụng giá trị mặc định là 1 trong cùng loại với tham số khác. Biến thể nào, # 1 hoặC# 2 bên dưới, sẽ làm điều đúng?

def f(a, b=None): 
    if b is None: 
    b = type(a)(1) # #1 
    b = a.__class__(1) # #2 

Trả lời

12

type(obj)type.__class__ không cư xử như nhau đối với các lớp học kiểu cũ:

>>> class a(object): 
...  pass 
... 
>>> class b(a): 
...  pass 
... 
>>> class c: 
...  pass 
... 
>>> ai=a() 
>>> bi=b() 
>>> ci=c() 
>>> type(ai) is ai.__class__ 
True 
>>> type(bi) is bi.__class__ 
True 
>>> type(ci) is ci.__class__ 
False 
+7

Sự trớ trêu lớn nhất là bình luận của yairchu bây giờ có cùng một vấn đề vì chúng đã chuyển đổi định dạng ..: P –

+10

Sẽ không làm tổn thương để hiển thị * cách chúng cư xử khác nhau, và cũng có thể * tại sao *. Chỉ cần nói * khi * họ cư xử khác nhau nghe có vẻ là một câu trả lời lười biếng, ngay cả khi chính xác. – MestreLion

+1

đáng nói đến đây chỉ là vấn đề trong Python 2. Trong Python 3 cả ba biểu thức sẽ là True. – Bob

30

lớp kiểu cũ là vấn đề, thở dài:

>>> class old: pass 
... 
>>> x=old() 
>>> type(x) 
<type 'instance'> 
>>> x.__class__ 
<class __main__.old at 0x6a150> 
>>> 

Không phải là một vấn đề trong Python 3 vì tất cả các lớp học kiểu mới tại ;-).

Trong Python 2, một lớp là kiểu mới chỉ khi nó được thừa hưởng từ một lớp học kiểu mới (bao gồm cả object và khác nhau được tích hợp trong các loại như dict, list, set ...) hoặc ngầm hoặc công khai đặt __metaclass__ đến type.

+3

Đó là thời gian Python 3, * nên * chúng tôi sử dụng? –

+2

Nếu mã của bạn đang thực hiện tốt nhất theo mô tả của Alex, 'type()' sẽ thích hợp hơn. Trong Python 3, nó luôn luôn theo sau thực hành tốt nhất, vì vậy hãy sử dụng type() trong Python 3. –

+0

@AaronHall Tôi có đúng không khi cho rằng sử dụng 'type()' cũng được ưu tiên hơn '__class__' nếu tôi đang viết Python 2 mã mà tôi biết rằng nó sẽ chỉ được gọi với các trường hợp của các lớp kiểu mới? – kasperd

30

Đây là một câu hỏi cũ, nhưng không ai trong số các câu trả lời dường như đề cập đến đó. trong trường hợp tổng quát, nó có thể cho một lớp học kiểu mới có giá trị khác nhau cho type(instance)instance.__class__:

class ClassA(object): 
    def display(self): 
     print("ClassA") 

class ClassB(object): 
    __class__ = ClassA 

    def display(self): 
     print("ClassB") 

instance = ClassB() 

print(type(instance)) 
print(instance.__class__) 
instance.display() 

Output:

<class '__main__.ClassB'> 
<class '__main__.ClassA'> 
ClassB 

Lý do là ClassB được trọng các __class__ mô tả, tuy nhiên trường kiểu nội bộ trong đối tượng không bị thay đổi. type(instance) đọc trực tiếp từ trường loại đó, vì vậy nó trả về giá trị chính xác, trong khi instance.__class__ đề cập đến bộ mô tả mới thay thế bộ mô tả ban đầu do Python cung cấp, đọc trường kiểu nội bộ. Thay vì đọc trường kiểu nội bộ đó, nó trả về một giá trị mã hóa cứng.

+10

_Caveat lector_: điều này nên được lấy làm ví dụ về lý do tại sao bạn nên tránh ghi đè '__class__'! Bạn có thể làm cho mã xuống dòng sử dụng '__class__' để ngắt. –

+0

Cũng bị ảnh hưởng bởi '__getattribute__', ngăn chặn yêu cầu cho' OBJ .__ class__' nhưng không ảnh hưởng đến 'type (OBJ)'. – kdb

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