Pertanyaan Tentukan jenis objek?


Apakah ada cara sederhana untuk menentukan apakah suatu variabel adalah daftar, kamus, atau sesuatu yang lain? Saya mendapatkan kembali objek yang mungkin tipe dan saya harus bisa membedakannya.


1378
2018-02-08 21:37


asal


Jawaban:


Untuk mendapatkan jenis objek, Anda bisa menggunakan built-in type() fungsi. Melewati objek sebagai satu-satunya parameter akan mengembalikan objek jenis objek itu:

>>> type([]) is list
True
>>> type({}) is dict
True
>>> type('') is str
True
>>> type(0) is int
True
>>> type({})
<type 'dict'>
>>> type([])
<type 'list'>

Ini tentu saja juga berfungsi untuk jenis khusus:

>>> class Test1 (object):
        pass
>>> class Test2 (Test1):
        pass
>>> a = Test1()
>>> b = Test2()
>>> type(a) is Test1
True
>>> type(b) is Test2
True

Perhatikan itu type() hanya akan mengembalikan jenis objek langsung, tetapi tidak dapat memberi tahu Anda tentang jenis warisan.

>>> type(b) is Test1
False

Untuk menutupi itu, Anda harus menggunakan isinstance fungsi. Ini tentu saja juga berfungsi untuk tipe bawaan:

>>> isinstance(b, Test1)
True
>>> isinstance(b, Test2)
True
>>> isinstance(a, Test1)
True
>>> isinstance(a, Test2)
False
>>> isinstance([], list)
True
>>> isinstance({}, dict)
True

isinstance() biasanya cara yang lebih disukai untuk memastikan jenis objek karena juga akan menerima jenis turunan. Jadi kecuali Anda benar-benar membutuhkan jenis objek (untuk alasan apa pun), gunakan isinstance() lebih disukai daripada type().

Parameter kedua dari isinstance() juga menerima tupel jenis, jadi mungkin untuk memeriksa beberapa jenis sekaligus. isinstance kemudian akan mengembalikan nilai true, jika objeknya adalah salah satu dari jenis itu:

>>> isinstance([], (tuple, list, set))
True

1603
2018-02-08 21:40



Anda dapat melakukannya menggunakan type():

>>> a = []
>>> type(a)
<type 'list'>
>>> f = ()
>>> type(f)
<type 'tuple'>

141
2018-02-08 21:39



Mungkin lebih Pythonic menggunakan try...except blok. Dengan begitu, jika Anda memiliki kelas yang menduakan seperti daftar, atau dukun seperti dict, itu akan berperilaku dengan benar terlepas dari apa jenisnya sangat aku s.

Untuk memperjelas, metode yang disukai "membedakan" antara tipe variabel adalah dengan sesuatu yang disebut bebek mengetik: selama metode (dan jenis pengembalian) yang ditanggap oleh suatu variabel adalah apa yang diharapkan oleh subrutin Anda, perlakukan seperti yang Anda harapkan. Misalnya, jika Anda memiliki kelas yang memberatkan operator braket getattr dan setattr, tetapi menggunakan beberapa skema internal yang lucu, itu akan sesuai untuk berperilaku sebagai kamus jika itu yang coba ditiru.

Masalah lainnya dengan type(A) is type(B) memeriksa apakah itu A adalah subkelas dari B, itu mengevaluasi ke false kapan, secara terprogram, Anda akan berharap itu terjadi true. Jika suatu objek adalah subkelas dari daftar, itu harus bekerja seperti daftar: memeriksa jenis seperti yang disajikan dalam jawaban lain akan mencegah hal ini. (isinstance akan bekerja, namun).


37
2018-02-08 21:43



Pada contoh objek, Anda juga memiliki:

__class__

atribut. Berikut ini contoh yang diambil dari konsol Python 3.3

>>> str = "str"
>>> str.__class__
<class 'str'>
>>> i = 2
>>> i.__class__
<class 'int'>
>>> class Test():
...     pass
...
>>> a = Test()
>>> a.__class__
<class '__main__.Test'>

Berhati-hatilah bahwa di python 3.x dan di kelas-kelas Gaya Baru (aviable opsional dari Python 2.6) kelas dan jenis telah digabungkan dan ini kadang-kadang dapat menyebabkan hasil yang tidak diharapkan. Terutama untuk alasan ini cara favorit saya untuk menguji jenis / kelas adalah dengan ini berlaku dibangun dalam fungsi.


30
2018-06-26 21:38



Tentukan jenis objek Python

Tentukan jenis objek dengan type

>>> obj = object()
>>> type(obj)
<class 'object'>

Meskipun berhasil, hindari atribut menggarisbawahi ganda seperti __class__ - mereka tidak semantik publik, dan, sementara mungkin tidak dalam kasus ini, fungsi builtin biasanya memiliki perilaku yang lebih baik.

>>> obj.__class__ # avoid this!
<class 'object'>

jenis pemeriksaan

Apakah ada cara sederhana untuk menentukan apakah suatu variabel adalah daftar, kamus, atau sesuatu yang lain? Saya mendapatkan kembali objek yang mungkin tipe dan saya harus bisa membedakannya.

Nah itu pertanyaan yang berbeda, jangan gunakan tipe - gunakan isinstance:

def foo(obj):
    """given a string with items separated by spaces, 
    or a list or tuple, 
    do something sensible
    """
    if isinstance(obj, str):
        obj = str.split()
    return _foo_handles_only_lists_or_tuples(obj)

Ini mencakup kasus di mana pengguna Anda mungkin melakukan sesuatu yang pintar atau masuk akal dengan subclassing str - sesuai dengan prinsip Liskov Substitusi, Anda ingin dapat menggunakan instance subkelas tanpa melanggar kode - dan isinstance mendukung ini.

Gunakan Abstraksi

Bahkan lebih baik, Anda mungkin mencari Kelas Basis Abstrak tertentu dari collections atau numbers:

from collections import Iterable
from numbers import Number

def bar(obj):
    """does something sensible with an iterable of numbers, 
    or just one number
    """
    if isinstance(obj, Number): # make it a 1-tuple
        obj = (obj,)
    if not isinstance(obj, Iterable):
        raise TypeError('obj must be either a number or iterable of numbers')
    return _bar_sensible_with_iterable(obj)

Atau Hanya Tidak secara eksplisit Ketik-cek

Atau, mungkin yang terbaik dari semuanya, gunakan itik-mengetik, dan jangan secara eksplisit mengetik-cek kode Anda. Duck-typing mendukung Liskov Substitution dengan lebih banyak keanggunan dan kurang verbositas.

def baz(obj):
    """given an obj, a dict (or anything with an .items method) 
    do something sensible with each key-value pair
    """
    for key, value in obj.items():
        _baz_something_sensible(key, value)

Kesimpulan

  • Menggunakan type untuk benar-benar mendapatkan kelas instance.
  • Menggunakan isinstance untuk secara eksplisit memeriksa subclass aktual atau abstraksi terdaftar.
  • Dan hindari pemeriksaan-jenis di mana itu masuk akal.

14
2018-03-14 21:12



Kamu dapat memakai type() atau isinstance().

>>> type([]) is list
True

Berhati-hatilah bahwa Anda dapat mengkritik list atau jenis lainnya dengan menetapkan variabel dalam lingkup saat ini dengan nama yang sama.

>>> the_d = {}
>>> t = lambda x: "aight" if type(x) is dict else "NOPE"
>>> t(the_d) 'aight'
>>> dict = "dude."
>>> t(the_d) 'NOPE'

Di atas kita melihat itu dict ditugasi ke string, oleh karena itu tes:

type({}) is dict

... gagal.

Untuk menyiasati ini dan gunakan type() lebih hati-hati:

>>> import __builtin__
>>> the_d = {}
>>> type({}) is dict
True
>>> dict =""
>>> type({}) is dict
False
>>> type({}) is __builtin__.dict
True

10
2018-05-31 21:57



Meskipun pertanyaannya sudah cukup lama, saya menemukan ini dengan cara sendiri, dan saya pikir itu masih perlu diklarifikasi, setidaknya untuk Python 2.x (tidak memeriksa Python 3, tetapi karena masalah muncul dengan kelas klasik yang hilang pada versi tersebut, mungkin tidak masalah).

Di sini saya mencoba menjawab pertanyaan judul: bagaimana saya bisa menentukan jenis objek arbitrer? Saran lain tentang menggunakan atau tidak menggunakan isyarat baik-baik saja dalam banyak komentar dan jawaban, tetapi saya tidak mengatasi masalah tersebut.

Masalah utama dengan type() pendekatan itu itu tidak berfungsi dengan baik dengan contoh gaya lama:

class One:
    pass

class Two:
    pass


o = One()
t = Two()

o_type = type(o)
t_type = type(t)

print "Are o and t instances of the same class?", o_type is t_type

Melaksanakan snippet ini akan menghasilkan:

Are o and t instances of the same class? True

Yang, saya pikir, bukanlah apa yang diharapkan kebanyakan orang.

Itu __class__ pendekatan adalah yang paling mendekati kebenaran, tetapi tidak akan berhasil dalam satu kasus krusial: ketika objek yang diteruskan adalah gaya lama kelas (bukan sebuah instance!), karena objek-objek tersebut tidak memiliki atribut seperti itu.

Ini adalah potongan kode terkecil yang dapat saya pikirkan yang memenuhi pertanyaan yang sah seperti itu dengan cara yang konsisten:

#!/usr/bin/env python
from types import ClassType
#we adopt the null object pattern in the (unlikely) case
#that __class__ is None for some strange reason
_NO_CLASS=object()
def get_object_type(obj):
    obj_type = getattr(obj, "__class__", _NO_CLASS)
    if obj_type is not _NO_CLASS:
        return obj_type
    # AFAIK the only situation where this happens is an old-style class
    obj_type = type(obj)
    if obj_type is not ClassType:
        raise ValueError("Could not determine object '{}' type.".format(obj_type))
    return obj_type

4
2018-06-17 08:35



Sebagai tambahan dari jawaban sebelumnya, ada baiknya disebutkan keberadaannya collections.abc yang berisi beberapa kelas dasar abstrak (ABC) yang melengkapi bebek-mengetik.

Misalnya, alih-alih secara eksplisit memeriksa apakah sesuatu itu daftar dengan:

isinstance(my_obj, list)

Anda bisa, jika Anda hanya tertarik untuk melihat apakah objek yang Anda miliki memungkinkan mendapatkan barang, gunakan collections.abc.Sequence:

from collections.abc import Sequence
isinstance(my_obj, Sequence) 

jika Anda sangat tertarik pada objek yang memungkinkan mendapatkan, pengaturan dan menghapus item (mis yg mungkin berubah urutan), Anda akan memilih collections.abc.MutableSequence.

Banyak ABC lainnya didefinisikan di sana, Mapping untuk objek yang dapat digunakan sebagai peta, Iterable, Callable, dan sebagainya. Daftar lengkap semua ini dapat dilihat di dokumentasi untuk collections.abc.


3
2017-12-07 15:50



hati-hatilah menggunakan isinstance

isinstance(True, bool)
True
>>> isinstance(True, int)
True

tapi ketikkan

type(True) == bool
True
>>> type(True) == int
False

2
2017-11-14 11:22