课后练习 第一阶段: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)