zoukankan      html  css  js  c++  java
  • Python-魔术方法

    一、__new__方法

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

    1.基本语法

    class MyClass():
    	a = 1
    
    obj = MyClass()
    print(obj)
    
    class MyClass1(object):
    	def __new__(cls):
    		print(cls)
    		# (1)借助父类object 类.方法(),返回本类自己的对象
    		# obj = object.__new__(cls)
    		# return obj
    		# (2)返回其他类的对象
    		# return obj
    		# (3)不返回任何对象
    		return None
    		
    obj = MyClass1()
    print(obj)
    

    2.new方法的触发时机要快于init

    new 用来创建对象
    init 用来初始化对象(前提的有对象)
    先创建对象,再去初始化对象,所以new快于init

    class Boat():
    	def __init__(self):
    		print(2)
    		
    	def __new__(cls):
    		print(1)
    		return object.__new__(cls)
    obj = Boat()
    

    3.new方法的参数要和init方法参数一一对应

    # 一个参数
    class Boat():
    	def __new__(cls,name):
    		return object.__new__(cls)
    	
    	def __init__(self,name):
    		self.name = name
    		
    obj = Boat("泰坦尼克号")
    print(obj.name)
    
    
    # 多个参数
    class Boat():
    	def __new__(cls,*args,**kwargs):
    		return object.__new__(cls)
    	
    	def __init__(self,name,a,b,c,d,e):
    		self.name = name
    		
    obj = Boat("泰坦尼克号",2,3,4,5,6)
    print(obj.name)
    

    4.如果返回的不是本类的对象,不会触发__init__构造方法

    print("<=====>")
    class MyClass():
    	a = 1
    other_obj = MyClass()
    
    class Boat():
    	def __new__(cls):
    		return other_obj
    	
    	def __init__(self):
    		print("构造方法被触发~")
    
    obj = Boat()
    

    二、单例(态)模式

    目的意义:
    为了节省内存空间,仅仅是为了调用类中的成员,
    不需要额外给该对象添加任何成员,这个场景,使用单态.
    比如:操作数据库的增删改查这样的类,是不需要的.

    1.基本语法

    class Singleton():
    	__obj = None
    	def __new__(cls):
    		if cls.__obj is None:
    			cls.__obj = object.__new__(cls)
    		return cls.__obj 
    
    """
    <__main__.Singleton object at 0x000001FB3F207278>
    有这个对象直接返回,没这个对象,就给你创建,保证只有一个
    第一次实例化时,if cls.__obj is None 条件为真 , 创建一个对象放到cls.__obj , 最后返回
    第二次实例化时,if cls.__obj is None 条件为假 , 直接返回
    第三次实例化时,if cls.__obj is None 条件为假 , 直接返回
    第三次实例化时,if cls.__obj is None 条件为假 , 直接返回
    """
    
    obj1 = Singleton()
    print(obj1)
    obj2 = Singleton()
    print(obj2)
    obj3 = Singleton()
    print(obj3)
    obj4 = Singleton()
    print(obj4)
    # 打印结果为同一个对象
    

    2.单态模式+构造方法 小练习

    class Singleton():
    	__obj = None
    	def __new__(cls,*args,**kwargs):
    		if cls.__obj is None:
    			cls.__obj = object.__new__(cls)
    		return cls.__obj 
    
    	def __init__(self,name):
    		self.name = name
    		
    obj1 = Singleton("aaa")
    obj2 = Singleton("bbb")
    # 求答案
    print(obj1.name)
    print(obj2.name)
    # obj1 和 obj2 都是同时指向同一个对象,因为对象只创建了一个对象.name  是获取他后边bbb那个值,是同一个值打印了2次;
    

    三、__del__析构方法

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

    1.基本方法

    del只会触发一次,即如果先把所有的对象给删除了,那么在执行完所有代码之后不会再触发

    class LangDog():
    	food = "吃肉"
    	def __init__(self,name):
    		self.name = name
    		
    	def __del__(self):
    		print("析构方法被触发..")
    	
    #(1) 页面执行完毕回收所有变量
    obj = LangDog("刀疤")
    print(obj.name)
    
    #(2) 所有对象被del的时候
    """
    当一个值,没有任何变量指向或者说引用,这个值才会被真正的释放
    """
    other_obj = obj
    print(other_obj is obj)
    print("<==start==>")
    del obj
    del other_obj
    print("<==end==>")
    

    2.模拟文件操作练习

    将文件操作也封装起来,这要其他同事在使用文件操作时候,只需要调用我们写的代码就可以了,减少了代码冗余

    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):		
    		# 读取文件操作
    		content = self.fp.read()
    		return content
    		
    	def __del__(self):
    		self.fp.close()
    		
    
    		
    obj = ReadFile("ceshi.txt")
    res = obj.readcontent()
    print(res)
    

    四、__str__与__repr__方法

    1.__str__

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

    class Cat():
    	gift = "传说中的小猫有九条命,喜欢卖萌和上树"
    	
    	def __init__(self,name):
    		self.name = name
    		
    	def __str__(self):
    		return self.cat_info()
    		
    	def cat_info(self):
    		return "{}小猫有故事-{}".format(self.name,self.gift)
    
    tom = Cat("汤姆")
    # 触发方式一, print 打印该对象
    print(tom)
    # 触发方式二, str
    res = str(tom)
    print(res)
    

    2.__repr__

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

    class Mouse():
    	gift = "打洞"
    	
    	def __init__(self,name):
    		self.name = name
    		
    	def __repr__(self):
    		return self.mouse_info()
    		
    	def mouse_info(self):
    		return "{}老鼠天赋是{},龙生龙,凤生凤,老鼠的儿子会打洞".format(self.name,self.gift)
    		
    	# 在系统底层,如果定义了repr , 将会默认赋值给str方法.
    	# __str__ = __repr__
    		
    
    # repr强转obj对象时触发		
    obj = Mouse("杰瑞")
    res = repr(obj)
    print(res)
    
    # 注意点 底层存在赋值调用给str的语法,所以能实现打印或者str强转对象的触发机制.
    print(obj)
    res = str(obj)
    print(res)
    

    五、__call__方法

    触发时机:把对象当做函数调用时候自动触发
    功能:模拟函数化操作

    参数:参数不固定,至少一个self参数

    返回值:看需求

    1.基本用法

    class MyClass():
    	a = 1
    	""""""
    	def __call__(self):
    		print("call魔术方法被触发..")	
    
    obj = MyClass()
    obj()
    

    2.call魔术方法的应用

    # 模拟洗衣服的过程
    class Wash():
    
    	# 用call魔术方法统一调用
    	def __call__(self,something):
    		self.step1(something)
    		self.step2()
    		self.step3()
    
    	def step1(self,something):
    		print("脱衣服,洗{}".format(something))
    		
    	def step2(self):
    		print("放水里,扔点洗衣液,洗衣粉,蓝月亮")
    		
    	def step3(self):
    		print("扭干净,穿上")
    
    # 利用魔术方法我们只需要两步完成了洗衣服的过程,并且之后洗衣服只需要一个语句
    obj = Wash()
    obj("裤衩")
    obj("衣服")
    obj("袜子")
    obj("毛巾")
    # 如不使用魔术方法,我们每次洗衣服都需要调三个函数
    obj.step1("裤衩")
    obj.step2()
    obj.step3()
    obj.step1("衣服")
    obj.step2()
    obj.step3()
    obj.step1("袜子")
    obj.step2()
    obj.step3()
    obj.step1("毛巾")
    obj.step2()
    obj.step3()
    

    3.模拟内置函数int

    import math
    class MyInt():
    
    	def mycalc(self,num,sign=1):
    		# 去掉左边多余的0
    		strvar = num.lstrip("0")
    		if strvar == "":
    			return 0
    		# 计算最终的结果
    		return eval(strvar) * sign
    
    
    	def __call__(self,num):
    	
    		# 判断是布尔类型
    		if isinstance(num,bool):
    			if num == True:
    				return 1
    			else:
    				return 0
    		# 判断是整型
    		elif isinstance(num,int):
    			return num
    		# 判断是浮点型
    		elif isinstance(num,float):
    			# 方法一
    			'''
    			strvar = str(num)			
    			return strvar.split(".")[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 = 1
    				else:
    					sign = -1
    				return self.mycalc(num[1:],sign)
    				
    			elif num.isdecimal():
    				return self.mycalc(num)
    				
    			else:
    				return "老铁,这个真不能转~"
    

    六、__bool__方法

    触发时机:使用bool(对象)的时候自动触发

    功能:强转对象

    参数:一个self接受当前对象

    返回值:必须是布尔类型

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

    __complex__(self)      # 被complex强转对象时调用
    __int__(self)          # 被int强转对象时调用
    __float__(self)        # 被float强转对象时调用
    

    基本语法

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

    七、__add__方法

    触发时机:使用对象进行运算相加的时候自动触发

    功能:对象运算

    参数:两个对象参数

    返回值:运算后的值(其中的运算规则可以自己定制)

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

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

    基本语法及小练习

    class MyAdd():
    	def __init__(self,num):
    		self.num = num
    
    	# 对象在加号+左侧的时,自动触发
    	def __add__(self,other):
    		return self.num + other
    		
    	def __radd__(self,other):
    		return self.num + other*2
    		
    # 情况一
    a = MyAdd(7)
    res = a + 7
    print(res)
    # self 接受a   other接受7 , 触发的是__add__方法
    
    # 情况二
    a = MyAdd(7)
    res = 7 + a
    print(res)
    # self 接受a   other接受7 , 触发的是__radd__方法
    
    # 情况三
    a = MyAdd(7)
    b = MyAdd(8)
    res = a+b
    print(res)
    '''
    a+b 先触发 __add__  ,self 接受的7 , other 接受的是b
    res = 7+b
    
    7+b 再触发 __radd__ ,self 接受的b , other 接受的是7
    return  8+7*2 = 22
    res = 22
    '''
    

    八、__len__方法

    触发时机:使用len(对象)时自动触发

    功能:用于检测对象中或者类中成员的个数

    参数:一个self参数,用来接收当前对象

    返回值:必须是整型

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

    __iter__(self)                 # 定义迭代容器中的元素的行为
    __reversed__(self)             # 定义当被 reversed() 调用时的行为
    __contains__(self, item)       # 定义当使用成员测试运算符(in 或 not in)时的行为
    

    基本语法及使用

    class MyClass():
    	pty1 = 1
    	pty2 = 2
    	__pty3 = 3
    	
    	def func1():
    		pass
    		
    	def func2():
    		pass
    	def __func3():
    		pass
    	
    	def func4():
    		pass
    		
    	def __len__(self):
    		# print(MyClass.__dict__)
    		# lst = []
    		# for i in MyClass.__dict__:
    			# print(i)
    			# if not(  i.startswith("__") and i.endswith("__")  ):
    				# lst.append(i)
    		# print(lst)	
    		
    		# 简写
    		lst = [i for i in MyClass.__dict__ if not(  i.startswith("__") and i.endswith("__")  )]
    		return len(lst)
    		
    obj = MyClass()
    print(len(obj))
    

    九、__getattr__方法

    基本语法及使用

    当对象访问一个不存在的属性时候,会触发该方法。

    class Student:
        def __init__(self, name, sex, age):
            self.name = name
            self.sex = sex
            self.age = age
    
        def __getattr__(self,x):
            return '你没有这个属性,小老弟'
    
    s = Student('yang','male',18)
    print(s.name)
    print(s.salary)
    ------------------
    yang
    你没有这个属性,小老弟
    

    十、魔术属性

    以__开头__结尾的属性,称为魔术属性,如之前ATM项目中使用到的__name__就是魔术属性.

    本笔记记录常用的五种魔术属性,dict,doc,name,class,bases

    class Man():
    	pass
    
    class Woman():
    	pass
    
    class Children(Man,Woman):
    
    	"""
    	成员属性: eye 
    	成员方法: skylight moonread __makebaby
    	完成的功能: 描述宇智波一族的天赋技能.
    	"""
    
    	eye = "血轮眼"
    	
    	def skylight(self):
    		print("使用")
    		
    	def moonread(self,func):
    		print("使用了月读,世界都幻境里~")
    		print(func.__name__ , type(  func.__name__  )) # earth_boom
    	
    	def __makebaby(self):
    		print("这一手招数,只能我自己用")
    
    obj = Children()
    
    # __dict__ 获取对象或类的内部成员结构
    print(obj.__dict__)
    print(Children.__dict__)
    
    # __doc__  获取对象或类的内部文档
    print(obj.__doc__)
    print(Children.__doc__)
    
    # __name__  获取类名函数名
    def earth_boom():
    	print("使出一招地爆天星")
    obj.moonread(earth_boom)
    obj.moonread(Children)
    
    # __class__ 获取当前对象所属的类
    print(obj.__class__)
    
    # __bases__ 获取一个类直接继承的所有父类,返回元组
    print(Children.__bases__) # (<class '__main__.Man'>, <class '__main__.Woman'>)
    
  • 相关阅读:
    Hibernate之必须导入jar包
    浏览器兼容性问题
    CSS中的浮动清除
    CSS的三种手段让元素脱离标准本文档流——浮动、绝对定位、固定定位
    块级元素和行内元素
    网页设计前端——盒子模型
    CSS的继承性和层叠性
    网站前端设计——选择器
    网站中图片的相对路径与绝对路径
    网站隐藏文件夹
  • 原文地址:https://www.cnblogs.com/chiyun/p/14066047.html
Copyright © 2011-2022 走看看