一文带你了解Python中的type,isinstance和issubclass

作者:勇敢努力拼搏 时间:2023-05-10 22:54:20 

type

type方法有两种重载形式:

  • type(o: object)

  • type(name: str, bases:Tuple[type, ...], dict:Mapping[str: Any], **kwds)

使用第一种重载形式的时候,传入一个【object】类型,返回一个【type】对象,通常与object.__class__方法的返回值相同。

使用第二种重载形式的时候,也会得到一个【type】对象,本质上来说这是一种动态类,参数含义如下:

  • name:字符型,指定动态类的类名,也是该动态类的__name__属性;

  • bases:type类型元祖,指定动态类继承的父类,也是该动态类的__bases__属性;

  • dict:字典类型,指定动态类的属性和方法定义,经过一定的包装后成为动态类的__dict__属性;

示例

重载形式1

class A(object):
    pass

a = A()
print(type(a), a.__class__, type(A))
-----------------------------
<class '__main__.A'> <class '__main__.A'> <class 'type'>

重载形式2

class OldClass(object):
    a = 1

    def __init__(self) -> None:
        self.name = "OldClass"

    def get_name(self):
        return self.name


my_dynamic_cls = type('DynamicClass', (OldClass,),
                      dict(name='dynamic', a=2, b=3, c=4))

new_obj = my_dynamic_cls()
print(my_dynamic_cls.__dict__)
print(new_obj.__dict__, type(new_obj))
-----------------------------
{'name': 'dynamic', 'a': 2, 'b': 3, 'c': 4, '__module__': '__main__', '__doc__': None}
{'name': 'OldClass'} <class '__main__.DynamicClass'>

在上面的示例中我们使用type成功创造了一个动态类并添加了几个类属性,由于指定了【OldClass】作为父类,所以动态生成的类也具有【OldClass】的全部特性。

动态生成一个类的时候不光可以指定类属性,还可以绑定类方法,示例如下:

class OldClass(object):
    a = 1

    def __init__(self) -> None:
        self.name = "OldClass"

    def get_name(self):
        return self.name

def print_msg(msg: str) -> None:
    print(msg)

my_dynamic_cls = type('DynamicClass ', (OldClass,),
                      dict(name='dynamic', a=2, b=3, c=4, method=print_msg))

new_obj = my_dynamic_cls()
my_dynamic_cls.method("使用动态绑定的方法!!")
print(my_dynamic_cls.__dict__)
-----------------------------
使用动态绑定的方法!!
{'name': 'dynamic', 'a': 2, 'b': 3, 'c': 4, 'method': <function print_msg at 0x00000188189F73A0>, '__module__': '__main__', '__doc__': None}

isinstance

Return True if the object argument is an instance of the classinfo argument, or of a (direct, indirect, or virtual) subclass thereof. If object is not an object of the given type, the function always returns False. If classinfo is a tuple of type objects (or recursively, other such tuples) or a union of multiple types, return True if object is an instance of any of the types. If classinfo is not a type or tuple of types and such tuples, a TypeError exception is raised. TypeError may not be raised for an invalid type if an earlier check succeeds.

&mdash;&mdash;PythonDoc

isinstance方法用来检查给定的对象是否是给定类型的实例或者是给定类型的任意子类的实例,通常使用该方法进行对象类型校验。

示例

class AMetaClass(type):

    def __new__(cls, *args, **kwargs):
        return type.__new__(cls, *args, **kwargs)


class BMetaClass(AMetaClass):
    pass


class AClass(object, metaclass=BMetaClass):

    def __init__(self, name: str) -> None:
        self.name = name


class BClass(AClass):

    def __init__(self, name: str) -> None:
        super().__init__(name)

obj_a = AClass('a')
obj_b = BClass('b')
-----------------------------
print(isinstance(obj_b, AClass)) -> True
print(isinstance(obj_b, BClass)) -> True
print(isinstance(obj_b, AMetaClass)) -> False
print(isinstance(obj_b, BMetaClass)) -> False
print(isinstance(obj_b, type)) -> False
print(isinstance(BClass, AMetaClass)) -> True
print(isinstance(BClass, BMetaClass)) -> True
print(isinstance(BClass, type)) -> True

总结一下,isinstance方法检查的范围就是参数的模板层按照继承关系进行检索。

issubclass

issubclass(class: type, classinfo: Union[type, ...])方法用来判断指定的两个类型之间的从属关系,如果【class】是【classinfo】的子类返回真(True),否则返回假(False)。

有几点注意事项这里说一下:

  • issubclass(cls, cls)返回是真;

  • 【classinfo】参数可以是一个type元祖,只要有一个条件为真,则表达式结果为真;

  • 【class】和【classinfo】必须是元类或者类,不能是一个对象,总结一下就是参数要么是【type】的子类要么是【type】的实例;

示例

class AMetaClass(type):

    def __new__(cls, *args, **kwargs):
        return type.__new__(cls, *args, **kwargs)


class BMetaClass(AMetaClass):
    pass


class AClass(object, metaclass=BMetaClass):

    def __init__(self, name: str) -> None:
        self.name = name


class BClass(AClass):

    def __init__(self, name: str) -> None:
        super().__init__(name)

obj_a = AClass('a')
obj_b = BClass('b')
-----------------------------

issubclass(AMetaClass, type) -> True
issubclass(BMetaClass, type) -> True
issubclass(BMetaClass, AMetaClass) -> True
issubclass(AClass, AMetaClass) -> False
issubclass(AClass, BMetaClass) -> False
issubclass(BClass, AClass) -> True
issubclass(AClass, obj_a) -> TypeError: arg 2 must be a class
issubclass(obj_a, AClass) -> TypeError: arg 1 must be a class

从程序结果可以看到传入元类和类返回永远是假,并且不能直接传入对象。

综合示例

为了更好的让大家明白这三者之间的区别和联系,我画了一张图

一文带你了解Python中的type,isinstance和issubclass

这是初始状态,定义了三个对象,三个类和三个元类,它们之间的关系如上图所示;

class M1(type):

    def __new__(cls, *args, **kwargs):
        return type.__new__(cls, *args, **kwargs)


class M2(M1):
    pass


class M3(type):

    def __new__(cls, *args, **kwargs):
        return type.__new__(cls, *args, **kwargs)


class C1(metaclass=M3):
    pass


class C2(C1):
    pass


class C3(metaclass=M2):
    pass


o1 = C1()
o2 = C2()
o3 = C3()

isinstance

针对对象

以【O2】为例,它的检索范围如下图红线所示:

一文带你了解Python中的type,isinstance和issubclass

针对类

以【C3】为例,它的检索范围如下图红线所示:

一文带你了解Python中的type,isinstance和issubclass

issubclass

针对类

以【C2】为例,返回真值的范围如下:

一文带你了解Python中的type,isinstance和issubclass

针对元类

以【M2】为例,返回真值的范围如下:

一文带你了解Python中的type,isinstance和issubclass

  • 参数必须是同一个类型,元类或者类;

  • 按照继承路径进行判断。

来源:https://juejin.cn/post/7193577879345561657

标签:Python,type,isinstance,issubclass
0
投稿

猜你喜欢

  • Python xmltodict模块安装及代码实例

    2023-05-27 09:25:43
  • js实现的星星评分功能函数

    2024-06-16 10:28:07
  • JavaScript字符串对象(string)基本用法示例

    2024-04-17 10:00:31
  • 用XMLHTTP很好的一个例子

    2008-04-25 10:25:00
  • 通用分页存储过程

    2007-11-28 13:08:00
  • Pandas透视表(pivot_table)详解

    2022-03-26 00:21:29
  • 关于TypeScript模块导入的那些事

    2024-06-07 15:57:46
  • PyCharm 安装与使用配置教程(windows,mac通用)

    2023-08-21 01:15:39
  • python DataFrame中stack()方法、unstack()方法和pivot()方法浅析

    2023-12-13 17:38:55
  • phpMyAdmin安装配置方法

    2009-09-09 20:15:00
  • Python+LyScript实现自定义反汇编

    2021-02-07 11:57:47
  • Pycharm配置opencv与numpy的实现

    2021-09-19 08:20:55
  • 浅谈numpy中np.array()与np.asarray的区别以及.tolist

    2022-06-06 12:32:10
  • opencv 实现特定颜色线条提取与定位操作

    2023-09-07 01:24:26
  • python opencv实现图像边缘检测

    2022-08-05 08:40:34
  • 分类与类型的问题

    2008-09-12 13:10:00
  • MYSQL本地安装以及出现的问题解决

    2024-01-25 00:00:36
  • JS截取与分割字符串常用技巧总结

    2024-02-26 13:48:45
  • 基于golang channel实现的轻量级异步任务分发器示例代码

    2024-05-08 10:13:09
  • java连接Oracle数据库的工具类

    2024-01-23 14:43:29
  • asp之家 网络编程 m.aspxhome.com