1.魔术方法 __new__

'''
触发时机:实例化类生成对象的时候触发(触发时机在__init__之前)
功能:控制对象的创建过程
参数:至少一个cls接受当前的类,其他根据情况决定
返回值:通常返回对象或None
'''

注意:python3.x 新式类 python2.x 旧式类, 新式类不需要每次都写一次object,默认继承控制创建的对象。

class MyClass2():abc = 1obj2 = MyClass2()class MyClass(object):def __new__(cls):print(cls)  # <class '__main__.MyClass'># 借助object父类方法里面__new__ 来为本类创建一个对象# return object.__new__(cls)  # 返回一个本类对象# return None # 返回一个空对象return obj2 # 返回的是一个其他类的对象pass# 实例化对象obj
obj = MyClass()
print(obj)
print(obj.abc)执行结果如下:

1.1.对比__new__和 __init__的触发时机

__new__ 魔术方法是用来创建对象的
__init__魔术方法是用来初始化对象的
得现有对象,才能够初始化,没有对象初始化谁?
__new__ 的触发时机要快于__init__
__new__ __init__ 这两个方法的参数要一一匹配.

1.2.__new__ __init__这两个方法中的参数一一匹配

#(1)一个参数的类型
class Boat():def __new__(cls, name):print(1)return object.__new__(cls)def __init__(self, name):self.name = nameobj = Boat("大锤")
#(2)无限个参数
class Boat():def __new__(cls, *args, **kwargs):print(1)return object.__new__(cls)def __init__(self, *args, **kwargs):strvar = ""for i in args:strvar += i + " "print("小船的贡献者有:", strvar)print("小船的名字是{}".format(kwargs['name']))
obj = Boat("王俊文", "舒畅", "境泽年", "五金玲", name="Anglelababy")代码运行结果:

 注意:如果通过__new__返回的是其他类的对象,不会触发到自己的__init__ ,因为__init__初始化的是本类的对象。

    例:

class Boat():def __new__(cls, *args, **kwargs):return obj2 #返回的是MyClass()类中产生的对象def __init__(self):print("init调用了")obj = Boat()
print(obj.abc)代码运行结果为:

即是1.中我们定义的对象obj2 = MyClass2()中的属性,即是输出123,实际 def __init__()

这初始化函数没有运行,因为我们定义__new__返回的是MyClass2()类中产生的对象obj2,

obj2调用类中的公有属性最后输出结果为123

2.单态模式

无论实例化多少次,都有且只有一个对象.最终目的:为了节省内存空间.应用的场景是只调用相关的成员属性或方法,而不用动态添加成员属性方法的环境中。

2.1 基本用法

class Singleton():__obj = Nonedef __new__(cls):if cls.__obj is None:# 借助父类创建对象obj = object.__new__(cls)# 把这个对象赋值给类中成员属性__objcls.__obj = objreturn cls.__obj# 第一次创建时,因为cls.__obj 是None 所以创建一个对象
obj = Singleton()
print(obj)
# 第二次实例化时,因为cls.__obj 不是None ,直接返回上一次创建的那个对象
obj = Singleton()
print(obj)
# 第三次实例化时,同第二次
obj = Singleton()
print(obj)
obj = Singleton()
print(obj)
obj = Singleton()
print(obj).代码运行结果:

总结:可以借助创建一个私有属性,默认为None,那么第一次实例化会利用__new__创建一个Singleton类的

对象,通过cls.__obj = obj赋值把已创建的对象赋值给cls.__obj。假使是第二次实例化的时,我们发现

Singleton有这属性(或者这个属性不是空),那么我们就不用用__new__创建对象这样就能达到单态,即是

只有一个内存空间的办法,从而节省内存空间。

对上面的代码就行稍作改造:

lass Singleton():__obj = Nonedef __new__(cls,*args,**kwargs):if cls.__obj is None:cls.__obj = object.__new__(cls)return cls.__obj def __init__(self,name):self.name = nameobj1 = Singleton("王波")obj2 = Singleton("方真强")
print(obj1.name)
print(obj2.name)运行结果:

总结:创建的obj1、obj2对象同时指向了Singleton类,所以最后访问的是obj2的name属性。详解:

第一次是创建对象,并且通过init初始化对象,为该对象赋值成员属性name
     self.name = 王波

第二次是直接返回上一个对象,然后对他进行初始化,为该对象赋值成员属性name
     self.name = 方真强

两个不同的变量名指向的是同一个对象
     而此时该对象的成员属性name 这个值是方真强
     print(obj1.name)
     print(obj2.name)
     打印的都是方真强

3.__del__析构方法 __init__构造方法

触发时机:当对象被内存回收的时候自动触发[1.页面执行完毕回收所有变量 2.所有对象被del的时候]
功能:对象使用完毕后资源回收
参数:一个self接受对象
返回值:无

 3.1页面执行完毕回收所有变量:

class LangDog():def __init__(self,name):self.name = namedef eat(self,something):print("可爱的小狼{},喜欢吃{}".format(self.name,something))def __del__(self):print("__del__方法被触发")# (1) 1.页面执行完毕回收所有变量
obj = LangDog("詹姆斯·狗蛋")
obj.eat("屎")
print("<===>")

代码执行结果:

3.2 触发__del__机制中的第二点所有对象被del删除时候。

      所有对象被del的时候只有当所有指向该对象的变量都删除的时候,才算真正的删除该对象。

class LangDog():def __init__(self,name):self.name = namedef eat(self,something):print("可爱的小狼{},喜欢吃{}".format(self.name,something))def __del__(self):print("__del__方法被触发")# (1) 1.页面执行完毕回收所有变量
obj = LangDog("詹姆斯·狗蛋")
obj.eat("屎")
print("<===>")
# (2) 2.所有对象被del的时候
'''
只有当所有指向该对象的变量都删除的时候,才算真正的删除该对象
'''obj2 = obj
print("<==start===>")
del obj
del obj2
print("<==end===>")代码执行结果:

3.3 用类来模仿文件的写操作

一个普通文件的写入和读写操作如下:

# fp = open("ceshi111.txt",mode="w",encoding="utf-8")
# fp.write("sfdsdf")
# fp.close()# fp = open("ceshi111.txt",mode="r",encoding="utf-8")
# res = fp.read()
# fp.close()
# print(res)

总结:打开 -写入文件内容/读出文件内容-关闭文件

用面对对象的写法如下:

import os
class MyFile():# 判断是否创建MyFile该对象def __new__(cls,filename):if os.path.exists(filename):return object.__new__(cls)        return print("该文件不存在")# 产生文件对象def __init__(self,filename):self.fp = open(filename,mode="r",encoding="utf-8")# 读取文件def readfile(self):res = self.fp.read()return resdef __del__(self):print(0)# 自动触发__del__ ,帮助我们关闭文件
        self.fp.close()obj = MyFile("ceshi222.txt")
res = obj.readfile()
print(res)
代码输出:
即是文件的内容结果,需要传入MyFile类中一个参数即是文件("ceshi222.txt")

4.魔术方法

4.1__call__的魔术方法

触发时机:把对象当作函数调用的时候自动触发
功能: 模拟函数化操作
参数: 参数不固定,至少一个self参数
返回值: 看需求

基本语法:

class MyClass():def __call__(self):print("__call__方法被调用")return "done"obj = MyClass()
res = obj()#也就是函数在调用的时候触发__call__
print(res)代码执行结果如下:

4.2利用__call__这个特性写一个洗衣服的流程

如下:

    class Wash():   # 使用call方法,进行统一的调用def __call__(self, something):self.something = somethingprint("以下是洗{}的过程:".format(something))self.step1()self.step2()self.step3()def step1(self):print("第一步放水,把{}扔盆里".format(self.something))def step2(self):print("第二部导入洗衣液,金纺,蓝月亮,吊牌洗衣皂扔盆里搓")def step3(self):print("第三部晒一下,穿上")obj = Wash() #用户使用Wash类的时候,只需要调用Wash就可以了,不用利用创建的obj对象依次调用洗衣的步骤,简单方便obj("裤衩")

代码运行结果:

 # 如果用户不采用内部写一个__call__方法的话,会一直用对象去调用,导致非常的不方便。

 # 一边写一边骂街
 # obj.step1()
 # obj.step2()
 # obj.step3()

4.2.1 利用__call__的触发机制(把对象当函数调用的时候会自动触发),写一个模拟内置int方法实现myint

代码如下:

import mathclass MyInt():def stoi(self, n, sign=1):res = n.lstrip("0")if res == "":return 0num = eval(res) * signreturn numdef __call__(self, n):# 判断的是布尔类型if isinstance(n, bool):if n == True:return 1else:return 0# 判断的是整型elif isinstance(n, int):return n# 判断的是浮点型elif isinstance(n, float):if n < 0:return math.ceil(n)else:return math.floor(n)# 判断的是字符串elif isinstance(n, str):if (n[0] == "-" or n[0] == "+") and n[1:].isdecimal():if n[0] == "+":sign = 1elif n[0] == "-":sign = -1return self.stoi(n[1:], sign)elif n.isdecimal():# 如果能够走到这个条件,一定没有带任何正负号return self.stoi(n)else:return "对不起,老弟,这个算不了"else:print("对不起,老哥,这个算不了")

myint = MyInt()
res = myint("12233")
print(res)
print(myint("+000000000333333"))
print(myint("00000000000"))
print(myint("-0000000000078"))
print(myint(-7.6))
print(myint(8.8))
print(myint(False))
print(myint(True))
print(myint(4))
print(myint([1, 3, 4]))

代码执行结果:

可以说我们这个功能比内置的int还牛逼!

4.3 __str__方法

触发时机: 使用print(对象)或者str(对象)的时候触发
功能: 查看对象
参数: 一个self接受当前对象
返回值: 必须返回字符串类型

class Cat():gift = "抓老鼠"def __init__(self,name):self.name = namedef cat_info(self):strvar = "这个对象的名字{},这个对象的天赋:{}".format(self.name,self.gift)return strvardef __str__(self):return self.cat_info()tom = Cat("汤姆")
# (1) 打印对象触发__str__方法
# print(tom)
# (2) str强转对象时候触发__str__方法
res = str(tom)
print(res)

代码执行结果如下:

4.4 __repr__ 方法

触发时机: 使用repr(对象)的时候触发
功能:     查看对象,与魔术方法__str__相似
参数:     一个self接受当前对象
返回值:   必须返回字符串类型

 例:

class Mouse():gift = "打洞"def __init__(self,name):self.name = namedef mouse_info(self):strvar = "该对象的名字{},它的天赋是{},龙胜龙,凤生凤,老鼠的儿子会打洞".format(self.name,self.gift)return strvardef __repr__(self):return self.mouse_info()# 在系统的底层加了如下一句话:如果存在__repr__ 这个方法,就把它赋值给__str__# __str__ = __repr__
jerry = Mouse("杰瑞")
# res = repr(jerry)
# print(res)
print(jerry)代码运行结果:

 4.5 __bool__ 方法

触发时机:使用bool(对象)的时候自动触发
功能:强转对象
参数:一个self接受当前对象
返回值:必须是布尔类型
类似的还有如下等等(了解):
__complex__(self)      被complex强转对象时调用
__int__(self)          被int强转对象时调用
__float__(self)        被float强转对象时调用

代码:

class MyBool():def __bool__(self):print(122)# return Truereturn False运行结果如下:

4.6__add__ 方法

触发时机:使用对象进行运算相加的时候自动触发
功能:对象运算
参数:二个对象参数
返回值:运算后的值

类似的还有如下等等(了解):

__sub__(self, other) 定义减法的行为:-
__mul__(self, other) 定义乘法的行为:
__truediv__(self, other) 定义真除法的行为:/

例:

class MyAdd():def __init__(self, num):self.num = num# 对象+数值,并且对象在+加号的左边,自动触发__add__方法def __add__(self, other):# self.num  => 3 + 56 => 59return self.num + otherdef __radd__(self, other):# self 接受b, other 接受33return self.num + other * 10# 1.当对象在加号的左侧  自动触发add 方法
a = MyAdd(3)
res = a + 56
print(res)# 2.当对象在加号的右侧  自动触发radd 方法
b = MyAdd(5)
res = 33 + b
print(res)# 3 a+b =?
res = a + b
print(res)
'''
a在加号的左侧,触发add魔术方法
self.num + other => 3 + bb在加号的右侧,触发radd魔术方法
res = 3+b
self.num + other * 10 => 5 + 3 *10 => 35代码运行结果如下:

*4.7 __len__方法

触发时机:使用len(对象)的时候自动触发
功能:用于检测对象中或者类中某个内容的个数
参数:一个self接受当前对象
返回值:必须返回整型
用len(对象)方式,算出该对象所归属的类有多少自定义成员

class MyLen():pty1 = 1pty2 = 2__pty3 = 3def func1():passdef func2():passdef __func3():passdef __func4():passdef __func5():passdef __len__(self):# print(MyLen.__dict__) 打印结果如下分析dic = MyLen.__dict__lst = [i for i in dic if not(i.startswith("__") and i.endswith("__"))]num = len(lst)return numobj = MyLen()
res = len(obj)
print(res)
"""分析
{'__module__': '__main__',
'pty1': 1, 'pty2': 2,'_MyLen__pty3': 3, 'func1': <function MyLen.func1 at 0x7f10880d9620>, 'func2': <function MyLen.func2 at 0x7f10880d96a8>,'_MyLen__func3': <function MyLen.__func3 at 0x7f10880d9730>, '__len__': <function MyLen.__len__ at 0x7f10880d97b8>,'__dict__': <attribute '__dict__' of 'MyLen' objects>, '__weakref__': <attribute '__weakref__' of 'MyLen' objects>, '__doc__': None}
"""运行代码结果如下:

转载于:https://www.cnblogs.com/longerandergou/p/10908371.html

Day20 python__new__、单态模式、析构方法、常用魔术方法、__str__、__repr__、__bool__ 、__len__...相关推荐

  1. invoke 魔术_PHP常用魔术方法(__invoke魔术方法)

    PHP5.3魔术方法 __invoke 这个魔幻方法被调用的时机是: 当一个对象当做函数调用的时候, 如果对象定义了__invoke魔幻方法则这个函数会被调用, class Callme { publ ...

  2. python基础之类的属性方法、魔术方法普通方法

    类的定义.调用方法.引用属性 类的属性和方法 类的属性 类属性的访问 类属性可以直接访问,无需实例化 类属性也可以通过实例来访问 实际上,所有的实例是共享类属性的 类属性的修改 修改了类属性后,对应的 ...

  3. Python学习笔记1:数据模型和特殊方法(魔术方法)

    首先不要脸的放上个人网站:www.comingnext.cn 1.关于数据模型 在Python的官方文档中是这样说的: 对象是Python对数据的抽象.Python程序中所有数据都由对象或对象之间的关 ...

  4. python怎么降维_【Python算法】常用降维方法-常用降维方法解读

    常用降维方法-常用降维方法解读 1. 引言 机器学习领域中所谓的降维就是指采用某种映射方法,将原高维空间中的数据点映射到低维度的空间中.降维的本质是学习一个映射函数 f : x->y,其中x是原 ...

  5. python怎么降维_【Python算法】常用降维方法-常用降维方法的目的

    常用降维方法-常用降维方法的目的 正所谓每一个结果的出现都是一系列的原因导致的,当构建机器学习模型时候,有时候数据特征异常复杂,这就需要经常用到数据降维技术,下面主要介绍一些降维的主要原理. 1. 降 ...

  6. python 类继承方法_python类的继承、多继承及其常用魔术方法

    继承 一个类可以派生出一个子类,这个子类可以使用父类的属性及方法,也可以在父类的基础上添加自己的独特属性或方法.属性和方法的继承的顺序是先从自己开始,找不到再去找父类,父类没有再找父类的父类,其尽头就 ...

  7. python魔术方法是什么_Python常用魔术方法

    什么是魔术方法? 在Python中,所有以双下划线__包起来的方法,统称为Magic Method(魔术方法),它是一种的特殊方法,普通方法需要调用,而魔术方法不需要调用就可以自动执行. 魔术方法在类 ...

  8. php魔术方法 效率,PHP常用魔术方法的性能探究

    性能往往是衡量代码很重要的一个标准.我们日常编码中经常会用到一些魔术方法,这些PHP提供的魔术方法是否会影响我们程序的性能呢?是否需要减少魔术方法 的使用呢?本文将通过测试对比来了解魔术方法对性能的影 ...

  9. python描述符魔术方法_学习笔记-Python基础9-面向对象编程OOP-类的成员描述符(property)、类的常用内置属性、类的常用魔术方法、类和对象的三种方法...

    一.类的成员描述符(property) 类的成员描述符是为了在类中,对类的成员属性进行相关操作而创建的一种方式,大部分属于数据清洗 属性有三种操作:get获取属性值.set修改或添加属性.delete ...

最新文章

  1. ecshop的Mysql操作类
  2. web service 基础学习
  3. 什么是事务(transaction)?它有什么好处
  4. native react 集成微信登录_react native 接入微信登陆(Android)
  5. 新款苹果电脑_苹果发布新款MacBookAir 搭载M1芯片7999起
  6. 写给程序员的美术创作指南
  7. 需要vmwareinstalldisk上的文件vmnet_手机上一键就能进行PDF与其他文件的相互转换,果然厉害到不行...
  8. fusionjs 学习二 核心概念
  9. Python入门--列表元素的增加操作,append(),extend(),insert(),切片
  10. java rome,ROME - RSS聚合类库 - 组件类库 - JAVA开源项目 - 开源吧
  11. 当出现“在当前位置发现已经存在为RESUME.XLW的文件。您希望将该文件替换掉吗?” 解决方案...
  12. Coursera | Introduction to Data Analytics(IBM) | Final Assignment
  13. 51c语言单片机io口控制实验报告,单片机实验报告二 单片机IO口实验
  14. 找回 Windows 11 丢失的扫雷游戏【新春快乐】
  15. 软件构造第一次实验感想总结
  16. spss多元线性回归散点图_SPSS多元线性回归.pdf
  17. 计算机专业的宣传,计算机专业招生宣传口号
  18. 填坑Go-“can‘t load package“
  19. 【Windows编程】Windows Socket API介绍
  20. Python使用turtle绘图中设置小乌龟(画笔)旋转的角度turtle.setheading()

热门文章

  1. jQuery-动画效果
  2. JavaScript 动画效果
  3. 别样肉客宣布进军全新品类 在华推出两款别样猪肉肉酱产品
  4. 什么是Remoting
  5. U3D控制摄像头第一人称WASD移动旋转
  6. PostCSS received undefined instead of CSS string
  7. 【ROS】实操_话题发布
  8. 颜色帮你缓解职场压力 给你的心情换个色
  9. win10计算机本地连接属性在哪里,Win10系统怎么打开本地连接属性
  10. pb11.5破解补丁