Bagaimana cara memeriksa apakah suatu variabel adalah kelas atau bukan?

236

Saya bertanya-tanya bagaimana cara memeriksa apakah variabel adalah kelas (bukan sebuah instance!) Atau tidak.

Saya sudah mencoba menggunakan fungsi isinstance(object, class_or_type_or_tuple)untuk melakukan ini, tetapi saya tidak tahu tipe apa yang akan dimiliki sebuah kelas.

Misalnya, dalam kode berikut

class Foo: pass  
isinstance(Foo, **???**) # i want to make this return True.

Saya mencoba mengganti " class" dengan ??? , tetapi saya menyadari bahwa itu classadalah kata kunci dalam python.

Astaga
sumber

Jawaban:

335

Lebih baik lagi: gunakan inspect.isclassfungsinya.

>>> import inspect
>>> class X(object):
...     pass
... 
>>> inspect.isclass(X)
True

>>> x = X()
>>> isinstance(x, X)
True
>>> y = 25
>>> isinstance(y, X)
False
Benjamin Peterson
sumber
7
Jika Anda juga ingin inspect.isclasskembali Truejika objek yang diperiksa adalah instance kelas , gunakaninspect.isclass(type(Myclass()))
michaelmeyer
8
Lebih baik dari apa :)?
Fisikawan Gila
8
@michaelmeyer type(whatever)selalu mengembalikan objek yang merupakan kelas, jadi pemeriksaan ini berlebihan. Jika tidak, tidak akan ada cara untuk instantiate whateverdan dengan demikian Anda tidak bisa melakukan pemeriksaan di tempat pertama.
a_guest
Tidak bekerja untuk saya. Menggunakan python3 dengan snakemake, type(snakemake.utils)kembali <class 'module'>dan inspect.isclass(snakemake.utils)kembali False.
tedtoal
3
Itu karena snakemake.utilmodul bukan kelas?
Benjamin Peterson
44

Inspect.isclass mungkin merupakan solusi terbaik, dan sangat mudah untuk melihat bagaimana itu sebenarnya diimplementasikan

def isclass(object):
    """Return true if the object is a class.

    Class objects provide these attributes:
        __doc__         documentation string
        __module__      name of module in which this class was defined"""
    return isinstance(object, (type, types.ClassType))
andrea_crotti
sumber
5
ingatimport types
nguyên
13
types.ClassTypetidak lagi diperlukan dalam Python 3 (dan dihapus).
kawing-chiu
ini tidak bekerja dengan kelas gaya baru sama sekali .... bahkan dalam python 2. jangan gunakan solusi ini sendirian
Erik Aronesty
Itu diambil dari modul inspeksi jadi saya ragu itu tidak berhasil. Sangat mudah untuk memeriksa dengan Python2.7 misalnyaIn [8]: class NewStyle(object): ...: pass ...: In [9]: isinstance(NewStyle, (type, types.ClassType)) Out[9]: True
andrea_crotti
Ini adalah implementasi Python 2, yang harus menangani kelas gaya lama dan gaya baru. Python 3 menyederhanakan ini menjadi isinstance(object, type). Perhatikan bahwa benda-benda seperti int, list, str, dll juga kelas, sehingga Anda tidak dapat menggunakan ini untuk membedakan antara kelas kustom didefinisikan dalam Python dan built-in kelas didefinisikan dalam kode C .
Martijn Pieters
39
>>> class X(object):
...     pass
... 
>>> type(X)
<type 'type'>
>>> isinstance(X,type)
True
S.Lott
sumber
1
Hm ... Jawaban yang bagus, tetapi ketika saya mengetik (Foo) di kelas Foo saya, ia mengatakan <type 'classobj'> alih-alih <type 'type'>. Saya berasumsi bahwa perbedaan berasal dari fakta bahwa X mewarisi dari objek, tetapi Foo tidak. Apakah ada perbedaan lain yang timbul dari ini? Terima kasih.
jeeyoungk
6
Ini tidak berfungsi untuk kelas gaya lama:, 'class Old:pass' 'isinstance(Old, type) == False'tapi inspect.isclass(Old) == True.
jfs
1
@ jeeyoungk: Anda tidak "menganggap perbedaan berasal dari ...", Anda sebenarnya membaca itu dalam kode. Subclass objek ("gaya baru") memiliki properti yang diinginkan, seperti yang Anda lihat di sini.
S.Lott
12
Inilah petunjuknya - karena ini berfungsi untuk kelas gaya baru, jangan gunakan kelas gaya lama. Tidak ada gunanya menggunakan kelas gaya lama.
S.Lott
isinstance (e, f) E adalah objek instantiated, F adalah objek kelas.
Dexter
24
isinstance(X, type)

Kembali Truejika Xkelas dan Falsejika tidak.

qnub
sumber
3
Saya mendapatkan False, bahkan jika X adalah kelas.
Mads Skjern
6
Ini hanya berfungsi untuk kelas gaya baru. Kelas gaya lama adalah tipe 'classobj'. Jadi, jika Anda menggunakan kelas gaya lama yang dapat Anda lakukan: import types isinstance (X, types.ClassType)
Charles L.
2
Ini tampaknya sama dengan S. Lott's answer, yaitu empat tahun lebih tua.
Ethan Furman
5

Pemeriksaan ini kompatibel dengan Python 2.x dan Python 3.x.

import six
isinstance(obj, six.class_types)

Ini pada dasarnya adalah fungsi pembungkus yang melakukan pemeriksaan yang sama seperti pada jawaban andrea_crotti.

Contoh:

>>> import datetime
>>> isinstance(datetime.date, six.class_types)
>>> True
>>> isinstance(datetime.date.min, six.class_types)
>>> False
Sergey
sumber
1

Cara paling sederhana adalah menggunakan inspect.isclasssebagaimana diposting dalam jawaban yang paling banyak dipilih.
detail implementasi dapat ditemukan di python2 inspect dan python3 inspect .
untuk kelas gaya baru: isinstance(object, type)
untuk kelas gaya lama: isinstance(object, types.ClassType)
em, untuk kelas gaya lama, yang digunakan types.ClassType, berikut adalah kode dari types.py :

class _C:
    def _m(self): pass
ClassType = type(_C)
lyu.l
sumber
1

Benjamin Peterson benar tentang penggunaan inspect.isclass()untuk pekerjaan ini. Tetapi perhatikan bahwa Anda dapat menguji apakah suatu Classobjek adalah spesifik Class, dan karenanya secara implisit a Class, menggunakan fungsi built-in issubclass . Tergantung pada kasus penggunaan Anda, ini bisa lebih pythonic.

from typing import Type, Any
def isclass(cl: Type[Any]):
    try:
        return issubclass(cl, cl)
    except TypeError:
        return False

Kemudian dapat digunakan seperti ini:

>>> class X():
...     pass
... 
>>> isclass(X)
True
>>> isclass(X())
False
masi
sumber
-2

Sudah ada beberapa solusi yang berfungsi di sini, tetapi ini satu lagi:

>>> import types
>>> class Dummy: pass
>>> type(Dummy) is types.ClassType
True
Ztyx
sumber
types.ClassTypetelah dihapus dengan Python 3
Beau Barker