032.Python魔术方法__new__和单态模式

一 __new__ 魔术方法

1.1 介绍

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

类.属性
类.方法()

1.2 基本用法

class MyClass():
        abc = 123
        def __new__(cls):      #把class这个类传递__new__这个方法
                print (123)
                return None     #返回一个None

#实例化对象
obj = MyClass()
print (obj)

执行

这样就不能使用使用obj这个对象调用abc的值

class MyClass():
        abc = 123
        def __new__(cls):
                print (123)
                return None

#实例化对象
obj = MyClass()
print (obj)
print (obj.abc)      #在这里就相当于使用None.abc.这种此写法不允许,就会报错

执行

借助父类创建对象

返回本类对象

class MyClass():
        abc = 123
        def __new__(cls):          print (cls)
                print (123)
                #要借助父类object的__new__创建对象
                obj = object.__new__(cls)
                return obj

#实例化对象
obj = MyClass()
print (obj)
print (obj.abc)

执行

[[email protected] python]# python3 test.py<class ‘__main__.MyClass‘>      #cls是一个类
123
<__main__.MyClass object at 0x7ff2808ba3c8>
123
[root

返回空对象

class MyClass():
        abc = 123
        def __new__(cls):
                print (cls)
                print (123)
                #要借助父类object的__new__创建对象
                obj = object.__new__(cls)
                #return obj
                return None

#实例化对象
obj = MyClass()
print (obj)
print (obj.abc)

执行

返回一个其他类的对象

class MyClass2():
        ccc = 4
obj2 = MyClass2()
class MyClass():
        abc = 123
        def __new__(cls):
                print (cls)
                print (123)
                #要借助父类object的__new__创建对象
                obj = object.__new__(cls)
                #return obj
                #return None
                return obj2

#实例化对象
obj = MyClass()
print (obj)
print (obj.abc)

执行

修改属性

[[email protected] python]# cat test.py
class MyClass2():
        ccc = 4
obj2 = MyClass2()
class MyClass():
        abc = 123
        def __new__(cls):
                print (cls)
                print (123)
                #要借助父类object的__new__创建对象
                obj = object.__new__(cls)
                #return obj
                #return None
                return obj2

#实例化对象
obj = MyClass()
print (obj)
print (obj.ccc)

执行

[[email protected] python]# python3 test.py
<class ‘__main__.MyClass‘>
123
<__main__.MyClass2 object at 0x7fb463cc7470>
4

1.3 对__new__和__init__这两个魔术方法的区别

调用的顺序

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

执行

[[email protected] python]# python3 test.py
1
2
<__main__.Boat object at 0x7f9bb5fcf400>

先调用__new__在调用__init__

调用和定义的顺序无关

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

执行

[[email protected] python]# python3 test.py
1
2
<__main__.Boat object at 0x7f95a73cf400>

结果一样

__new__ 的触发时机要快于 __init__
__new__  是用来创建对象的
__init__ 是用来初始化对象的

先得有对象
才能初始化对象

new 和 init 他门的参数要保持一致.

1.4  如果返回的不是一个本类对象__init__就不会触发

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

执行

[[email protected] python]# python3 test.py
1
None

初始化参数

class Boat():
        def __new__(cls):
                print (1)
                return object.__new__(cls)
                #return None
        def __init__(self,name):
                self.name = name
obj = Boat("John")
print (obj.name)

执行

[[email protected] python]# python3 test.py
Traceback (most recent call last):
  File "test.py", line 8, in <module>
    obj = Boat("John")
TypeError: __new__() takes 1 positional argument but 2 were given

这是因为,__new__先于__init__调用,但是,在调用的时候,已经传递了一个类(cls)的参数,name的参数就不能对应报错

class Boat():
        def __new__(cls,name):
                print (1)
                return object.__new__(cls)
                #return None
        def __init__(self,name):
                self.name = name
obj = Boat("John")
print (obj.name)

执行,而可以调用

[[email protected] python]# python3 test.py
1
John

1.5 使用参数的普通参数和关键字实参

lass Boat():
        def __new__(cls,*args,**kwargs):
                print (1)
                return object.__new__(cls)
                #return None
        def __init__(self,*args,**kwargs):
                strvar = ""
                for i in args:
                        strvar += i + " "
                print (strvar)
                print (kwargs)
obj = Boat("John","Jim","Tom",name="David")

执行

[[email protected] python]# python3 test.py
1
John Jim Tom
{‘name‘: ‘David‘}

1.6 如果__new__魔术方法返回的时其他类的对象,不会触发__init__ 本类的魔术方法

class MyClass2():
        ccc = 4
obj2 = MyClass2()
class Boat():
        def __new__(cls,*args,**kwargs):
                print (1)
                #return object.__new__(cls)
                return obj2
        def __init__(self,*args,**kwargs):
                print (111)
obj = Boat("John","Jim","Tom",name="David")
print (obj.ccc)

执行

[[email protected] python]# python3 test.py
1
4

二 单态模式

无论实例化类几次,都有且只有一个对象.为了节省内存空间

2.1 创建一个类,实例化三个对象

[[email protected] python]# cat test.py
class Singleton():
        pass
obj1 = Singleton()
print (obj1)
obj2 = Singleton()
print (obj2)
obj3 = Singleton()
print (obj3)

执行

[[email protected] python]# python3 test.py
<__main__.Singleton object at 0x7efd7ec76400>
<__main__.Singleton object at 0x7efd7ec76438>
<__main__.Singleton object at 0x7efd7ec76470>

可以看到占用不同的内存空间

2.2 使用单态模式

class Singleton():
        #创建一个私有的对象,类外无法调用
        __obj = None
        #定义一个方法
        def __new__(cls):
                #判断这个对象是否为None对象
                if cls.__obj is None:
                        obj = object.__new__(cls)   #如果是,就重新创建一个新的对象
                        cls.__obj = obj             #把这新的对象夫给类的私有方法
                return cls.__obj                    #如果不是None,直接返回
obj1 = Singleton()
print (obj1)
obj2 = Singleton()
print (obj2)
obj3 = Singleton()
print (obj3)

执行

[[email protected] python]# python3 test.py
<__main__.Singleton object at 0x7fbae7edb4a8>
<__main__.Singleton object at 0x7fbae7edb4a8>
<__main__.Singleton object at 0x7fbae7edb4a8>

发现三个对象都是一个内存地址

2.3 实际的含义,对象和init之间的关系

class Singleton():
        #创建一个私有的对象,类外无法调用
        __obj = None
        #定义一个方法
        def __new__(cls,name):
                #判断这个对象是否为None对象
                if cls.__obj is None:
                        cls.__obj = object.__new__(cls)
                return cls.__obj
        def __init__(self,name):
                self.name = name
obj1 = Singleton("John")
obj2 = Singleton("Frnak")
print (obj1.name)
print (obj2.name)

执行

[[email protected] python]# python3 test.py
Frnak
Frnak

原文地址:https://www.cnblogs.com/zyxnhr/p/12344977.html

时间: 2024-10-10 11:57:51

032.Python魔术方法__new__和单态模式的相关文章

python中单例模式的实现-通过闭包函数和魔术方法__new__实现单例模式

1.通过闭包函数实现单例模式: # 使用闭包函数实现单例 def single(cls, *args, **kwargs): instance = {} def get_instance(): if cls not in instance: instance[cls] = cls(*args, **kwargs) return instance[cls] return get_instance @single class Apple: pass a = Apple() b = Apple() p

Python 魔术方法笔记

魔术方法总是被__包围, 如__init__ , __len__都是常见的魔术方法,这里主要写一下我遇到的一些魔术方法 setitem 对某个索引值赋值时 即可以进行赋值操作,如 def __setitem__(self, k, v): self.put(k, v) 在上述代码的情况下,可以执行p['key'] = value操作,即将key赋给k,value赋给v,执行put(k, v)函数.所以,__setitem__建立的前提,是要这个函数内的操作本来具有赋值的性质. getitem 使用

Python 魔术方法及调用方式

魔术方法 调用方式 解释 __new__(cls [,...]) instance = MyClass(arg1, arg2) __new__ 在创建实例的时候被调用 __init__(self [,...]) instance = MyClass(arg1, arg2) __init__ 在创建实例的时候被调用 __cmp__(self, other) self == other, self > other, 等. 在比较的时候调用 __pos__(self) +self 一元加运算符 __n

[学习记录]python魔术方法与抽象方法like型反思

之前一直没搞懂python的魔术方法是怎么回事,今天看到一篇讲的很好的文章,这里先把链接贴出来 总的来说魔术方法就是定义成用两条下划线包围方法名前后的一种方法,例如__init__,__del__等等 换句话说,当你在python中使用dir()时,看到的那么一大堆__方法__都是魔术方法,如下图 test类只定义了一个hello方法,但是dir展示了大量的魔术方法.这些魔术方法都是内置的,但是允许我们对它们进行重写. 对比一下会感觉有点像定义的接口类的抽象方法,定义出来作为模板,然后由子类对其

Python魔术方法

1. 查看属性 方法: __dir__ 意义: 返回类或者对象的所有成员名称列表.dir()函数就是调用__dir__().如果提供__dir__(),则返回属性的列表,否则会尽量从__dict__属性中收集信息. 如果dir([obj])参数包含方法__dict__(),该方法将被调用.如果参数不包含__dir__(),该方法将最大限度地收集参数信息. dir()对于不同类型的对象具有不同的行为: 如果对象是模块对象,列表包含模块的属性名. 如果对象是类型或者类对象,列表包含类的属性名,及它的

python 魔术方法

import time func_count_time_dict = {} def count_time(func): global func_count_time_dict func_count_time_dict[func]=[1,time.localtime()] def wrapper(): global func_count_time_dict func() print 'func name: ',func.__name__ print 'count: ',func_count_tim

流动python - 什么是魔术方法(magic method)

我们经常看到各种各样的方法已经被包围了由双下划线,例如__init__,他们是魔术方法. 魔术方法python语言预订好"协议",在不同情况下不同的魔术方法,是隐式调用.我们重写这些方法,因此,操纵各种行为. class A(object): def __str__(self): return "I am A,2333" def __len__(self): return 42 a = A() print a#输出 "I am A,2333" p

飘逸的python - 什么是魔术方法(magic method)

我们经常看到各种被双下划线环绕的方法,如__init__,它们就是魔术方法. 魔术方法是python语言预定好的"协议",不同魔术方法在不同场景下,会被隐式调用.我们通过重载这些方法,从而操控各种行为. class A(object): def __str__(self): return "I am A,2333" def __len__(self): return 42 a = A() print a#输出 "I am A,2333" prin

python魔法方法

Python 魔术方法指南 入门 构造和初始化 构造定制类 用于比较的魔术方法 用于数值处理的魔术方法 表现你的类 控制属性访问 创建定制序列 反射 可以调用的对象 会话管理器 创建描述器对象 持久化对象 总结 附录 介绍 此教程为我的数篇文章中的一个重点.主题是魔术方法. 什么是魔术方法?他们是面向对象的Python的一切.他们是可以给你的类增加”magic”的特殊方法.他们总是被双下划线所包围(e.g. __init__ 或者 __lt__).然而他们的文档却远没有提供应该有的内容.Pyth