提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 魔术方法
    • __init__构造方法
      • 概念
      • 基本语法
      • 带有多个参数的构造方法
    • __new__魔术方法
      • 概念
      • 基本语法
      • __new__的触发时机
      • __new__和 __init__参数一一对应
      • 关于__new__的注意点
    • __del__析构方法
      • 概念
      • 触发方式一
      • 触发方式二
      • 使用__del__模拟文件操作
    • __str__查看对象
      • 概念
      • 基本用法
    • __repr__查看对象,与魔术方法__str__相似
      • 概念
      • 基本用法
    • __call__模拟函数化操作
      • 概念
      • 基本用法
      • 模拟洗衣服的过程
      • 模拟内置的int方法,实现相应的操作
    • __bool__强转对象
      • 概念
      • 基本用法
    • __ add__、__radd__对象运算
      • 概念
      • 基本用法
    • __len__用于检测对象中或者类中成员的个数
      • 概念
      • 基本用法
  • 5个类的魔术属性
    • 类的魔术属性
    • 用法
  • 单态模式
    • 概念
    • 基本语法
    • 单态模式+构造方法

魔术方法

__init__构造方法

概念

1.触发时机:实例化对象,初始化的时候触发2.功能:为对象添加成员3.参数:参数不固定,至少一个self参数4.返回值:无

基本语法

# 1.基本语法
class MyClass():def __init__(self):print("初始化方法被触发")# 为当前对象self添加成员nameself.name = "Mike"
# 实例化对象
obj = MyClass() # 初始化方法被触发
print(obj.name) # Mike

带有多个参数的构造方法

# 2.带有多个参数的构造方法
class MyClass():def __init__(self,name):# self.成员名 = 参数self.name = name
# 实例化对象
obj = MyClass("Mike") # 在实例化对象的时候,给构造方法传递参数
print(obj.name) # Mike

类可以是一个,对象可以是多个,创造的对象彼此是独立的
注意:

1.一个类可以实例化多个不同的对象2.对象和对象之间彼此独立3.但都可以使用类中的公有成员
class Children():def __init__(self, name, skin):self.name = nameself.skin = skindef cry(self):print("小孩一出生就哇哇哇的哭")def drink(self):print("小孩一下生就要喝奶奶")def __la(self):print("小孩拉粑粑是私有的")def pub_info(self):print("该对象的名字是{},该对象的肤色是{}".format(self.name, self.skin))# 创建第一个小孩
afanda = Children("阿凡达", "蓝色的")
afanda.pub_info()
afanda.cry()# 创建第二个小孩
afanti = Children("阿凡提", "黄色的")
afanti.pub_info()
afanti.drink()# 创建第三个小孩
bao = Children("我滴宝强", "绿色的")
bao.pub_info()
# bao.__la() # 无法在类外调用私有的成员

__new__魔术方法

概念

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

基本语法

# (1)基本语法
class MyClass2():pty = 100
obj2= MyClass2()class MyClass():def __new__(cls):print(cls)# 类.方法(自定义类) => 借助父类object创建MyClass这个类的对象obj = object.__new__(cls)# (1) 借助父类object创建自己类的一个对象return obj# (2) 返回其他类的对象return obj2# (3) 不返回任何对象return Noneobj = MyClass()
print(obj)

__new__的触发时机

__new__ 触发时机快于构造方法__new__ 用来创建对象__init__ 用来初始化对象先创建对象,才能在初始化对象,所以__new__快于__init__
class Boat():def __new__(cls):print(2)return object.__new__(cls)def __init__(self):print(1)obj = Boat()# 因为__new__比__init__先执行,所以会先打印2后打印1.

__new__和 __init__参数一一对应

单个参数

class Boat():def __new__(cls,name):return object.__new__(cls)def __init__(self,name):self.name = nameobj = Boat("友谊的小船说裂开就裂开")
print(obj.name)

多个参数的情况

# 当__init__参数很多的时候,在__new__方法使用*args和**kwargs收集所有的参数!!class Boat():def __new__(cls,*args,**kwargs):return object.__new__(cls)def __init__(self,name,color,shangpai):self.name = nameself.color = colorself.shangpai = shangpaiobj = Boat("泰坦尼克号","屎绿色","京A66688")
print(obj.name)
print(obj.color)
print(obj.shangpai)

关于__new__的注意点

如果返回的对象不是自己本类中的对象,不会触发本类的构造方法

"""如果返回的对象不是自己本类中的对象,不会触发本类的构造方法"""
class MyClass():pty = 200
obj = MyClass()class Boat():def __new__(cls,*args,**kwargs):return object.__new__(cls) # 返回的是自己类的对象,会触发__init__方法# return obj # 返回的不是自己的对象,所以不会触发下面的__init__方法# return None # 没有返回对象,不可能触发__init__方法def __init__(self):print("构造方法被触发")
obj = Boat()
print(obj)

__del__析构方法

概念

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

触发方式一

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

class Long():food = '猪肉'def __init__(self,name):self.name = namedef __del__(self):print('析构方法被触发')print('=============')
obj = Long('青菜')
print('=============')
# 1.页面执行完毕回收所有变量
print(obj.name) # 当执行完这句话后,才算页面执行完毕,这个时候触发__del__析构方法
'''
输出:
=============
=============
青菜
析构方法被触发
'''

触发方式二

所有对象被del的时候被触发

class Long():food = '猪肉'def __init__(self,name):self.name = namedef __del__(self):print('析构方法被触发')obj1 = Long('青菜')
obj2 = obj1
print('=============')
# 删除对象
del obj1
print('=============')
'''
输出:
=============
=============
析构方法被触发
'''

代码解析

虽然obj1对象被删除了,但是obj2对象并没有被删除,obj1和obj2绑定的是同一个对象,这里涉及到一个引用计数的知识点,
所以不会触发析构方法
打印了“析构方法被触发”是因为整个页面执行完毕了,也会触发析构方法

使用__del__模拟文件操作

# 3.模拟文件操作
import os
class ReadFile():    def __new__(cls,filename):if os.path.exists(filename): # 判断文件路径是否存在return object.__new__(cls) # 如果文件存在,创建文件对象else:return print("该文件是不存在的") # 如果文件不存在,给予错误提示def __init__(self,filename):# 打开文件self.fp = open(filename,mode="r+",encoding="utf-8")def readcontent(self):# 读取文件return self.fp.read()def __del__(self):# 关闭文件self.fp.close()obj = ReadFile("1.txt")if obj is not None:res = obj.readcontent()print(res)
else:print("没有该类文件")# 当然,也可以用三元运算符来实现
""" 真值 if 条件表达式 else 假值 """
print(obj.readcontent()) if obj is not None else print("没有该类文件")

__str__查看对象

概念

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

基本用法

class Cat():gift = "小猫咪会卖萌求猫粮,小猫咪抓老鼠"def __init__(self,name):self.name = namedef __str__(self):return self.cat_info()def cat_info(self):return "小猫咪的名字是{},小猫咪{}元".format(self.name,5000)# __repr__ = __str__
tom = Cat("汤姆")
# 方法一. print(对象)
print(tom)
# 方法二. str(对象)
res = str(tom)
print(res)

__repr__查看对象,与魔术方法__str__相似

概念

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

基本用法

class Mouse():gift = "偷粮食"def __init__(self,name):self.name = namedef __repr__(self):return self.mouse_info()def mouse_info(self):return "名字是{},龙生龙,凤生凤,老鼠的儿子会打洞,还会{}".format(self.name,self.gift)# 系统在底层默认自动加了一句赋值操作,等于__repr__可以使用__str__触发方式__str__ = __repr__jerry = Mouse("杰瑞")
res = repr(jerry)
print(res)# 因为系统底层赋值的原因,在打印对象或者强转对象为字符串的时候,仍然可以触发;
print(jerry)
res = str(jerry)
print(res)

__call__模拟函数化操作

概念

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

基本用法

# (1) 基本用法
class MyClass():a = 1def __call__(self):print("call魔术方法被触发了")obj = MyClass() # 实例化一个对象
obj() # 把对象当做函数调用,此时会触发__call__方法

模拟洗衣服的过程

# (2) 模拟洗衣服的过程
class Wash():def __call__(self,something):print("我现在要洗{}".format(something))self.step1()self.step2()self.step3()return "洗完了"def step1(self):print("加热水,家洗衣粉,加洗衣液,加洗涤剂")def step2(self):print("衣服泡进去搅乱 打散 搓一搓~ ")def step3(self):print("脱水,穿上")obj = Wash()# 方法一
# obj.step1()
# obj.step2()
# obj.step3()# 方法二
res = obj("衣服") # 把对象obj当做函数进行调用,此时触发__call__方法,执行__call__方法所有内容
print(res)

模拟内置的int方法,实现相应的操作

# (3) 模拟内置int 实现相应的操作
import math
class MyInt():def calc(self,num,sign=1):# print(num,sign)# 去掉左边多余的0strvar = num.lstrip("0")# print(strvar)# 为了防止都是0 ,如果去掉之后为空,返回0if strvar == "":return 0# 正常情况下,执行存数字字符串变成数字 , 在乘上相应的符号,得出最后的结果return eval(strvar) * signdef __call__(self,num):if isinstance(num , bool):if num  == True:return 1elif num == False:                return 0elif isinstance(num,int):return numelif isinstance(num,float):# 方法一"""strvar = str(num)lst = strvar.split(".")return eval(lst[0])"""# 方法二"""if num >= 0:return math.floor(num)else:return math.ceil(num)"""return math.floor(num) if num >= 0 else  math.ceil(num)elif isinstance(num,str):if (num[0] == "+" or num[0]== "-") and num[1:].isdecimal():if num[0] == "+":sign = 1else:sign = -1                    return self.calc(num[1:],sign)elif num.isdecimal():return self.calc(num)else:return "老铁,这个真转不了"myint = MyInt()
# myint(5) => 5
# myint(3.14) => 3res = myint(True)
print(res)
res = myint(100)
print(res)
res = myint(3333.14)
print(res, type(res)) # 3
# bool int float "12312312323"# int(3.14) => 3
print(int(3.14))  # 3
print(int(-3.14)) # -3
print("<===>")
print(myint(3.14))
print(myint(-0.2))print("<===>")
print(int("0000000000000000000000000000000000000000001230000000"))
print(int("00000000000000000000000000000000000000000"),"1111222333")
print(int("+000000000000000000000000000000000000000000123"))
print(int("-000000000000000000000000000000000000000000123"))
print(int("000000000000000000000000000000000000000000123"))print("<==111=>")
print(myint("+000000000234"))
print(myint("000000000000000000000000000000000000000000123"))
print(myint("456899200"))
print(myint("3.143434"))
print(myint(+-++-+-+-+-+-+-+-+-+-+-++++++++-----234234),"<====>")
print(int(+-++-+-+-+-+-+-+-+-+-+-++++++++-----234234),"<====>")"""
exec("a = 3")
print(a)eval("4")
"""
# print(math.floor(0.14)) # 0
# print(math.floor(3.14)) # 3
# print(math.ceil(-3.14))  # -3

__bool__强转对象

概念

1.触发时机:使用bool(对象)的时候自动触发2.功能:强转对象3.参数:一个self接受当前对象4.返回值:必须是布尔类型

基本用法

class MyClass():def __bool__(self):return Falseobj = MyClass()
res = bool(obj)
print(res)

类似的还有如下等等(了解):
__ complex__(self) 被complex强转对象时调用
__ int__(self) 被int强转对象时调用
__ float__(self) 被float强转对象时调用

__ add__、__radd__对象运算

概念

1.触发时机:使用对象进行运算相加的时候自动触发2.功能:对象运算3.参数:二个对象参数4.返回值:运算后的值5.注意点:对象在加号+的左侧时,自动触发__add__方法对象在加号+的右侧时,自动触发__radd__方法加号左侧和右侧都是对象时,先触发__add__方法,再触发__radd__方法

基本用法

class MyClass1():def __init__(self,num):self.num = num# 对象在加号+的左侧时,自动触发def __add__(self,other):# print(self)# print(other)return self.num + other # return 10 + 7 = 17# 对象在加号+的右侧时,自动触发def __radd__(self,other):# print(self)# print(other)return self.num * 2 + other# 第一种
a = MyClass1(10)
res = a + 7
print(res) # 第二种
b = MyClass1(5)
res = 20 + b
print(res)# 第三种
print("<============>")
res = a+b
print(res)
"""
第一次触发魔术方法, a+ =>触发__add__方法
self => a other => b
self.num + other => a.num+ b => 10 + bres = 10 + b
第二次触发魔术方法 __radd__
self => b other=> 10
self.num * 2 + other => b.num*2 + other => 5 * 2 + 10 => 20
res = 20
"""

类似的还有如下等等(了解):
__ sub__(self, other) 定义减法的行为:-

__ mul__(self, other) 定义乘法的行为:*

__ truediv__(self, other) 定义真除法的行为:/

__len__用于检测对象中或者类中成员的个数

概念

1.触发时机:使用len(对象)的时候自动触发2.功能:用于检测对象中或者类中成员的个数3.参数:一个self接受当前对象4.返回值:必须返回整型

基本用法

class MyClass():pty1 = 1pty2 = 2__pty3 = 3pyt3  =10pty100 = 90def func1():passdef __func2():passdef __func3():passdef __len__(self):lst = []dic = MyClass.__dict__# 方法一# print(MyClass.__dict__) # 获取类当中的所有成员# print(object.__dict__) # 获取对象中的所有成员dic = MyClass.__dict__ # 遍历类中所有成员for i in dic: # 遍历类中所有成员if not(i.startswith("__") and i.endswith("__")): # 如果开头和结尾都不是以双下划线结尾lst.append(i) # 将符合条件的成员添加到列表中return len(lst) # 方法二lst = [i for i in dic if  not(i.startswith("__") and i.endswith("__"))]return len(lst)

5个类的魔术属性

类的魔术属性

__dict__ 获取对象或类的内部成员结构__doc__ 获取对象或类的内部文档__name__ 获取类名函数名__class__ 获取当前对象所属的类__bases__ 获取一个类直接继承的所有父类,返回元组

用法

class Man():passclass Woman():passclass Children(Man,Woman):"""功能: 描述小孩天生的属性成员属性:eye , skin成员方法:skylight , moonread , __makebaby    """eye = "万花筒血轮眼"skin = "白色"def skylight(self):print("宇智波家族的小孩,天生能够发动天照技能")def moonread(self,func):# func = func111print("宇智波家族的小孩,能够发动月亮的光照消灭你~")res = func.__name__print(res,type(res))def __makebaby(self):print("这一手招数,只能我自己用")# __dict__ 获取对象或类的内部成员结构
obj = Children()
print(obj.__dict__)
print(Children.__dict__)# __doc__  获取对象或类的内部文档
print(obj.__doc__)
print(Children.__doc__)# __name__ 获取类名函数名
def func111():    print("我是func111方法")
# 获取函数名
obj.moonread(func111)
# 获取类名
obj.moonread(Man)# __class__ 获取当前对象所属的类
print(obj.__class__)# __bases__ 获取一个类直接继承的所有父类,返回元组
print(Children.__bases__)

单态模式

注意:和__new__方法搭配使用

概念

同一个类,无论实例化多少次,都有且只有一个对象每创建一个对象,就会在内存中多占用一份空间
为了节省空间,提升执行效率,使用单态模式场景:只是单纯调用类中的成员,而不会额外为当前对象添加成员;

基本语法

class Singleton():__obj = Nonedef __new__(cls):if cls.__obj is None:cls.__obj = object.__new__(cls)return cls.__obj"""
解析:
第一次,在实例化对象时触发__new__魔术方法
if cls.__obj is None 条件成立  cls.__obj = object.__new__(cls) 创建一个对象给私有成员属性__obj
return cls.__obj  用obj1接收到了对象第二次,在实例化对象时触发__new__魔术方法 if cls.__obj is None不满足,因为已经在__obj属性中存放了一个对象
return cls.__obj第三次,在实例化对象时触发__new__魔术方法 if cls.__obj is None不满足,因为已经在__obj属性中存放了一个对象
return cls.__obj
"""
obj1 = Singleton()
obj2 = Singleton()
obj3 = Singleton()
print(obj1,obj2,obj3)

单态模式+构造方法

class Singleton():__obj = Nonedef __new__(cls,*args,**kwargs):if cls.__obj is None:cls.__obj = object.__new__(cls)return cls.__objdef __init__(self,name):self.name = nameobj1 = Singleton("大漠")
obj2 = Singleton("落日")
print(obj1,obj2)
print(obj1.name)
print(obj2.name)
'''
解析:
第一次实例化对象时,
触发__new__ if cls.__obj is None: 创建一个新的对象进行返回
然后触发__init__ self.name = 大漠第二次实例化对象时
触发__new__ if cls.__obj is None: 条件不满足,返回的是第一次实例化的对象,是同一个
然后触发__init__ self.name = 落日obj1 和 obj2 所指代的对象是同一个对象obj1.name => 落日
obj2.name => 落日其实有些相当于是B把A覆盖了,因为B和A指向同一个对象
'''

魔术方法、5个类的魔术属性和单态相关推荐

  1. java类似php魔术方法_PHP与类有关的几个魔术方法

    与类有关的其他魔术方法 序列化与反序列化技术 含义: 序列化: 就是将一个变量所代表的"内存"数据,转换为"字符串"形式并持久保存在硬盘上的一种做法. 反序列化 ...

  2. php 魔术方法 多继承,PHP通过魔术方法实现多继承与重载

    PHP所提供的"重载"(overloading)是指动态地"创建"类属性和方法.我们是通过魔术方法(magic methods)来实现的.当调用当前环境下未定义 ...

  3. python创建实例会调用哪些魔术方法_Python最会变魔术的魔术方法,我觉得是它!...

    作者:豌豆花下猫 来源:Python猫 在,我有一个核心的发现:Python 内置类型的特殊方法(含魔术方法与其它方法)由 C 语言独立实现,在 Python 层面不存在调用关系. 但是,文中也提到了 ...

  4. php面向对象魔术方法,PHP面向对象中的魔术方法

    魔术方法:某种场景下,能够自动调用的方法 如: __construct. __destruct.__set. __get. __isset.__unset.__call __construct(): ...

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

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

  6. php魔术方法和代码,PHP的魔术方法_php

    1.__get/__set:对对象属性的接管 2.__call/__callStatic:控制php对象方法的使用 3.__toString:将php对象转换成字符串 4.__invoke:将一个ph ...

  7. java中如何使用反射调用方法以及获得类中的属性

    使用反射获取类中的方法: 1):获取方法所在类的字节码对象. 2):获取方法. ------------------------------------------------------------ ...

  8. PHP面向对象的魔术方法

    <?php /** * Created by PhpStorm. * User: fu * Date: 2017/7/19 * Time: 9:41 */ class Person{ prote ...

  9. (转)python类:magic魔术方法

    原文:https://blog.csdn.net/pipisorry/article/details/50708812 版权声明:本文为博主皮皮http://blog.csdn.net/pipisor ...

  10. php如何在特定情况下触发,php类知识点滴---魔术方法,系统在特定时机触发的方法...

    __get()获取私有或受保护属性时调用的方法 class coach { private $chairfit = "徐晓冬"; public function __constru ...

最新文章

  1. 5G时代,工业互联网安全挑战远超消费互联网
  2. linux下创建多进程,linux之多进程fork:进程创建
  3. Stanford UFLDL教程 独立成分分析
  4. MATLAB实现实时录音,语音采集与读写用matlab实现录音以及语谱图的绘制.pdf
  5. 第二章:Webdriver 控制浏览器前进和后退
  6. tomcat配置项目路径或部署工程名
  7. kylin版本_kylin多维数据分析(一)单机部署
  8. 微服务熔断限流Hystrix之流聚合
  9. http 响应消息解码_响应生成所需的解码策略
  10. php个人网页完整代码,个人主页php+html
  11. 国家开放大学2021春1062文学英语赏析题目
  12. kafka-eagle 使用配置及远程jmx端口设置遇到的问题
  13. 软件开发外包:你有什么选择
  14. 直播美颜SDK代码浅析:直播平台接入美颜SDK是怎样实现美颜的?
  15. 海洋cms单本小说网站模板
  16. RCNN,Fast RCNN, Faster RCN解析
  17. 用SkinMagic工具包创建换皮肤程序
  18. 从开发转网络安全工程师一点不后悔,兴趣大于一切!
  19. 【迷人的爪哇】—带你从零开始了解Java
  20. SQL Pass北京将举办第一次线下活动,欢迎大家报名

热门文章

  1. RedHat 8 dnf源配置
  2. wordpress企业主题安装
  3. OpenCV创始人Gary Bradski,现已加入蓝胖子机器人
  4. 马步站桩---快速健身法
  5. Android Studio连接海马玩模拟器
  6. flutter 实现文字竖排以及动画效果(文字逐一显示)
  7. Android自定义Behavior
  8. Android下载多张图片保存到本地
  9. html设置本地字体文件
  10. xp计算机workgroup无法访问,无法访问,小编告诉你怎么解决workgroup无法访问