元类有关知识点补充


#类的名称空间 类的名称空间不能用类似字典的方法修改,例如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. Scala Symbol解释

    Symbol This class provides a simple way to get unique objects for equal strings. Since symbols are i ...

  2. 面试官:”准备用HashMap存1w条数据,构造时传10000会触发扩容吗?“

    通常在初始化 HashMap 时,初始容量都是根据业务来的,而不会是一个固定值,为此我们需要有一个特殊处理的方式,就是将预期的初始容量,再除以 HashMap 的装载因子,默认时就是除以 0.75. ...

  3. 动态引用存储——集合&&精确的集合定义——泛型

    1,集合宏观理解 1.1,为什么引入集合? 对于面向对象的语言来说,操作对象的功能不可或缺. 为了方便对对象进行操作和处理,就必须要对对象进行暂时的存储.[数据最终存在数据库里] 使用数组来存储对象的 ...

  4. 算法设计与分析(李春保)练习题答案v2

    ----------------------------------------------------- Page 1 --------------------------------------- ...

  5. 一次kuberneets evicted的历险

    一.概述 kubernetes 的eviction检测diskpresure,检测的是kubelet的root-dir.kubelet的默认root-dir是/var/lib/kubelet,可以使用 ...

  6. JavaIO学习:序列化流

    对象流 1.涉及到的类 ObjectInputStream 和 ObjectOutputStream 用于存储和读取基本数据类型数据或对象的处理流. 2.作用 ObjectOutputStream:内 ...

  7. pod的yaml说明

    apiVersion: v1 #指定api版本,此值必须在kubectl apiversion中 kind: Pod #指定创建资源的角色/类型 metadata: #资源的元数据/属性 name: ...

  8. golang学习笔记 go 相关命令

    go build 命令一些可选项的用途和用法 在运行go build命令的时候,默认不会编译目标代码包所依赖的那些代码包.当然,如果被依赖的代码包的归档文件(*.a)不存在,或者源码文件有了变化,那么 ...

  9. vs 发版时,在发版的文件夹中,找不到应该有的某个文件

    检查:VS中,这个文件右击属性,查看生成操作.如果是“无”,改为“内容”.再重新发布就没问题了. 想看发版出来的内容包括哪些,可以从“发布”--“应用程序文件”查看

  10. 用SWFUpload上传图片小例子

    在开发项目中,经常会用到上传图片,接下来我就用一种简单的方式给大家分享一下使用SWFUpload的方式上传图片. 1.在网站根目录下新建一个SWFUpload文件夹,把下载的组建放在SWFUpload ...