• 10.new方法和单列模式、定制属性访问、描述符、装饰器


      new方法和单列模式  

     一、new方法

    1 . 四个点理解__new__方法

    1、__new__方法是在 类 创建实例 的时候 自动调用的。

    2、实例是通过类里面的__new__方法是在 类 创建出来的

    3、先调用__new__方法创建实例,再调用 __init__方法初始化实例。

    4、__new__方法,,后面括号里的cls代表 的是类本身

    #一般不会重写__new__方法,常用在单例模式
    class Hero(object):
    
        def __init__(self,name):
            self.name = name
    
            print('%s调用了我进行初始化'%self.name)
    
        def __new__(cls, *args, **kwargs):
            print(args)       #*args  传入位置参数   #**kwargs  传入关键字参数     #用于间接传参
            print('new方法被调用了,要创建一个对象')
            return object.__new__(cls)   #重写__new__方法不要忘记       #cls 代表类本身
    
    moran = Hero('墨染')
    print(id(moran) )
    ni = Hero('AA')
    print(id(ni))
    # print(moran.name)
    
    ('墨染',)
    new方法被调用了,要创建一个对象
    墨染调用了我进行初始化
    3072197388
    ('AA',)
    new方法被调用了,要创建一个对象
    AA调用了我进行初始化
    3072197420

    我们可以看到创建实例的时候,自动调用了__new__,方法和__init__方法,并且 是先调用的__new__再调用的__init__方法,打印 cls 的时候显示的这个Hero类

    二、单例模式

    单例模式实现的原理:通过重写__new__方法,让__new__只能进行一次实例创建。

    class Hero:
        __instance = None      #定义一个私有 类属性 并赋值为None
        def __new__(cls, *args, **kwargs):          #创建对象
            if cls.__instance == None:              #然后我们判断它是不是等于None,如果等于None,我们调用父类的方法创建一个实例对象,并把返回的对象赋值给 __instance,并且返回__instance
    
                cls.__instance = object.__new__(cls)
                return cls.__instance
            else:                                  #如果__instance不等于None,那就说明已经创建了对象  我们直接把__instance返回出去。
                return cls.__instance
    moran = Hero()
    print(id(moran))
    yanzhi = Hero()
    print(id(yanzhi))
    
    
    3072236972
    3072236972

    两个实例的ID是相同的,意味着第二 次创建的时候,并没有真正的去创建,而是引用的第一次创的实例, 同一个实例的不同名字

           定制属性访问      

    class Hero:
        attr1 = 1001
        attr2 = 1002
        def __getattribute__(self, item):        
    print('------bute------')                                 
        def __getattr__(self, item):                          
            print('get调用的时候触发了我')                       
        def __setattr__(self, key, value):                        
            print('set调用的时候触发了我')                       
    yanzhi = Hero()                                           
    yanzhi.attr1
    #  属性查找
    print(hasattr(yanzhi,'attr2')) #属性存在返回Ture 不存在返回False 判断是否存在属性,果属性存在则进行下一步操作
    print(getattr(yanzhi,'attr1'))    #属性存在返回属性值 不存在报错   得到属性值
    #  增加属性
    yanzhi.name = '炎志'
    setattr(yanzhi,'age',18)
    print(yanzhi.name)
    print(yanzhi.age)
    #  修改属性
    setattr(yanzhi,'age',28)           #设置属性值
    print(yanzhi.age)
    #  删除属性
    # delattr(yanzhi,'attr1')
    # print(yanzhi.attr1)
    
    ------bute------
    ------bute------
    True
    ------bute------
    None
    set调用的时候触发了我
    set调用的时候触发了我
    ------bute------
    None
    ------bute------
    None
    set调用的时候触发了我
    ------bute------
    None

                描述符             

    描述符协议:python描述符是一个“绑定行 为”的对象属性,在描述符协议中,它可以 通过方法重写属性的访问。这些方法有 __get__(), __set__(), 和__delete__()。

    如果这些方法中的任何一个被定义在一个对 象中,这个对象就是一个描述符

    魔术方法的作用其实是让开发人员能够更加灵活的控制类的表现形式

    class Hero:
        def __get__(self, instance, owner):
            print("--------get----------")
        def __set__(self, instance, value):
            print("---------set---------")
        def __delete__(self, instance):
            print("-------delete--------")
    class MyClass:
        m = Hero()
        attr = 111
    c = MyClass()
    c.m
    
    c.m = 1111
    del c.m
    
    --------get----------
    ---------set---------
    -------delete--------

                装饰器             

     一、装饰器

    能够实现在不修改原来的函数的基础上添加功能,修饰函数。

    #闭包复习,装饰器引入
    def func(a):
        def fun1():
            print("---------func------------")
            print(a)
            a()
        return fun1
    @func
    def fun():
        print("我是-----fun------")
    # # func(fun)()
    # result = func(fun)
    # result()
    fun()
    
    ---------func------------
    <function fun at 0xb7249a4c>
    我是-----fun------
    #简单装饰器
    def f1(func):
        def f2():
            print("装饰的功能")
            func()
        return f2
    @f1
    def func():
        print("基础功能代码")
    func()
    
    
    装饰的功能
    基础功能代码
    #通过装饰器实现功能
    def f1(func):
        def f2(a,b):
            print("a加b的结果是:%s" % (a + b))
            print("a减b的结果是:%s" % (a - b))
            print("a除b的结果是:%s" % (a / b))
            func(a,b)
        return f2
    @f1
    def func(a,b):
        print("a乘b的结果是:%s"%(a*b))
    func(11,2)
    
    
    a加b的结果是:13
    a减b的结果是:9
    a除b的结果是:5.5
    a乘b的结果是:22

    二、内置装饰器(经常使用)

     python的类里面中还有三个内置的装饰器:

    class MyClass(object):
        attr = ''
        @property            #让方法像属性一样被访问  将类里面的一个方法变成属性
        def func1(self):
            print('--------这是func1---------')
        @classmethod        #
        def func2(cls):    #cls 标识类方法   self访问不到
            print('--------这是func2---------')
        @staticmethod
        def func3():         #类的静态方法
            print('---------这是fun3---------')
        def func4(self):
            print('----------这是fun4---------')
    #类方法可以通过实例和类去访问yan.func2  实例方法只能通过实例去访问
    yan = MyClass()
    print(yan.attr)
    yan.func1
    yan.func2()
    MyClass.func2()
    yan.func3()
    MyClass.func3()
    yan.func4()
    
    
    人
    --------这是func1---------
    --------这是func2---------
    --------这是func2---------
    ---------这是fun3---------
    ---------这是fun3---------
    ----------这是fun4---------

    三、类装饰器

    类也可以做装饰器,但是需要定义 __call__ 方法

    # #类装饰器
    class Text(object):
    
        def __init__(self,fun):
            self.fun = fun
    
        def __call__(self, *args, **kwargs):
            print('装饰器的功能代码')
            self.fun()
    
    @Text
    def func():
        print('原来的功能代码')
    
    # func = Text(func)
    func()
    
    装饰器的功能代码
    原来的功能代码

    四、装饰器参考

    #查看函数运行时间:
    >>> import time
    >>> def run_time(func):
    ...     def new_fun(*args,**kwargs):
    ...             t0 = time.time()
    ...             print('star time: %s'%(time.strftime('%x',time.localtime())) )
    ...             back = func(*args,**kwargs)
    ...             print('end time: %s'%(time.strftime('%x',time.localtime())) )
    ...             print('run time: %s'%(time.time() - t0))
    ...             return back
    ...     return back
  • 相关阅读:
    sublime Text3插件无法安装解决方法(提示There are no packages available installation)
    扫码消费数量栏点击可编辑,失去焦点还原样式
    浏览器内核
    js全选checkbox框
    word-wrap: break-word;与word-break: break-all;文本自动换行
    含加减的输入框
    linux ,mac连接, git pull error, chmod修改文件的权限/chown修改文件和目录的所有者
    vue修改对象的属性值后页面不重新渲染
    jsp 判断时间大小
    利用js实现 禁用浏览器后退| 去除上一个历史记录链接
  • 原文地址:https://www.cnblogs.com/lyh-520/p/9296401.html
Copyright © 2020-2023  润新知