课后练习 第一阶段:Python开发基础 day30 面向对象--单例模式实例

day30 课后作业

1.在元类中控制把自定义类的数据属性都变成大写

class MyMeta(type):
    def __new__(cls,name,bases,attr):
        dic = {}
        for k,v in attr.items():
            if not k.startswith('__'):
                dic[k.upper()] = v
            else:
                dic[k] = v
        return type.__new__(cls,name,bases,dic)

class Demo(metaclass=MyMeta):
    name = 'forever'
    age = 18

print(Demo.__dict__)

2.在元类中控制自定义的类无需init方法

class MyMeta(type):
    def __call__(self, *args, **kwargs):
        obj = object.__new__(self)
        for k,v in kwargs.items():
            obj.__dict__[k] = v
        return obj

class Demo(metaclass=MyMeta):
    name = 'forever'
    age = 18

demo = Demo(name = 'forever',age = 18)
print(demo.__dict__)

3.在元类中控制,把自定义的类的属性都放到attr字典中

class MyMeta(type):
    def __new__(cls,name,bases,attr):
        dic = {'attr':{}}

        for k,v in attr.items():
            if not k.startswith('__'):
                dic['attr'][k] = v
            else:
                dic[k] = v
        return type.__new__(cls,name,bases,dic)

class Demo(metaclass=MyMeta):
    name = 'forever'
    age = 18

print(Demo.__dict__)

4.四种方式实现单例模式

  • 第一种(通过类的绑定方法)

    dic = {'PORT':3306,'HOST':'127.0.0.1'}
    class Demo1():
        _instance = None
        def __init__(self,port,host):
            self.port = port
            self.host = host
    
        @classmethod
        def get_sigoleton(cls):
            if not cls._instance:
                cls._instance = cls(dic['PORT'],dic['HOST'])
            return cls._instance
    
    s1 = Demo1.get_sigoleton()
    s2 = Demo1.get_sigoleton()
    s3 = Demo1(33306,'192.168.1.1')
    print(s1)
    print(s2)
    print(s3)
    
  • 第二种(通过装饰器)

    • 用户输入端口和地址,实例化产生对象

    • 当用户不输入端口和地址,每次拿到的对象,都是同一个

    dic = {'PORT':3306,'HOST':'127.0.0.1'}
    def get_sigoleton(cls):
        _instance=None
        def wrapper(*args,**kwargs):
            if len(args)!=0 or len(kwargs)!=0:
                #表示传了参数,生成新对象
                res=cls(*args,**kwargs)
                return res
            else:
                nonlocal _instance
                if not _instance:
                    _instance=cls(dic['PORT'], dic['HOST'])
                return _instance
        return wrapper
    
    @get_sigoleton    #会把下面的Sql当中参数传入,相当于:Sql=get_sigoleton(Sql)
    class Sql():
        def __init__(self,port,host):
            self.port=port
            self.host=host
    s1=Sql()
    s2=Sql()
    s3=Sql('33306','192.168.1.1')
    s4=Sql('33306','192.168.1.1')
    print(s1)
    print(s2)
    print(s3)
    
  • 第三种(通过元类)

    • 当用户输入端口和地址,实例化产生新对象
    • 当用户不输入端口和地址,每次拿到的对象,都是同一个
    dicc = {'PORT':'3306','HOST':'127.0.0.1'}
    class Mymeta(type):
        def __init__(self,name,bases,dic):
            #self 是Sql类
    
            #把实例化好的对象,放到了类的名称空间
            self._instance=self(dicc['PORT'], dicc['HOST'])
        def __call__(self, *args, **kwargs):
            #self是谁?是Sql类
            if len(args)!=0 or len(kwargs)!=0:
                obj=object.__new__(self)
                obj.__init__(*args, **kwargs)
                return obj
            else:
                return self._instance
    
    class Sql(metaclass=Mymeta):    #相当于 Sql=Mymeta(name,bases,dic)   这个会调用 Mymeta的__init__  在里面已经向类的名称空间放了一个对象
        def __init__(self,port,host):
            self.port=port
            self.host=host
    
    print(Sql.__dict__)
    s1=Sql()
    #调用元类的__call__
    s2=Sql()
    s3=Sql('33306','192.168.1.1')
    print(s1)
    print(s2)
    print(s3)
    
  • 第四种(通过模块导入:python中的模块是天然的单例)

    def test():
        from sigonleton import s1
        print(s1.port)
        print(s1)
    def test2():
        from sigonleton import s1 as s2
        print(s2)
    
    test()
    test2()
    from sigonleton import s1
    from sigonleton import Sql
    s2=Sql(3306,'192.168.1.1')
    print(s1)
    print(s2)
    
    # 被调用的 sigonleton.py文件
    def test():
        from sigonleton import s1
        print(s1.port)
        print(s1)
    def test2():
        from sigonleton import s1 as s2
        print(s2)
    
    test()
    test2()
    from sigonleton import s1
    from sigonleton import Sql
    s2=Sql(3306,'192.168.1.1')
    print(s1)
    print(s2)
    
posted @ 2019-09-04 22:38  foreversun92  阅读(192)  评论(0编辑  收藏  举报