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内置函数与类的千丝万缕关系的更多相关文章

  1. Python学习(八) —— 内置函数和匿名函数

    一.递归函数 定义:在一个函数里调用这个函数本身 递归的最大深度:997 def func(n): print(n) n += 1 func(n) func(1) 测试递归最大深度 import sy ...

  2. python基础12_匿名_内置函数

    一个二分查找的示例: # 二分查找 示例 data = [1, 3, 6, 7, 9, 12, 14, 16, 17, 18, 20, 21, 22, 23, 30, 32, 33, 35, 36, ...

  3. 【python】dir(__builtins__)查看python中所用BIF(内置函数)

    dir(__builtins__)查看python中所用BIF(内置函数)

  4. 查看python内部模块命令,内置函数,查看python已经安装的模块命令

    查看python内部模块命令,内置函数,查看python已经安装的模块命令 可以用dir(modules) 或者用 pip list或者用 help('modules') 或者用 python -m  ...

  5. Python基础(十一)--内置函数

    内置函数 数学类 abs():绝对值 round():四舍五入 >>> round(1.3747,1) 1.4 sum():求和 >>> sum({1:'dj',2 ...

  6. Python开发【第五篇】内置函数

    abs() 函数返回数字的绝对值 __author__ = "Tang" a = -30 all() 函数用于判断给定的可迭代参数iterable中的所有元素是否都为True,如果 ...

  7. python 基础篇 15 内置函数和匿名函数

    ------------------------>>>>>>>>>>>>>>>内置函数<<< ...

  8. python学习之路-4 内置函数和装饰器

    本篇涉及内容 内置函数 装饰器 内置函数 callable()   判断对象是否可以被调用,返回一个布尔值 1 2 3 4 5 6 7 8 9 10 11 num = 10 print(callabl ...

  9. python全栈开发-Day13 内置函数

    一.内置函数 注意:内置函数id()可以返回一个对象的身份,返回值为整数. 这个整数通常对应与该对象在内存中的位置,但这与python的具体实现有关,不应该作为对身份的定义,即不够精准,最精准的还是以 ...

随机推荐

  1. [视频]K8飞刀 S2-020 exploit getshell 动画教程

    [视频]K8飞刀 S2-020 exploit getshell 动画教程 链接:https://pan.baidu.com/s/1G5x7Dcu6pzHz6ZfSCDDmKA 提取码:05kw

  2. 纯JavaScript实现俄罗斯方块(详细注释,ES6)

    借鉴了慕课网的课程<基于websocket的火拼俄罗斯(单机版)>虽然改动比较多,但是还是核心部分没有改,加了一些不怎么好听的声音,和看起来并不好看的界面. CSS部分基本是瞎写的,因为对 ...

  3. 第三章 服务治理:Spring Cloud Eureka

    Spring Cloud Eureka是Spring Cloud Netflix 微服务套件中的一部分,它基于Netflix Eureka做了二次封装,主要负责完成微服务架构中的服务治理功能.Spri ...

  4. mysql 开发进阶篇系列 35 工具篇 mysqldump(数据导出工具)

    一.概述 mysqldump客户端工具是用来备份数据库或在不同数据库之间进行数据迁移.备份内容包含创建表或装载表的sql语句.mysqldump目前是mysql中最常用的备份工具. 三种方式来调用my ...

  5. [git与github]__git与github简单了解

    前言 关于版本控制,版本控制是一种记录一个或若干文件内容变化,以便将来查阅特定版本修订情况的系统. 我们通过版本控制系统可以解决的问题:可以非常方便的查看我们的源码文件的历代更新版本.或将我们的项目源 ...

  6. 树莓派+tomcat+mysql安装及配置

    0x00 系统:ubuntu-mate-16.04.2-desktop-armhf-raspberry-pi 该版本中apt源在国内访问速度不算慢,可以不换,但软件包不完整,建议添加阿里云源 deb ...

  7. Java 面试基础总结(一)

    1.九种基本数据类型的大小以及它们的封装类 java提供的九种基本数据类型:boolean.byte(1).char(2).short(2).int(4).long(8).float(4).doubl ...

  8. eosio.cdt:EOS智能合约工具集

    目前EOS已经迎来了1.5.x时代,很多内容都有了较大的改变.其中智能合约的工作流程发生了改变,EOSIO为智能合约提供了独立且功能完整的工具集eosio.cdt.该工具集基于WASM平台,可解耦于e ...

  9. go sync.once用法

    欢迎关注go语言微信公众号 每日go语言 golang_everyday sync.once可以控制函数只能被调用一次.不能多次重复调用.示例代码: package main import ( &qu ...

  10. (转)eclipse上传项目到码云

    把Eclipse项目上传到码云的步骤: 1.登录码云:新建项目 2.输入项目名: 3.空项目创建成功如下图: 4.右键点击Eclipse的项目,选择“Team”—————->“Share Pro ...