一、概述

  我们知道类可以实例化出对象,那么类本身又是怎么产生的呢?我们就来追溯一下类的起源。

二、类的起源

  2.1 创建一个类 

class Foo(object):

    def __init__(self, name):
self.name = name f = Foo('bigberg') # 我们创建一个 Foo的类
# 实例化一个 对象 f

  在python中有个说法:一切皆为对象。如果按照一切事物都是对象的理论:obj对象是通过执行Foo类的构造方法创建,那么Foo类对象应该也是通过执行某个类的 构造方法 创建。

print(type(f))
print(type(Foo)) # 输出 <class '__main__.Foo'>
<class 'type'> # 对象 f 由类 Foo创建
# Foo类由 type 创建

  所以,f对象是Foo类的一个实例Foo类对象是 type 类的一个实例,即:Foo类对象 是通过type类的构造方法创建。

  2.2 type 创建类

  type创建类的格式,类名 = type('类名',(父类,),{'方法名':方法的内存地址})  

def func(self):      # 定义一个函数
print('hello,world') Foo = type('Foo', (object,), {'talk': func}) # type创建类,(object,) 为元组 f = Foo()
f.talk()
print(type(f))
print(type(Foo)) # 输出
hello,world
<class '__main__.Foo'>
<class 'type'

  可以看到type 确实可以创建一个类,并且可以实例化对象

  那么我们如何传参呢?就需要我们自己写构造函数这些了: 

def func(self):
print('hello,%s' % self.name) def __init__(self, name): # 构造函数
self.name = name Foo = type('Foo', (object,), {'talk': func, '__init__': __init__}) f = Foo('Bigberg') # 传参
f.talk() # 输出
hello,Bigberg

  So: 类 是由 type 类 实例化产生的

  

三、__new__方法

  __new__() 是在新式类中新出现的方法,它作用在构造方法建造实例之前,可以这么理解,在 Python 中存在于类里面的构造方法 __init__() 负责将类的实例化,而在 __init__() 启动之前,__new__() 决定是否要使用该 __init__() 方法,因为__new__() 可以调用其他类的构造方法或者直接返回别的对象来作为本类的实例。  

class Foo(object):

    def __init__(self, name):
self.name = name
print("in the Foo __init__") def __new__(cls, *args, **kwargs): # 第一个参数cls,是当前正在实例化的类,这里是object
print("Foo __new__", cls, *args, ** kwargs)
return object.__new__(cls) # 继承父类的__new__方法 f = Foo('bigberg')
print(f.name) # 输出 Foo __new__ <class '__main__.Foo'> bigberg # new方法先于init方法执行
in the Foo __init__
bigberg

__new__() 方法的特性:

  • __new__() 方法是在类准备将自身实例化时调用。
  • __new__() 方法始终都是类的静态方法,即使没有被加上静态方法装饰器。

注意:

  事实上如果(新式)类中没有重写__new__()方法,即在定义新式类时没有重新定义__new__()时,Python默认是调用该类的直接父类的__new__()方法来构造该类的实例,如果该类的父类也没有重写__new__(),那么将一直按此规矩追溯至object的__new__()方法,因为object是所有新式类的基类。

  如果我们不返回__new__()方法,无法进行实例化对象  

class Foo(object):

    def __init__(self, name):
self.name = name
print("in the Foo __init__") def __new__(cls, *args, **kwargs): object
print("Foo __new__", cls, *args, ** kwargs)
# return object.__new__(cls)
f = Foo('bigberg')
print(f.name)
# 输出
File "G:/python/untitled/study6/类的起源.py", line 39, in <module>
print(f.name)
AttributeError: 'NoneType' object has no attribute 'name'

  

四、__metaclass__方法 

  4.1 metaclass作用

  metaclass这个属性叫做元类,它是用来表示这个类是由谁来帮他实例化创建的,说白了,就是相当于自己定制一个类,就这么一个意思。

 class MyType(type):

     def __init__(self, *args, **kwargs):

         print("Mytype __init__", *args, **kwargs)

     def __call__(self, *args, **kwargs):
print("Mytype __call__", *args, **kwargs)
obj = self.__new__(self)
print("obj ", obj, *args, **kwargs)
print(self)
self.__init__(obj, *args, **kwargs)
return obj def __new__(cls, *args, **kwargs):
print("Mytype __new__", *args, **kwargs)
return type.__new__(cls, *args, **kwargs) print('here...') class Foo(object, metaclass=MyType): def __init__(self, name):
self.name = name print("Foo __init__") def __new__(cls, *args, **kwargs):
print("Foo __new__", cls, *args, **kwargs)
return object.__new__(cls) f = Foo("Bigberg")
print("f", f)
print("fname", f.name) #输出 here...
Mytype __new__ Foo (<class 'object'>,) {'__qualname__': 'Foo', '__init__': <function Foo.__init__ at 0x000002A1968FE8C8>, '__module__': '__main__', '__new__': <function Foo.__new__ at 0x000002A1968FE950>}
Mytype __init__ Foo (<class 'object'>,) {'__qualname__': 'Foo', '__init__': <function Foo.__init__ at 0x000002A1968FE8C8>, '__module__': '__main__', '__new__': <function Foo.__new__ at 0x000002A1968FE950>}
Mytype __call__ Bigberg
Foo __new__ <class '__main__.Foo'>
obj <__main__.Foo object at 0x000002A196905898> Bigberg
<class '__main__.Foo'>
Foo __init__
f <__main__.Foo object at 0x000002A196905898>
fname Bigberg

创建过程如下:

  4.2 执行顺序

  类的生成 调用 顺序依次是 __new__ --> __init__ --> __call__

类的起源与metaclass的更多相关文章

  1. 面向对象【day08】:类的起源与metaclass(二)

    本节内容 1.概述 2.类的起源 3.__new__方法 4.__metaclass__方法 一.概述 前面我们学习了大篇幅的关于类,通过类创建对象,那我们想知道这个类到底是怎么产生的呢?它的一切来源 ...

  2. python元类:type和metaclass

    python元类:type和metaclass python中一切皆对象,所以类本身也是对象.类有创建对象的能力,那谁来创建类的呢?答案是type. 1.用tpye函数创建一个类 class A(ob ...

  3. 类的特殊成员方法,类的起源type, metaclass

    1.__doc__表示类的描述信息 2. __module__ 和  __class__  __module__ 表示当前操作的对象在那个模块 __class__     表示当前操作的对象的类是什么 ...

  4. python基础-类的起源

    Python中一切事物都是对象. class Foo(object): def __init__(self,name): self.name = name f = Foo("alex&quo ...

  5. python 描述符 上下文管理协议 类装饰器 property metaclass

    1.描述符 #!/usr/bin/python env # coding=utf-8 # 数据描述符__get__ __set__ __delete__ ''' 描述符总结 描述符是可以实现大部分py ...

  6. 探索未知种族之osg类生物---起源

    任何程序都是有生命的,是生命就需要呼吸.例如普通的windows程序,当运行完main()函数后,就需要进入消息循环,来监听用户的各种操作,以便做出及时的回应.这样的每次循环就像生命的每次呼吸,来维持 ...

  7. **类的起源--type

    通过type类的实例化,创建新的类. #!/usr/bin/env python # Version = 3.5.2 def func(self): print('Hello,{}'.format(s ...

  8. Python类(八)-类的起源

    首先用type()看一下类和实例化对象的类型 # -*- coding:utf-8 -*- __author__ = "MuT6 Sch01aR" class Person(obj ...

  9. python笔记-9(subprocess模块、面向对象、socket入门)

    一.subprocess 模块 1.了解os.system()与os.popen的区别及不足 1.1 os.system()可以执行系统指令,将结果直接输出到屏幕,同时可以将指令是否执行成功的状态赋值 ...

随机推荐

  1. 阿里IPO法律咨询费达1580万美元 为Facebook六倍

    据路透社报道,阿里巴巴集团周五在 IPO (首次公开招股)更新文件中披露,将向美国盛信律师事务所(Simpson Thacher)以及其他为 IPO 提供咨询服务的律师事务所支付 1580 万美元的法 ...

  2. 4个数的和为0 51nod 1267

    给出N个整数,你来判断一下是否能够选出4个数,他们的和为0,可以则输出"Yes",否则输出"No". Input 第1行,1个数N,N为数组的长度(4 < ...

  3. CSS3:不可思议的border属性

    在CSS中,其border属性有很多的规则.对于一些事物,例如三角形或者其它的图像,我们仍然使用图片代替.但是现在就不需要了,我们可以用CSS形成一些基本图形,我分享了一些关于这方面的技巧. 1.正三 ...

  4. js正则表达式匹配斜杠 网址 url等

    项目中有个需求,需要从url中截取ID.需要在前台用js匹配截取,所以就百度一下,发现都没有说清楚,所以这里就总结下. 正则表达式如下: var epId=0; //工厂企业ID var urlInd ...

  5. 未能加载文件或程序集“log4net, Version=1.2.10.0, Culture=neutral, PublicKeyToken=1b44e1d426115821”或它的某一个依赖项。系统找不到指定的文件。

    在网上找了很久,很多个地方让修改配置文件,也有重装log4net的. 如文章:使用Common.Logging与log4net的组件版本兼容问题 我检查下发现项目中的package包中的Log4net ...

  6. Java中的网络编程-3

    用户数据协议(UDP)是网络信息传输的另外一种形式, 基于UDP的通信不同于基于TCP的通信, 基于UDP的信息传递更快, 但是不提供可靠的保证. 使用UDP传输数据时, 用户无法知道数据能否正确地到 ...

  7. 使用selenium遍历frame中的表单信息 ;

    遍历frame中的表单 : package webDriverPro; import java.util.List; import java.util.regex.Matcher; import ja ...

  8. django里的http协议

    一个普通的user Begin########## ['__class__', '__delattr__', '__dict__', '__doc__', '__eq__', '__format__' ...

  9. Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction

    我在update数据库的时候出现的死锁 数据库表死锁 Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackExcept ...

  10. 使用JMeter录制Web应用测试脚本

    环境 操作系统:Windows 7 工具:JMeter.Badboy 1. 使用代理录制Web性能测试脚本 使用代理录制脚本来创建测试计划无疑是一个简便的方法,代理所要完成的工作就是录制发往服务器的请 ...