python 类的内置函数2
必须明确创建对象的过程: 先创建空对象,执行初始化将属性存储到对象的名称空间中!
所以在__call__函数中必须完成这两步操作,同时将初始化完成的对象返回给调用者 一旦覆盖了__call__函数,就必须自己来完成上述的几个步骤 class MyMate(type):
def __call__(self, *args, **kwargs):
# 创建空对象
# 调用init
# 返回初始化后的对象
obj = object.__new__(self)
self.__init__(obj,*args,**kwargs)
return obj
class Foo(metaclass=MyMate):
def __init__(self):
print("初始化对象")
f = Foo()
print(f)
通过元类来控制一个类实例化对象的过程
只需覆盖__call__函数我们就能完成对实例化过程的控制 #需求:
#2.要求实例化时传参必须为关键字形式,否则抛出异常TypeError: must use keyword argument
#3.key作为用户自定义类产生对象的属性,且所有属性变成大写
class Mymetaclass(type):
def __call__(self, *args, **kwargs):
if args:
raise TypeError('must use keyword argument for key function')
obj = object.__new__(self) #创建对象,self为类Chinese for k,v in kwargs.items():
obj.__dict__[k.upper()]=v
return obj
class Chinese(metaclass=Mymetaclass):
country='China'
tag='Legend of the Dragon' #龙的传人
def walk(self):
print('%s is walking' %self.name)
p=Chinese(name='egon',age=18,sex='male')
print(p.__dict__)
补充:
产生类Teacher的过程就是在调用Mymeta,而Mymeta也是type类的一个对象,那么Mymeta之所以可以调用,一定是实现了__call__方法,但是我们就算自己写该方法,类也可以被创建,这是因为type中已经有默认的__call__的实现了
该方法中同样需要做至少三件事 #伪代码
class type:
def __call__(self, *args, **kwargs): #self=<class '__main__.Mymeta'>
obj=self.__new__(self,*args,**kwargs) # 产生Mymeta的一个对象
self.__init__(obj,*args,**kwargs)
return obj
5.元类实现单例
什么是单例
单例是指的是单个实例,指一个类只能有一个实例对象 为什么要用单例
当一个类的实例中的数据不会变化时使用单例,数据是不变的 例如开发一个音乐播放器程序,音乐播放器可以封装为一个对象,那你考虑一下,当你切歌的时候,是重新创建一个播放器,还是使用已有的播放器? 因为播放器中的数据和业务逻辑都是相同的没有必要创建新的,所以最好使用单例模式,以节省资源 当两个对象的数据完全相同时 则没有必要占用两份资源 #使用classmethod 实现单例
class Player():
def __init__(self):
print("创建播放器了")
__play = None
@classmethod
def get_player(cls):
if not cls.__play:
cls.__play = Player()
return cls.__play p1 = Player.get_player();
p1 = Player.get_player();
p1 = Player.get_player();
p1 = Player.get_player();
该方法无法避免使用者直接调用类来实例化,这样就不是单例了 使用元类实现单例模式 #在类定义时 自动执行init 在init中创建实例 call中直接返回已有实例
class MyMeta(type):
__instance = None def __init__(self,name,bases,dic):
if not self.__instance:
self.__instance = object.__new__(self)
self.__init__(self.__instance) super().__init__(name, bases, dic) def __call__(cls):
return cls.__instance class Player(metaclass=MyMeta):
def __init__(self):
print("创建播放器了")
Player()
Player()
# 仅执行一次创建播放器
6.元类之属性查找
当一个类既有父类又有元类时属性的查找顺序是什么样的? 回顾一下,在没有元类时属性的查找是基于MRO列表的顺序,这个点还是相同的,那我们为某个类增加元类后,元类中的属性,什么时候会被使用到呢?来看一个例子 class Mymeta(type): #只有继承了type类才能称之为一个元类,否则就是一个普通的自定义类
n=444
def __new__(cls, *args, **kwargs):
pass
class Bar(object):
n = 333
def __new__(cls, *args, **kwargs):
pass
class Foo(Bar):
n=222
def __new__(cls, *args, **kwargs):
pass
class Teacher(Foo,metaclass=Mymeta):
n=111
def __new__(cls, *args, **kwargs):
pass
school='Tsinghua'
print(Teacher.__new__)
print(Teacher.n)
测试结果表明:属性查找的顺序依然是遵循MRO列表顺序,当顶级类object中不存在时会查找元类,元类没有时查找元类的父类也就是type类, image-20181204102324732

7.令人迷惑的__new__函数与__init__函数
class M(type):
def __init__(self,clsname,bases,namespace):
print("init")
def __call__(self, *args, **kwargs):
pass
pass
class A(metaclass=M):
n = 1
pass
print(A.__name__)
print(A.__bases__)
print(A.__dict__)
"""输出
init
A
(<class 'object'>,)
{'__module__': '__main__', 'n': 1, '__dict__': <attribute '__dict__' of 'A' objects>, '__weakref__': <attribute '__weakref__' of 'A' objects>, '__doc__': None}
"""
我们已经知道__init__可以控制类的创建过程,但是现在我们看到的是,init中没有任何代码但是类的三个基本信息已经都有了,这说明类的创建其实已经完成了 class M(type):
def __new__(cls, *args, **kwargs):
print("new")
#return type.__new__(cls,*args,**kwargs)
def __init__(self,clsname,bases,namespace):
print("init")
class A(metaclass=M):
n = 1
print(A.__name__)
print(A.__bases__)
print(A.__dict__)
"""输出
new
Traceback (most recent call last):
File "/Users/jerry/PycharmProjects/元类属性查找.py", line 43, in <module>
print(A.__name__)
AttributeError: 'NoneType' object has no attribute '__name__'"""
执行了__new__函数但是并没有执行__init__,因为__new__函数是真正用于创建类的方法,只有创建类成功了才会执行init函数,new必须要有返回值且返回值类型为__type__时才会执行__init__函数, 将__new__中被注释的代码打开 一切正常! 再一次印证了第四节中的伪代码 总结:元类中__new__是用于创建类对象的 __init__是用于初始化类的其他信息的
python 类的内置函数2的更多相关文章
- python学习交流 - 内置函数使用方法和应用举例
内置函数 python提供了68个内置函数,在使用过程中用户不再需要定义函数来实现内置函数支持的功能.更重要的是内置函数的算法是经过python作者优化的,并且部分是使用c语言实现,通常来说使用内置函 ...
- python常用的内置函数哈哈
python常用的内置函数集合做一个归类用的时候可以查找 abs 返回数字x的绝对值或者x的摸 all (iterable)对于可迭代的对象iterable中所有元素x都有bool(x)为true,就 ...
- python常用的内置函数
python常用的内置函数集合做一个归类用的时候可以查找- abs 返回数字x的绝对值或者x的摸 - all (iterable)对于可迭代的对象iterable中所有元素x都有bool(x)为tru ...
- python 常见的内置函数
内置函数 接下来,我们就一起来看看python里的内置函数.截止到python版本3.6.2,现在python一共为我们提供了68个内置函数.它们就是python提供给你直接可以拿来使用的所有函数.这 ...
- python之路——内置函数和匿名函数
阅读目录 楔子 内置函数 匿名函数 本章小结 楔子 在讲新知识之前,我们先来复习复习函数的基础知识. 问:函数怎么调用? 函数名() 如果你们这么说...那你们就对了!好了记住这个事儿别给忘记了,咱们 ...
- 十六. Python基础(16)--内置函数-2
十六. Python基础(16)--内置函数-2 1 ● 内置函数format() Convert a value to a "formatted" representation. ...
- 十五. Python基础(15)--内置函数-1
十五. Python基础(15)--内置函数-1 1 ● eval(), exec(), compile() 执行字符串数据类型的python代码 检测#import os 'import' in c ...
- Python的常用内置函数介绍
Python的常用内置函数介绍 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.取绝对值(abs) #!/usr/bin/env python #_*_coding:utf-8_ ...
- Python进阶(五)----内置函数Ⅱ 和 闭包
Python进阶(五)----内置函数Ⅱ 和 闭包 一丶内置函数Ⅱ ####内置函数#### 特别重要,反复练习 ###print() 打印输入 #sep 设定分隔符 # end 默认是换行可以打印到 ...
随机推荐
- vivo产能问题
生产手机,第一天量产1台,接下来2天(即第二.三天)每天量产2件,接下来3天(即第四.五.六天)每天量产3件 ... ... 以此类推,请编程计算出第n天总共可以量产的手机数量. public int ...
- Active MQ未授权访问
ActiveMQ是一款流行的开源消息服务器.默认情况下,ActiveMQ服务是没有配置安全参数.恶意人员可以利用默认配置弱点发动远程命令执行攻击,获取服务器权限,从而导致数据泄露. 一.未授权访问 默 ...
- Linux passwd 提权
利用条件,passwd 可写 ls -al /etc/passwd 利用方式: 生成密钥 openssl passwd -1 -salt test 123456 写入passwd echo 'tes ...
- Spring boot Sample 012之spring-boot-web-upload
一.环境 1.1.Idea 2020.1 1.2.JDK 1.8 二.目的 spring boot 整合web实现文件上传下载 三.步骤 3.1.点击File -> New Project -& ...
- ActiveMQ 笔记(一)概述与安装
个人博客网:https://wushaopei.github.io/ (你想要这里多有) 一.消息中间件的产生背景 1.前言:考虑消息中间件的使用场景? 在何种场景下需要使用消息中间件 为什么要 ...
- Java实现 LeetCode 822 翻转卡片游戏(暴力)
822. 翻转卡片游戏 在桌子上有 N 张卡片,每张卡片的正面和背面都写着一个正数(正面与背面上的数有可能不一样). 我们可以先翻转任意张卡片,然后选择其中一张卡片. 如果选中的那张卡片背面的数字 X ...
- Java实现 LeetCode 672 灯泡开关 Ⅱ(数学思路问题)
672. 灯泡开关 Ⅱ 现有一个房间,墙上挂有 n 只已经打开的灯泡和 4 个按钮.在进行了 m 次未知操作后,你需要返回这 n 只灯泡可能有多少种不同的状态. 假设这 n 只灯泡被编号为 [1, 2 ...
- Java实现 LeetCode 64 最小路径和
64. 最小路径和 给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小. 说明:每次只能向下或者向右移动一步. 示例: 输入: [ [1,3,1], ...
- Java实现第八届蓝桥杯纸牌三角形
纸牌三角形 题目描述 A,2,3,4,5,6,7,8,9 共9张纸牌排成一个正三角形(A按1计算).要求每个边的和相等. 下图就是一种排法(如有对齐问题,参看p1.png). A 9 6 4 8 3 ...
- 为什么阿里巴巴Java开发手册中强制要求接口返回值不允许使用枚举?
在阅读<阿里巴巴Java开发手册>时,发现有一条关于二方库依赖中接口返回值不允许使用枚举类型的规约,具体内容如下: 在谈论为什么之前先来科普下什么是二方库,二方库也称作二方包,一般指公司内 ...