元类有关知识点补充


#类的名称空间 类的名称空间不能用类似字典的方法修改,例如School类里面有name属性xxx,那么我用School.__dict__[‘name’] = ‘yyy’就会报错“TypeError: 'mappingproxy' object does not support item assignment”原因是类的名称空间和对象的名称空间不一样,后者是一个`a plain dict`,就是普通的字典,而后者是一个`mappingproxy`,不可映射类型,是不含__setattr__方法的 #class底层原理的实现
Person = type('Person', (object,), {}) def __init__(self, name, age):
self.name = name
self.age = age
p = type('Person', (object, ), {'x': 1, '__init__': __init__})
p1 = p('ljy', 19) class Person:
x = 1
def __init__(self, name, age):
self.name = name
self.age = age
p = Person
q = p('ljy', 18)
print(p.__dict__)
print(q.__dict__) # exec : 执行字符串的代码,当成python解释器 ss = '''
global x #全局变量要加在最前面
x = 1
y = 2
z = 3 print(y) '''
g = {}
l = dict()
exec(
ss, g, l
) print(print(1)) #会打印出1,和None,因为print的返回值是None print(l) # 先把y=2打印出来,然后再打印局部变量的字典
print(g) #打印全部变量的字典,里面包含x:2,在字典的末尾 # 自定义元类,继承type class Mymeta(type):
def __init__(self, name, bases, dic):
#self 是Person这个类(对象)
#在这个位置,其实self也就是Person这个类,
#内部已经有东西了,名称空间里面的东西在__new__
#可以通过过dic来判断名称空间,也可以直接通过
#self.__dict__/self.属性 来判断
a = dic.get('name')
if not a:
raise Exception('没有name属性,不能创建')
def __call__(self, *args, **kwargs):
pass # class Person(metaclass = Mymeta):
'''
Person = Mymeta('Person', (object,), {...})
Mymete类实例化,会把三个参数传到Mymeta的__init__方法中
''' class PersonException(metaclass=Mymeta):
name = 'lae'#加上这句话,类的名称空间里面就有name属性了
def __init__(self,name,age):
self.name = name
self.age = age
#通过元类控制类的调用过程,实例化产生对象的过程
p1 = PersonException(18)
#因为类中没有name属性,所以会抛异常‘没有name属性,不能创建’ class Person():
def __init__(self, name):
self.name = name
raise Exception('就不让你创建') p = Person('nick')
# 自动触发Person类__init__的执行,
# 抛异常:就不让你创建
# 总结:可以通过自定义元类,重写__init__方法来控制类的产生 class Mymeta(type):
def __init__(self, name, bases, dic):
if 'name' not in dic.keys():
raise Exception('没有name属性,不能创建')
else:
self.__dict__['name'] = 'nick'
'''
会报错TypeError: 'mappingproxy'
object does not support item assignment
也就是类的名称空间是一个字典,但是不能对里面的值进行修改
(错误详情见下一篇博客整理)
''' class Person(metaclass=Mymeta):
name = 'ljy'
def __init__(self, name, age):
self.name = name
self.age = age
p = Person('ljy', 19)
print(p.name)
print(Person.name) class Mymeta(type):
def __call__(self, *args, **kwargs):
#该方法必须返回一个对象(类对象),
# 这个地方返回什么, p=Person('lqz')
#p就是什么
#返回一个真正的Person类的对象
#第一步:产生一个空对象
# object.__new__(self)
# 传一个参数,传类,就会产生一个该类的空对象 #obj是Person类的空对象
obj = object.__new__(self) # print(self.__new__ is object.__new__)
#打印结果是True,说明
# self.__new__就是object.__new__ #第二步:初始化该对象,把初始值放到对象中
#obj是Person类的空对象,obj.__init__ 调
# 用自己的绑定方法,也就是说Person类中写的
# __init__方法
obj.__init__(*args, **kwargs)
#还可以类来调用
Person.__init__(obj, *args, **kwargs)
self.__init__(obj, *args, **kwargs)
print(obj.name) #打印出来lqz
#第三步:把该对象返回
return obj
class Person(metaclass=Mymeta):
def __init__(self, name):
self.name = name
def __call__(self, *args, **kwargs):
print('XXXX')
p = Person('lqz')
print(p.name)
print(p)

单例模式

一共有23中设计模式,单例模式是指整个过程中只有一个实例,所有生成的实例都指向同一快内存空间

PORT = '192.384.28.2'
HOST = 2728
#方式一:通过类的绑定方法
#当用户不输入端口和地址,每次拿到的对象都是同一个。
class Sql:
_instance = None
def __init__(self, port, host):
self.port = port
self.host = host
@classmethod
def singleton(cls):
if not cls._instance:
cls._instance = cls(PORT, HOST)
return cls._instance
p1 = Sql.singleton()
p2 = Sql.singleton()
p3 = Sql('33306','192.168.1.1')#当用户输入端口和地址,实例化产生新对象
print(p1)
print(P2)
print(p3)
'''
<__main__.Sql object at 0x00000225BDBABFD0>
<__main__.Sql object at 0x00000225BDBABFD0>
<__main__.Sql object at 0x00000225BDBABF98>
''' ##方式二:通过装饰器
#不传参,实例化对象内存地址相同
def get_singleton(cls):
_instance = None
def inner(*args, **kwargs):
if len(args)!=0 or len(kwargs)!=0:
res = cls(*args, **kwargs)
return res
else:
nonlocal _instance
if not _instance:
_instance = cls(PORT, HOST)
return _instance
return inner @get_singleton
class Sql:
def __init__(self, port, host):
self.port = port
self.host = host
s1=Sql()
s2=Sql()
s3=Sql('33306','192.168.1.1') #传参,实例化对象地址不同
print(s1)
print(s2)
print(s3)
'''
<__main__.Sql object at 0x00000185E9601978>
<__main__.Sql object at 0x00000185E9601978>
<__main__.Sql object at 0x00000185F04CE2B0>
''' #方法三:用自定义元类
#不传参,实例化对象内存地址相同
class Mymeta(type):
def __init__(cls, name, bases, dic):
cls._instance = cls(PORT, HOST)
def __call__(cls, *args, **kwargs):
if len(args)!=0 or len(kwargs)!=0:
obj = object.__new__(cls)
obj.__init__(*args, **kwargs)
return obj
else:
return cls._instance
class Sql(metaclass=Mymeta):
def __init__(self, port, host):
self.port = port
self.host = host
p1 = Sql()
p2 = Sql()
p3 = Sql(8001, '178.23.4.53')#传参,实例化对象地址不同
print(p1)
print(p2)
print(p3)
"""
<__main__.Sql object at 0x000002469196E320>
<__main__.Sql object at 0x000002469196E320>
<__main__.Sql object at 0x000002469196E438> """ #方法四:导入模块
#singleton.py
class Sql():
def __init__(self, port, host):
self.port = port
self.host = host s1 = Sql(PORT, HOST) #test.py
def test1():
from singleton import s1
print(s1)
def test2():
from singleton import s1
print(s1) test1()
test2()
from singleton import s1
from singleton import Sql
s2 = Sql(477, '182.22.2.2')
print(s1)
print(s2) '''
<sigonleton.Sql object at 0x000001B0456F53C8>
<sigonleton.Sql object at 0x000001B0456F53C8>
<sigonleton.Sql object at 0x000001B0456F53C8>
<sigonleton.Sql object at 0x000001B045B3F080> '''

面向对象高级C(元类补充及单例模式)的更多相关文章

  1. CSIC_716_20191129【面向对象高级----反射、类的内置方法(魔法方法)、单例模式】

    反射 反射是通过'字符串'对 对象的属性进行操作,反射有四个内置的方法. hasattr 通过字符串 判断对象的属性或者方法是否存在 getattr 通过字符串  获取对象的属性或者方法        ...

  2. python 面向对象进阶之元类metaclass

    一:知识储备 exec exec:三个参数 参数一:字符串形式的命令 参数二:全局作用域(字典形式),如果不指定,默认为globals() 参数三:局部作用域(字典形式),如果不指定,默认为local ...

  3. Python面向对象篇之元类,附Django Model核心原理

    关于元类,我写过一篇,如果你只是了解元类,看下面这一篇就足够了. Python面向对象之类的方法和属性 本篇是深度解剖,如果你觉得元类用不到,呵呵,那是因为你不了解Django. 在Python中有一 ...

  4. C++面向对象高级编程(五)类与类之间的关系

    技术在于交流.沟通,转载请注明出处并保持作品的完整性. 本节主要介绍一下类与类之间的关系,也就是面向对象编程先介绍两个术语 Object Oriented Programming   OOP面向对象编 ...

  5. 【转】python面向对象中的元类

    type() 动态语言和静态语言最大的不同,就是函数和类的定义,不是编译时定义的,而是运行时动态创建的. 比方说我们要定义一个Hello的class,就写一个hello.py模块: class Hel ...

  6. exec , 元类,__new__, __call__ , 单例模式 , 异常

    1,类也是对象 ''' 动态语言 可以在运行期间 动态生成类 修改对象属性 静态语言 ''''' ''' type(object_or_name, bases, dict) type(object) ...

  7. [Python之路] 元类(引申 单例模式)

    一.类也是对象 当我们定义一个变量或者函数的时候,我们可以在globals()的返回值字典中找到响应的映射: def A(): print("This is function A" ...

  8. python 面向对象编程 之 元类

    元类是类的类,使我们自定义的类,即我们用class定义类本质就是元类,是类的模板 四步走: 一:控制class定义类的过程 1.先拿到类名 2.在拿到基类 3.执行类体代码,得到名称空间的dict 4 ...

  9. python 面向对象十二 元类

    一.类也是对象 只要使用关键字class,Python解释器在执行的时候就会创建一个对象.下面的代码段: class ObjectCreator(object): pass 将在内存中创建一个对象,名 ...

随机推荐

  1. QSS文件美化界面无效

    问题描述: 同样的qss内容,内置有效,写进qss文件加载无效. 搜寻.........很多网友的经理是qss文件编码和qt文本编辑器的属性........而我怎么尝试,怎么失败. 解决方案: 从fi ...

  2. Ubuntu 14.04 apt-get update失效解决(转)

    现象如下: VirtualBox:~$ sudo apt-get update Err http://mirrors.aliyun.com trusty InRelease Err http://mi ...

  3. Java中HashMap和TreeMap的区别

    什么是Map集合在数组中我们是通过数组下标来对其内容索引的,而在Map中我们通过对象来对对象进行索引,用来索引的对象叫做key,其对应的对象叫做value.这就是我们平时说的键值对. HashMap ...

  4. SpringCloud-ZUUL网关Cookie被拦截

    在application.properties文件中添加配置(注意后面的值为空) zuul.sensitiveHeaders= org.springframework.cloud.netflix.zu ...

  5. base62与long的相互转换

    public static class Converter { private static String keys = "0123456789abcdefghijklmnopqrstuvw ...

  6. SpringBoot第十篇:thymeleaf详解

    作者:追梦1819 原文:https://www.cnblogs.com/yanfei1819/p/10931435.html 版权声明:本文为博主原创文章,转载请附上博文链接! 引言   Sprin ...

  7. Docker remote API

    Docker remote API 该教程基于Ubuntu或Debian环境,如果不是,请略过本文 Docker API 在Docker生态系统中一共有三种API Registry API:提供了与来 ...

  8. Git拉取远程分支命令

    如果我们想从Git仓库中拉取一个分支到本地,此处假如远程分支为develop,本地要创建的分支为dev,可以使用以下命令: git init    //初始化本地Git仓库 git remote ad ...

  9. C#4.0的十种语法糖

    https://www.cnblogs.com/dotnet261010/p/6055092.html

  10. Service Mesh服务网格新生代--Istio

    原文: 数人云|万字解读:Service Mesh服务网格新生代--Istio 参考: istio 简介 Istio是啥?一文带你彻底了解! 使用Istio治理微服务入门 Istio 流量管理 ist ...