Làm thế nào để so sánh loại đối tượng trong Python?


163

Về cơ bản tôi muốn làm điều này:

obj = 'str'
type ( obj ) == string

Tôi đã thử:

type ( obj ) == type ( string )

và nó đã không hoạt động.

Ngoài ra, những gì về các loại khác? Ví dụ, tôi không thể sao chép NoneType.


Tác phẩm nàytype(obj) == str
Joshua Varghese

Câu trả lời:


241
isinstance()

Trong trường hợp của bạn, isinstance("this is a string", str)sẽ trở lại True.

Bạn cũng có thể muốn đọc điều này: http://www.canonical.org/~kragen/isinstance/


4
Tôi muốn nói rằng bạn (OP) chắc chắn nên đọc liên kết được tham chiếu, nó cung cấp nhiều chi tiết về lý do tại sao kiểm tra loại đối tượng thường là một ý tưởng tồi và thay vào đó bạn nên làm gì.
Jeff Shannon

2
bạn nên sử dụng basestr, không str. nếu không bạn sẽ không chọn unicode. (mặc dù đối với 3.x tôi nghĩ str basestr)
hasen

36

isinstance làm:

if isinstance(obj, MyClass): do_foo(obj)

nhưng , hãy nhớ rằng: nếu nó trông giống như một con vịt, và nếu nó giống như một con vịt, thì đó là một con vịt.

EDIT: Đối với loại Không có, bạn chỉ cần làm:

if obj is None: obj = MyClass()

def distance_from_zero(n): if isinstance(n,int) or isinstance(n,float): return abs(n) else: return "Nope" print distance_from_zero(True) Điều này trả về "1" thay vì "Không". Làm thế nào để có được xung quanh này?
dig_123

Nếu bạn muốn sử dụng isinstancenhưng kiểm tra cũng cho Nonesau đó isinstance(obj, (MyClass, type(None)))công trình. types.NoneTypeđã bị xóa khỏi Python 3 vì vậy nó không dễ mang theo type(None)để tham khảo NoneType.
Santeri Paavolainen 17/2/2016

33

Đầu tiên, tránh tất cả các so sánh loại. Chúng rất, rất hiếm khi cần thiết. Đôi khi, chúng giúp kiểm tra các loại tham số trong một hàm - thậm chí đó là hiếm. Dữ liệu loại sai sẽ đưa ra một ngoại lệ và đó là tất cả những gì bạn cần.

Tất cả các hàm chuyển đổi cơ bản sẽ ánh xạ bằng với hàm loại.

type(9) is int
type(2.5) is float
type('x') is str
type(u'x') is unicode
type(2+3j) is complex

Có một vài trường hợp khác.

isinstance( 'x', basestring )
isinstance( u'u', basestring )
isinstance( 9, int )
isinstance( 2.5, float )
isinstance( (2+3j), complex )

Không, BTW, không bao giờ cần bất kỳ loại kiểm tra loại này. Không có gì là trường hợp duy nhất của noneType. Đối tượng Không có là một Singleton. Chỉ cần kiểm tra Không

variable is None

BTW, không sử dụng ở trên nói chung. Sử dụng các ngoại lệ thông thường và tính đa hình tự nhiên của Python.


3
Nếu bạn xác nhận đầu vào từ DSL, bạn cần tất cả điều này, thậm chí NoneType. Điều gì nếu một tham số có thể là một str, unicodehoặc None? isinstance(x, (str, unicode, types.NoneType))có nhiều bụi hơn kiểm tra None. Nếu bạn đang xây dựng các công cụ để tính toán hoãn lại hoặc nếu bạn sắp khởi chạy một quy trình dài hoặc tốn nhiều tài nguyên, thì việc bắt typelỗi trước thời hạn, trong một số bước xác thực tùy chỉnh là rất có giá trị . Đây là một phần quan trọng trong hầu hết các dự án điện toán khoa học mà tôi từng làm. Trong số tất cả các dự án dev tôi đã thấy, cần nhiều thứ hơn là không có.
ely

23

Đối với các loại khác, hãy kiểm tra mô-đun loại :

>>> import types
>>> x = "mystring"
>>> isinstance(x, types.StringType)
True
>>> x = 5
>>> isinstance(x, types.IntType)
True
>>> x = None
>>> isinstance(x, types.NoneType)
True

PS typechecking là một ý tưởng tồi.


15

Bạn luôn có thể sử dụng type(x) == type(y)thủ thuật, đâu ylà thứ có loại đã biết.

# check if x is a regular string
type(x) == type('')
# check if x is an integer
type(x) == type(1)
# check if x is a NoneType
type(x) == type(None)

Thường có nhiều cách tốt hơn để làm điều đó, đặc biệt với bất kỳ con trăn nào gần đây. Nhưng nếu bạn chỉ muốn nhớ một điều, bạn có thể nhớ điều đó.

Trong trường hợp này, những cách tốt hơn sẽ là:

# check if x is a regular string
type(x) == str
# check if x is either a regular string or a unicode string
type(x) in [str, unicode]
# alternatively:
isinstance(x, basestring)
# check if x is an integer
type(x) == int
# check if x is a NoneType
x is None

Lưu ý trường hợp cuối cùng: chỉ có một trường hợp NoneTypetrong python, và đó là None. Bạn sẽ thấy Không có nhiều trường hợp ngoại lệ ( TypeError: 'NoneType' object is unsubscriptable- xảy ra với tôi mọi lúc ..) nhưng bạn sẽ hầu như không cần phải đề cập đến nó trong mã.

Cuối cùng, như fengshaun chỉ ra, việc kiểm tra trăn không phải lúc nào cũng là một ý kiến ​​hay. Sẽ tốt hơn khi chỉ sử dụng giá trị như thể đó là loại bạn mong đợi và bắt (hoặc cho phép truyền bá) các ngoại lệ phát sinh từ nó.


1
Đối với những gì nó có giá trị, isinstance () là cách kiểm tra các loại ưa thích trong Python (khi bạn phải làm điều đó).
David Z

6

Bạn đang ở rất gần! stringlà một mô-đun, không phải là một loại. Bạn có thể muốn so sánh kiểu objso với đối tượng loại cho chuỗi, cụ thể là str:

type(obj) == str  # this works because str is already a type

Cách khác:

type(obj) == type('')

Lưu ý, trong Python 2, nếu objlà một loại unicode, thì cả hai cách trên đều không hoạt động. Cũng sẽ không isinstance(). Xem bình luận của John cho bài đăng này để biết cách khắc phục điều này ... Tôi đã cố nhớ nó trong khoảng 10 phút, nhưng đã có một khối bộ nhớ!


2
Sử dụng basestring với isinstance () để có cả str và unicode.
John Fouhy

5

Đó là bởi vì bạn phải viết

s="hello"
type(s) == type("")

loại chấp nhận một thể hiện và trả về kiểu của nó. Trong trường hợp này, bạn phải so sánh hai loại trường hợp.

Nếu bạn cần thực hiện kiểm tra phòng ngừa, sẽ tốt hơn nếu bạn kiểm tra giao diện được hỗ trợ so với loại.

Loại này không thực sự cho bạn biết nhiều, ngoài thực tế là mã của bạn muốn có một thể hiện của một loại cụ thể, bất kể thực tế là bạn có thể có một thể hiện khác của một loại hoàn toàn khác hay không vì nó thực hiện cùng một giao diện .

Ví dụ: giả sử bạn có mã này

def firstElement(parameter):
    return parameter[0]

Bây giờ, giả sử bạn nói: Tôi muốn mã này chỉ chấp nhận một tuple.

import types

def firstElement(parameter):
    if type(parameter) != types.TupleType:
         raise TypeError("function accepts only a tuple")
    return parameter[0]

Điều này đang làm giảm khả năng tái sử dụng của thói quen này. Nó sẽ không hoạt động nếu bạn vượt qua một danh sách, hoặc một chuỗi, hoặc một numpy.array. Một cái gì đó tốt hơn sẽ là

def firstElement(parameter):
    if not (hasattr(parameter, "__getitem__") and callable(getattr(parameter,"__getitem__"))):
        raise TypeError("interface violation")
    return parameter[0]

nhưng không có lý do gì để thực hiện nó: tham số [0] sẽ đưa ra một ngoại lệ nếu giao thức không được thỏa mãn dù sao đi nữa ... điều này tất nhiên trừ khi bạn muốn ngăn chặn tác dụng phụ hoặc phải phục hồi từ các cuộc gọi mà bạn có thể gọi trước khi thất bại. (Ngốc) ví dụ, chỉ để đưa ra quan điểm:

def firstElement(parameter):
    if not (hasattr(parameter, "__getitem__") and callable(getattr(parameter,"__getitem__"))):
        raise TypeError("interface violation")
    os.system("rm file")
    return parameter[0]

trong trường hợp này, mã của bạn sẽ đưa ra một ngoại lệ trước khi chạy lệnh gọi system (). Nếu không kiểm tra giao diện, bạn sẽ xóa tệp và sau đó đưa ra ngoại lệ.


Cảm ơn đã chỉ ra cách ưa thích thực tế để kiểm tra giao diện. Nhiều câu trả lời ở đây đề cập đến nó, nhưng ít người đưa ra ví dụ về những gì tốt thay thế. Nó vẫn không trả lời trực tiếp câu hỏi cá nhân của tôi (Tôi đang cố tách một danh sách các chuỗi, chứa nhiều mục có ý nghĩa, từ một chuỗi chứa nhiều mục không có ý nghĩa. Cảm ơn!
Nick

5

Sử dụng str thay vì chuỗi

type ( obj ) == str

Giải trình

>>> a = "Hello"
>>> type(a)==str
True
>>> type(a)
<type 'str'>
>>>

4

tôi sử dụng type(x) == type(y)

Ví dụ, nếu tôi muốn kiểm tra một cái gì đó là một mảng:

type( x ) == type( [] )

kiểm tra chuỗi:

type( x ) == type( '' ) or type( x ) == type( u'' )

Nếu bạn muốn kiểm tra không có, sử dụng là

x is None

Huh? Tại sao nó là một ý tưởng tồi nói chung? Đây chỉ là một ý tưởng tồi cho các chuỗi (cho trước 3.0) vì có hai loại chuỗi, str và unicode. Đối với mảng, đó là một ý tưởng tốt imho.
hasen

@hasen: đó là một ý tưởng tồi tổng thể. Điều gì sẽ xảy ra nếu tôi xác định loại của riêng mình hoạt động như một mảng nhưng, giả sử, lấy các giá trị từ cơ sở dữ liệu? Mã của bạn sẽ thất bại với loại của tôi không có lý do.
nosklo

@hasen: đọc liên kết canonical.org/~kragen/isinstance của câu trả lời được bình chọn nhiều nhất (+7), bởi voltronw
nosklo

1
Vâng, toàn bộ lý do (đối với tôi ít nhất) trong việc kiểm tra loại chính xác là vì tôi muốn xử lý các mảng khác với các loại khác (bao gồm cả các loại bắt chước mảng).
hasen

2
Bạn sai rồi. Tôi sẽ cho bạn một ví dụ cụ thể: django có một phím tắt kết xuất mẫu có thể chấp nhận một chuỗi hoặc một chuỗi các chuỗi. Bây giờ, cả chuỗi và mảng (danh sách) đều có thể lặp lại, nhưng trong trường hợp này, các hàm cần phân biệt giữa chúng.
hasen

2

tôi nghĩ điều này nên làm điều đó

if isinstance(obj, str)

2

Loại không hoạt động trên các lớp nhất định. Nếu bạn không chắc chắn về loại đối tượng, hãy sử dụng __class__phương thức, như vậy:

>>>obj = 'a string'
>>>obj.__class__ == str
True

Cũng xem bài viết này - http://www.siafoo.net/article/56


2

Để có được loại, sử dụng __class__thành viên, như trongunknown_thing.__class__

Nói về gõ vịt là vô ích ở đây vì nó không trả lời một câu hỏi hoàn toàn tốt. Trong mã ứng dụng của tôi, tôi không bao giờ cần phải biết loại của một cái gì đó, nhưng vẫn hữu ích để có cách tìm hiểu loại của một đối tượng. Đôi khi tôi cần phải nhận được lớp thực tế để xác nhận một bài kiểm tra đơn vị. Việc gõ vịt được thực hiện theo cách đó bởi vì tất cả các đối tượng có thể có cùng một API, nhưng chỉ có một điều đúng. Ngoài ra, đôi khi tôi đang duy trì mã của người khác và tôi không biết tôi đã được thông qua loại đối tượng nào. Đây là vấn đề lớn nhất của tôi với các ngôn ngữ được gõ động như Python. Phiên bản 1 rất dễ dàng và nhanh chóng để phát triển. Phiên bản 2 là một vấn đề khó khăn, đặc biệt là nếu bạn không viết phiên bản 1. Vì vậy, đôi khi, khi tôi làm việc với một chức năng tôi không viết, tôi cần biết loại tham số,

Đó là nơi __class__tham số có ích. Điều đó (theo như tôi có thể nói) là cách tốt nhất (có thể là cách duy nhất) để có được một loại đối tượng.


2

Sử dụng isinstance(object, type). Như trên đây là dễ sử dụng nếu bạn biết chính xác type, ví dụ,

isinstance('dog', str) ## gives bool True

Nhưng đối với các đối tượng bí truyền hơn, điều này có thể khó sử dụng. Ví dụ:

import numpy as np 
a = np.array([1,2,3]) 
isinstance(a,np.array) ## breaks

nhưng bạn có thể làm thủ thuật này:

y = type(np.array([1]))
isinstance(a,y) ## gives bool True 

Vì vậy, tôi khuyên bạn nên khởi tạo một biến ( ytrong trường hợp này) bằng một loại đối tượng bạn muốn kiểm tra (ví dụ type(np.array()):), sau đó sử dụng isinstance.


0

Bạn có thể so sánh các lớp để kiểm tra mức độ.

#!/usr/bin/env python
#coding:utf8

class A(object):
    def t(self):
        print 'A'
    def r(self):
        print 'rA',
        self.t()

class B(A):
    def t(self):
        print 'B'

class C(A):
    def t(self):
        print 'C'

class D(B, C):
    def t(self):
        print 'D',
        super(D, self).t()

class E(C, B):
    pass

d = D()
d.t()
d.r()

e = E()
e.t()
e.r()

print isinstance(e, D) # False
print isinstance(e, E) # True
print isinstance(e, C) # True
print isinstance(e, B) # True
print isinstance(e, (A,)) # True
print e.__class__ >= A, #False
print e.__class__ <= C, #False
print e.__class__ <  E, #False
print e.__class__ <= E  #True
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.