洗礼灵魂,修炼python(42)--巩固篇—type内置函数与类的千丝万缕关系
type函数的隐藏属性
相信大家都知道内置函数type是用来查看对象的数据类型的。例:

那比如我对int类查看类型呢?

有朋友会说,int是内置类啊,用自定义的应该不会这样,我们自定义一个类呢?

还是【type】,那如果使用python2,不继承object类呢?

哎,果然,不继承object类就没事了,但它是还是一个类对象(classobj)啊,换句话说它还是一个对象啊,那我们用isinstance看看test是不是对象呢?

返回True,果然是啊,那再看看基类object呢?

还是这个【type】,还是逃不了
那这个【type】又是什么呢?

结果是它自身
那么这【type】到底是什么?type类,有吗?不急着说,先说说type另一个功能,这个功能却没多少人知道,在 Stack overflow有一位大神e-satis说,它还能创建类,是不是想说,卧槽,这么吊?确实可以的
先看看type函数到底有哪些用法:

其中有个用法:
type(类名, 父类的元组(针对继承的情况,可以为空),包含属性的字典(名称和值))
那么这个怎么用呢?
试试看:

试试用class关键词定义一样否呢?

好像一样的,对吧?不急着下结论,传入属性看看:

哎呀,一样的,继承一个类呢?

确实一样的。要注意的是,使用type时第二个参数是继承对象,因为参数必须是个元组,当只有一个元素时,得加入逗号才能表示是一个元组(这个在前面元组篇说过的)
那么这是什么原理呢?
首先,我们在之前就掌握的知识点——类也是对象,你可以动态的创建类,可以给类进行重新赋值,复制,添加属性,添加方法等操作,当使用class关键字创建类时,在python内部是怎么操作的?这就是通过元类来实现的。
元类(metaclass)是什么
元类就是用来创建类的“工具”,当创建类目的就是为了创建类的实例对象对吧?需要实例化类对象才能进行我们想要的操作,实现我们希望实现的功能对吧?创建好类后,能够通过类创建出实例化的对象,而类本身也是一个实例对象,不过它是元类的实例对象。而我们已经知道类也是对象。那么,你有没有想过,类这个对象又是被谁创建的呢?我们用class关键词创建时,python是怎么识别并创建类对象的呢?
从表层上说,这是python的解释器自动创建的这个类,从深层上说,这是元类“搞的鬼”,元类就是用来创建这些类(对象)的,元类就是类的类,你可以这样理解
元类和type有什么关系?
在刚才的例子里:

type实际上是一个元类(metaclass)。type就是Python在背后用来创建所有类的元类。可以类比一下,int是用来创建整数对象的类,list是用来创建列表对象的类,str是用来创建字符串的类等等的,而这些int类,list类,dict类等等全部都是对象,全部都从一个类创建而来——type:
比如博文的最开始a=3这个例子:

所以,元类就是创建类这种对象的工具或者东西,type就是Python的内建元类
当然你可以创建自己的元类(如果你想的话)
自定义元类
1.__metaclass__属性
要想创建自己的元类,就得使用__metaclass__属性

当使用class Test()创建类时,此时Test还不存在于内存中,当使用了__meaclass__就会用元类来创建类Test,这时python会在类的定义中寻找__metaclass__属性,如果有这个属性,就会创建。如果没有就会用内建的type来创建这个类对象。
当然,如果使用继承也是一样的,比如:

使用继承的话,python会判断Test是否有__metaclass__属性,如果有就通过__metaclass__创建,如果没有又从继承的父类Parent类里找有没有__metaclass__,如果有就通过__metaclass__创建,如果还是没有则查找当前主程序模块(__main__,是的,就是 【if __name__ == '__main__'】里的__main__)查找是否有__metaclass__属性,同样的,有就通过其创建,没有就用内置的type创建这个类对象
这里我个人的理解是:在创建类时,python会判断是否有__metaclass__属性,如果有则按照__metaclass__的特性来创建,如果没有则直接用type来创建一个普通的类,比如一个list,int,str类。
那么我们可以在__metaclass__属性里放置什么呢?可以放置一个type来创建类对象的工具(也可以是type的子类)

2.元类定义的目的
元类的主要目的就是为了当创建类时能够自动地改变类。通常的用途在于可以在web框架或者API做这样的事情,只要是希望可以创建符合当前上下文的类
自己去体会django里的用法,你会发现,格式是创建的类的格式,但是效果和每行代码的意思完全和常识的类无关了。
元类本身而言,它们其实是很简单的:
- 拦截类的创建(到底用__metaclass__还是用type来创建)
- 修改类(__meta__=type……)
- 返回修改之后的类
3.使用元类的原因
“元类就是深度的魔法,99%的用户应该根本不必为此操心。如果你想搞清楚究竟是否需要用到元类,那么你就不需要它。那些实际用到元类的人都非常清楚地知道他们需要做什么,而且根本不需要解释为什么要用元类。” —— Python界的领袖 Tim Peters
换句话就是,当我们在想搞清楚什么时候需要用到元类时,那么你就不需要用它了,要用它都是非常清楚它能干什么的。知道这个就行,如果没有接触到深层次的开发,不用管它。并且,元类是很复杂的。对于非常简单的类,没必要通过使用元类来对类做修改
洗礼灵魂,修炼python(42)--巩固篇—type内置函数与类的千丝万缕关系的更多相关文章
- Python学习(八) —— 内置函数和匿名函数
一.递归函数 定义:在一个函数里调用这个函数本身 递归的最大深度:997 def func(n): print(n) n += 1 func(n) func(1) 测试递归最大深度 import sy ...
- python基础12_匿名_内置函数
一个二分查找的示例: # 二分查找 示例 data = [1, 3, 6, 7, 9, 12, 14, 16, 17, 18, 20, 21, 22, 23, 30, 32, 33, 35, 36, ...
- 【python】dir(__builtins__)查看python中所用BIF(内置函数)
dir(__builtins__)查看python中所用BIF(内置函数)
- 查看python内部模块命令,内置函数,查看python已经安装的模块命令
查看python内部模块命令,内置函数,查看python已经安装的模块命令 可以用dir(modules) 或者用 pip list或者用 help('modules') 或者用 python -m ...
- Python基础(十一)--内置函数
内置函数 数学类 abs():绝对值 round():四舍五入 >>> round(1.3747,1) 1.4 sum():求和 >>> sum({1:'dj',2 ...
- Python开发【第五篇】内置函数
abs() 函数返回数字的绝对值 __author__ = "Tang" a = -30 all() 函数用于判断给定的可迭代参数iterable中的所有元素是否都为True,如果 ...
- python 基础篇 15 内置函数和匿名函数
------------------------>>>>>>>>>>>>>>>内置函数<<< ...
- python学习之路-4 内置函数和装饰器
本篇涉及内容 内置函数 装饰器 内置函数 callable() 判断对象是否可以被调用,返回一个布尔值 1 2 3 4 5 6 7 8 9 10 11 num = 10 print(callabl ...
- python全栈开发-Day13 内置函数
一.内置函数 注意:内置函数id()可以返回一个对象的身份,返回值为整数. 这个整数通常对应与该对象在内存中的位置,但这与python的具体实现有关,不应该作为对身份的定义,即不够精准,最精准的还是以 ...
随机推荐
- [视频]K8飞刀 S2-020 exploit getshell 动画教程
[视频]K8飞刀 S2-020 exploit getshell 动画教程 链接:https://pan.baidu.com/s/1G5x7Dcu6pzHz6ZfSCDDmKA 提取码:05kw
- 纯JavaScript实现俄罗斯方块(详细注释,ES6)
借鉴了慕课网的课程<基于websocket的火拼俄罗斯(单机版)>虽然改动比较多,但是还是核心部分没有改,加了一些不怎么好听的声音,和看起来并不好看的界面. CSS部分基本是瞎写的,因为对 ...
- 第三章 服务治理:Spring Cloud Eureka
Spring Cloud Eureka是Spring Cloud Netflix 微服务套件中的一部分,它基于Netflix Eureka做了二次封装,主要负责完成微服务架构中的服务治理功能.Spri ...
- mysql 开发进阶篇系列 35 工具篇 mysqldump(数据导出工具)
一.概述 mysqldump客户端工具是用来备份数据库或在不同数据库之间进行数据迁移.备份内容包含创建表或装载表的sql语句.mysqldump目前是mysql中最常用的备份工具. 三种方式来调用my ...
- [git与github]__git与github简单了解
前言 关于版本控制,版本控制是一种记录一个或若干文件内容变化,以便将来查阅特定版本修订情况的系统. 我们通过版本控制系统可以解决的问题:可以非常方便的查看我们的源码文件的历代更新版本.或将我们的项目源 ...
- 树莓派+tomcat+mysql安装及配置
0x00 系统:ubuntu-mate-16.04.2-desktop-armhf-raspberry-pi 该版本中apt源在国内访问速度不算慢,可以不换,但软件包不完整,建议添加阿里云源 deb ...
- Java 面试基础总结(一)
1.九种基本数据类型的大小以及它们的封装类 java提供的九种基本数据类型:boolean.byte(1).char(2).short(2).int(4).long(8).float(4).doubl ...
- eosio.cdt:EOS智能合约工具集
目前EOS已经迎来了1.5.x时代,很多内容都有了较大的改变.其中智能合约的工作流程发生了改变,EOSIO为智能合约提供了独立且功能完整的工具集eosio.cdt.该工具集基于WASM平台,可解耦于e ...
- go sync.once用法
欢迎关注go语言微信公众号 每日go语言 golang_everyday sync.once可以控制函数只能被调用一次.不能多次重复调用.示例代码: package main import ( &qu ...
- (转)eclipse上传项目到码云
把Eclipse项目上传到码云的步骤: 1.登录码云:新建项目 2.输入项目名: 3.空项目创建成功如下图: 4.右键点击Eclipse的项目,选择“Team”—————->“Share Pro ...