【Python】type、isinstance、issubclass详解

news2024/11/24 11:31:52

type

type方法有两种重载形式:

  1. type(o: object)
  2. 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.

​ ——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)。

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

  1. issubclass(cls, cls)返回是真;
  2. 【classinfo】参数可以是一个type元祖,只要有一个条件为真,则表达式结果为真;
  3. 【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

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

综合示例

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

示例

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

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】为例,它的检索范围如下图红线所示:

instance针对对象

针对类

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

instance针对类

issubclass

针对类

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

issubclass针对类

针对元类

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

issubclass针对元类

总结

调用type方法

  1. 如果是对象,则会顺着实例化的逆方向寻找,也就是找到创建它的类;
  2. 如果是类,则会顺着继承逆方向寻找,直到找到它的元类。

调用isinstance方法

  1. 如果是对象,那么实例化它的类和该类的所有父类都返回真,也就是沿着继承路径上都是返回真,但
    不能是元类;
  2. 如果是类,那么就找其元类的继承路径,路径上所有的元类都返回真。

调用issubclass方法

  1. 参数必须是同一个类型,元类或者类;
  2. 按照继承路径进行判断。

往期回顾

  1. 【Python】python深拷贝和浅拷贝(二)
  2. 【Python】python深拷贝和浅拷贝(一)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/158117.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

解决使用element-plus时使用el-select-v2组件时,选中后无法移除focus的状态的方法。

我们可以使用element-ui-plus的el-select-v2的组件&#xff0c;实现复合搜索和下拉框的功能。 使用如下模块&#xff1a; <template><el-select-v2 v-model"value" filterable :options"options" placeholder"Please select"visibleCha…

爸妈记性变差怎么办?

记不住事的时候&#xff0c;我们总会自嘲“老了&#xff0c;脑子不好使了”。记忆力总是和年龄挂钩的&#xff0c;所以很多子女听到父母这样说&#xff0c;也不会放在心上。但有时&#xff0c;记性变差不一定因为年龄&#xff0c;还有可能是患病的前兆。当父母出现频繁忘事的情…

zerotier虚拟网络配置,局域网与外网如同局域网一样访问。

zerotier:可以搭建用于自己的虚拟网络&#xff0c;经过授权连接成功之后彼此都在同一网段&#xff0c;可以像在局域网一样互相访问。 1.创建zerotier账户 2.创建网络&#xff08;Create A Network&#xff09;并记住网络标识&#xff08;NETWORK ID&#xff09; 一、openwrt设…

中华财险进击数字化

本文来源 / 瞭望 中华联合财产保险股份有限公司&#xff08;下称中华财险&#xff09;&#xff0c;是一家 36 年的老牌国有保险公司&#xff0c;全国营业网点超过 2900 个。近年来&#xff0c;中华财险在业务高速发展的同时&#xff0c;从难啃的硬骨头下手&#xff0c;重构核心…

Unity 之 Addressable可寻址系统 -- 可寻址系统面板介绍 -- 入门(二)

可寻址系统面板介绍 -- 入门&#xff08;二&#xff09;一&#xff0c;可寻址系统目录介绍1.2 创建分组1.2 目录介绍二&#xff0c;可寻址系统设置介绍2.1 Profile - 配置文件2.2 Catalog - 目录2.3 Content Update - 内容更新2.4 Downloads - 下载2.5 Build - 构建2.6 Build a…

【数据结构】5.6 树和森林

文章目录5.6.1 树的存储结构&#xff08;不是二叉树&#xff09;双亲表示法孩子表示法结构定义双亲孩子法孩子兄弟法5.6.2 二叉树的转换树与二叉树的转换将树转换成二叉树将二叉树转换成树森林与二叉树的转换森林转换成二叉树二叉树转换成森林5.6.3 树和森林的遍历树的遍历森林…

Nginx简介

一、什么是Nginx?Nginx是一个高性能的HTTP和反向代理Web服务器&#xff0c;同时也提供IMAP/POP3/SMTP服务。Nginx是一款轻量级的Web服务器/反向代理服务器及电子邮件&#xff08;IMAP/POP3/SMTP&#xff09;代理服务器。Nginx的特点是&#xff1a;占有内存少&#xff0c;并发能…

JJWT实现令牌Token

登录实现方式 Session 详情&#xff1a; https://www.cnblogs.com/andy-zhou/p/5360107.html 会话的概念 会话就好比打电话&#xff0c;一次通话可以理解为一次会话。我们登录一个网站&#xff0c;在一个网站上不同的页面浏览&#xff0c;最后退出这个网站&#xff0c;也是…

【Java AWT 图形界面编程】Container 容器 ② ( Frame 窗口示例 | Panel 示例 | 窗口中文乱码处理 )

文章目录一、Frame 窗口示例二、Panel 示例三、窗口中文乱码处理一、Frame 窗口示例 首先 , 创建 Frame 实例对象 , 该对象就是 操作系统中应用软件的 窗口 ; // 1. 创建窗口 Frame frame new Frame("AWT 图形界面编程");Frame 是 Window 的子类 , public class F…

前端号外—2022年最受欢迎居然是它,Node.js危已

导读 | 2022年是艰难的一年&#xff0c;不仅有互联网的寒冬、还有新冠疫情的洗礼。但是似乎这一切都阻挡不了JavaScript的内卷&#xff0c;一年不长不短的时间中&#xff0c;JavaScript从创新、性能、功能等多维度深度进化&#xff0c;给前端带来了诸多惊喜。本文基于github上流…

仓库管理系统demo搭建指南

1、简介 1.1、案例简介 本文将介绍&#xff0c;如何搭建云进销存-仓库管理。 1.2、应用场景 云进销存-仓库管理应用分仓管理并提供灵活的库存计算方式及库存预警。 2、设置方法 2.1、表单搭建 1&#xff09;新建表单【商品管理】&#xff0c;字段设置如下&#xff1a; …

TensorFlow笔记之神经网络完成多分类任务

文章目录前言一、数据集调用二、Tensorflow1.x1.单隐藏层2.模型保存与调用三、Tensorflow2.x1.全连接层类2.keras建模总结前言 对TensorFlow笔记之单神经元完成多分类任务进行修改&#xff0c;在tf1.x与tf2.x中使用神经网络完成手写体数字识别多分类任务。 一、数据集调用 数…

10、Javaweb_Cookkie会话Session修改IDEA代码模板

修改IDEA代码模板 选择Setting... 找到要修改的代码模板&#xff0c;点击ok修改即可 使用模板创建方法 ,点击文件包,右键New选择文件类型 点击ok即可 创建完成 会话技术 1. 会话&#xff1a;一次会话中包含多次请求和响应。 * 一次会话&#xff1a;浏览器第一次给服务器资…

JAVA开发(web常见安全漏洞以及修复建议)

web安全常见漏洞修复建议&#xff1a;SQL注入规避 代码层最佳防御sql漏洞方案&#xff1a;使用预编译sql语句查询和绑定变量。&#xff08;1&#xff09;使用预编译语句&#xff0c;使用PDO需要注意不要将变量直接拼接到PDO语句中。所有的查询语句都使用数据库提供的参数化查询…

92、【树与二叉树】leetcode ——222. 完全二叉树的节点个数:普通二叉树求法+完全二叉树性质求法(C++版本)

题目描述 原题链接&#xff1a;222. 完全二叉树的节点个数 解题思路 1、普通二叉树节点个数求法 &#xff08;1&#xff09;迭代&#xff1a;层序遍历BFS 遍历一层获取一层结点 /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode …

华为交换机、路由器设备批量配置端口方法步骤

华为交换机、路由器批量配置端口方法步骤 在现实工作中&#xff0c;如果要对多个端口做同样的配置&#xff0c;每个接口逐一进行相同的配置&#xff0c;很容易出错&#xff0c;而且造成大量重复工作。 配置端口组功能就可以解决这个问题啦。 你只需要将这些以太网接口加入同一…

HTML学习笔记(全)

HTML 文章目录HTML第一章——HTML 基础认识1. 1 基础补充1.1.1 网页组成1.1.2 代码如何转换成网页1.1.3 渲染引擎&#xff08;了解&#xff09;1.1.4 web 标准1.2 HTML 基础认知1. HTML的概念2. HTML页面固定结构3. **标签说明&#xff1a;**第二章——HTML基础语法2.1——注释…

国产linux操作系统——麒麟操作系统的来龙去脉

文章目录1、linux操作系统2、国产操作系统3、麒麟操作系统4、引用1、linux操作系统 目前市场主流的linux操作系统分类大致如此&#xff0c;国产操作系统的麒麟操作系统&#xff0c;底层比较杂&#xff0c;所以单独一类。 2、国产操作系统 排名日期截止到2022 这里提一下排名第…

科技云报道:从re:Invent 2022读懂亚马逊云科技的“生态棋局”

科技云报道原创。 懂棋的人都知道&#xff0c;下棋靠的是智力的角逐&#xff0c;也是气度的较量。 到了云计算发展的新时期&#xff0c;下棋的“人”已经变了&#xff0c;单靠一个人的智力解决不了N个用户的N种问题。 因此&#xff0c;近年来头部云厂商纷纷加大了对合作伙伴生…

centos7:jenkins+nodejs前端自动化部署

系统:centos7 nodejs版本&#xff1a;v16.18.1 npm版本&#xff1a;8.19.2 由于centos7最大只支持16.18.1版本&#xff0c;尽量让前端写代码时使用这个版本&#xff0c;linux系统如果要装高版本的node需要安装glibc库&#xff0c;很危险&#xff0c;尽量不要操作。 jenkin…