类的起源与metaclass
一、概述
我们知道类可以实例化出对象,那么类本身又是怎么产生的呢?我们就来追溯一下类的起源。
二、类的起源
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的更多相关文章
- 面向对象【day08】:类的起源与metaclass(二)
本节内容 1.概述 2.类的起源 3.__new__方法 4.__metaclass__方法 一.概述 前面我们学习了大篇幅的关于类,通过类创建对象,那我们想知道这个类到底是怎么产生的呢?它的一切来源 ...
- python元类:type和metaclass
python元类:type和metaclass python中一切皆对象,所以类本身也是对象.类有创建对象的能力,那谁来创建类的呢?答案是type. 1.用tpye函数创建一个类 class A(ob ...
- 类的特殊成员方法,类的起源type, metaclass
1.__doc__表示类的描述信息 2. __module__ 和 __class__ __module__ 表示当前操作的对象在那个模块 __class__ 表示当前操作的对象的类是什么 ...
- python基础-类的起源
Python中一切事物都是对象. class Foo(object): def __init__(self,name): self.name = name f = Foo("alex&quo ...
- python 描述符 上下文管理协议 类装饰器 property metaclass
1.描述符 #!/usr/bin/python env # coding=utf-8 # 数据描述符__get__ __set__ __delete__ ''' 描述符总结 描述符是可以实现大部分py ...
- 探索未知种族之osg类生物---起源
任何程序都是有生命的,是生命就需要呼吸.例如普通的windows程序,当运行完main()函数后,就需要进入消息循环,来监听用户的各种操作,以便做出及时的回应.这样的每次循环就像生命的每次呼吸,来维持 ...
- **类的起源--type
通过type类的实例化,创建新的类. #!/usr/bin/env python # Version = 3.5.2 def func(self): print('Hello,{}'.format(s ...
- Python类(八)-类的起源
首先用type()看一下类和实例化对象的类型 # -*- coding:utf-8 -*- __author__ = "MuT6 Sch01aR" class Person(obj ...
- python笔记-9(subprocess模块、面向对象、socket入门)
一.subprocess 模块 1.了解os.system()与os.popen的区别及不足 1.1 os.system()可以执行系统指令,将结果直接输出到屏幕,同时可以将指令是否执行成功的状态赋值 ...
随机推荐
- 如何通俗理解贝叶斯推断与beta分布?
有一枚硬币(不知道它是否公平),假如抛了三次,三次都是“花”: 能够说明它两面都是“花”吗? 1 贝叶斯推断 按照传统的算法,抛了三次得到三次“花”,那么“花”的概率应该是: 但是抛三次实在太少了,完 ...
- JavaScript 高级之面向对象
1. 对象属性及方法 创建对象的方式 <script> //创建对象的方式一 var obj = {}; //创建对象的方式一 var obj = new Object(); </s ...
- 带你玩转JavaScript中的隐式强制类型转换
正题开始前我想先抛出一个问题,==和===有什么区别?可能一般人会想,不就是后者除了比较值相等之外还会比较类型是否相等嘛,有什么好问的,谁不知道?!但是这样说还不够准确,两者的真正区别其实是==在比较 ...
- PSP Daily软件Alpha版本——基于spec评论
题目要求:每个小组评论其他小组Alpha发布作品的软件功能说明书.要求和提交在[https://edu.cnblogs.com/campus/nenu/SWE2017FALL/homework/122 ...
- Beta阶段第二次网络会议
Beta阶段第二次网络会议 第一次会议问题解决情况 画面问题已经解决,游戏提示信息已加入完成 不同情况下背景已加入完成,但细节部分仍需要进行调整 科技树添加完成,权限修改完成,还存在部分细节调整 AI ...
- 第二次程序+PSP0级
第二周,老师接着上次的程序有对四则运算的程序,做出来一些要求,这次要求可以控制乘除法,有无括号,控制输出方式,控制结果有无负数,有无余数. 我在对原先的程序分析了一下,发现我原先的程序可扩展性特别差, ...
- HDU 5159 Card
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5159 题解: 考虑没一个数的贡献,一个数一次都不出现的次数是(x-1)^b,而总的排列次数是x^b, ...
- JavaScript设计模式学习之路——继承
早在学习java的时候,就已经接触了继承,在java中因为有extends关键字,因此继承就比较简单.但是在JavaScript中,只能通过灵活的办法实现类的继承. 下面是我昨天在学习过程中,了解到的 ...
- 【Leetcode】725. Split Linked List in Parts
Given a (singly) linked list with head node root, write a function to split the linked list into k c ...
- PAT 甲级 1020 Tree Traversals
https://pintia.cn/problem-sets/994805342720868352/problems/994805485033603072 Suppose that all the k ...