元类有关知识点补充


#类的名称空间 类的名称空间不能用类似字典的方法修改,例如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. Jena Fuseki安装完成后不能添加数据库

    问题描述:安装Jena成功后可以进入管理页面,无法通过界面选择和查询数据 解决方案: 进入 apache-jena-fuseki-3.12.0\run 修改 shiro.ini 配置文件 注释 /$/ ...

  2. Java中json使用与问题汇总

    一.JSON 解析类库 FastJson: 阿里巴巴开发的 JSON 库,性能十分优秀. 在maven项目的pom文件中以下依赖 <dependency> <groupId>c ...

  3. UVA 10924 Prime Words 题解

    Prime Words A prime number is a number that has only two divisors: itself and the number one. Exampl ...

  4. bean的shutdown

    使用@Bean注解,在不配置destroyMethod时,其默认值为: String destroyMethod() default AbstractBeanDefinition.INFER_METH ...

  5. 《 .NET并发编程实战》阅读指南 - 第10章

    先发表生成URL以印在书里面.等书籍正式出版销售后会公开内容.

  6. 【docker】centos7 上拉取docker镜像,一直拉取不到,报错:Error response from daemon: Get https://registry-1.docker.io/v2/: net/http: request canceled while w

    镜像拉取一直报错: Error response from daemon: Get https://registry-1.docker.io/v2/: net/http: request cancel ...

  7. Storm 系列(九)—— Storm 集成 Kafka

    一.整合说明 Storm 官方对 Kafka 的整合分为两个版本,官方说明文档分别如下: Storm Kafka Integration : 主要是针对 0.8.x 版本的 Kafka 提供整合支持: ...

  8. SQLServer之列数据转换为行数据

    UNPIVOT特点 UNPIVOT运算符通过将列旋转到行来执行PIVOT的反向操作,UNPIVOT 并不完全是 PIVOT 的逆操作. PIVOT 执行聚合,并将多个可能的行合并为输出中的一行.UNP ...

  9. 我是如何一步步编码完成万仓网ERP系统的(五)产品库设计 1.产品类别

    https://www.cnblogs.com/smh188/p/11533668.html(我是如何一步步编码完成万仓网ERP系统的(一)系统架构) https://www.cnblogs.com/ ...

  10. Flutter实体与JSON解析的一种方法

    vs code作为编辑器 1. 首先,json对象与字符串的转换是使用json.encode和json.decode的,需要导入import 'dart:convert'; 这里主要的自然不是这个,而 ...