'''
# 知识储备exec()
# 参数1:字符串形式的命令
# 参数2:全局作用域(字典形式),如果不指定默认就使用globals()
# 参数3:局部作用域(字典形式),如果不指定默认就使用locals()
'''
# g = {
# 'x': 2,
# 'y': 4
# }
# l = {}
# exec('''
# global x, m
# x = 10
# m = 100
#
# z = 3
# ''', g, l)
# print(g)
# print(l)
'''一切皆对象,元类(产生类的类叫元类,默认用class定义的类,他们的元类是type)'''
# 一切皆对象,对象可以怎么用?
# 1.都可以被引用,x = obj
# 2.都可以当做函数的参数传入
# 3.都可以当作函数的返回值
# 4.都可以当做容器类型的元素,l = [func, time, obj, l] # # 类也是对象,Foo = type(...)
# class Foo:
# pass
# obj = Foo()
# print(type(obj))
# print(type(Foo))
# #产生类的类叫元类,默认用class定义的类,他们的元类是type
'''定义类'''
# 方式一class
# class Chinese:
# country = 'china'
# def __init__(self, name):
# self.name = name
# def talk(self):
# print('%s is talking' % self.name)
# print(Chinese)
# 方式二type
#定义类三要素 类名,类的基类, 类的名称空间
# class_name = 'Chinese'
# class_bases = (object,)
# class_body = '''
# country = 'china'
# def __init__(self, name):
# self.name = name
# def talk(self):
# print('%s is talking' % self.name)
# '''
# class_dic = {}
# exec(class_body, globals(), class_dic)
# # print(class_dic)
#
# Chinese1 = type(class_name, class_bases, class_dic)
# print(Chinese1)
'''自定义元类控制类的创建'''
# class Mymeta(type):
# def __init__(self, class_name, class_bases, class_dic):
# if not class_name.istitle():
# raise TypeError('类名首字母必须大写')
# if '__doc__' not in class_dic or not class_dic['__doc__'].strip():
# raise TypeError('必须有注释,且注释不能为空')
# super(Mymeta, self).__init__(class_name, class_bases, class_dic)
# class Chinese(object, metaclass = Mymeta):
# '''
# 国人
# '''
# country = 'china'
# def __init__(self, name):
# self.name = name
# def talk(self):
# print('%s is talking' % self.name)
# c = Chinese('name')
# # Chinese = type(class_name, class_bases, class_dic)
'''知识储备__call__方法'''
# class Foo:
# def __call__(self, *args, **kwargs):
# print(self)
# print(args)
# print(kwargs)
# obj = Foo()
# obj(1, 2, 3, a=1, b=2, c=3) # 元类内部也应该有一个__call__方法,会在调用Foo时触发执行
'''自定义元类控制类的实例化行为'''
# class Mymeta(type):
# def __init__(self, class_name, class_bases, class_dic):
# if not class_name.istitle():
# raise TypeError('类名首字母必须大写')
# if '__doc__' not in class_dic or not class_dic['__doc__'].strip():
# raise TypeError('必须有注释,且注释不能为空')
# super(Mymeta, self).__init__(class_name, class_bases, class_dic)
# def __call__(self, *args, **kwargs):
# # print(self)
# # print(args)
# # print(kwargs)
# # 第一件事,造一个空对象
# obj = object.__new__(self)
# # 第二件事,初始化
# self.__init__(obj, *args, **kwargs)
# # 第三件事,返回obj
# return obj
# class Chinese(object, metaclass = Mymeta):
# '''
# 国人
# '''
# country = 'china'
# def __init__(self, name):
# self.name = name
# def talk(self):
# print('%s is talking' % self.name)
# obj = Chinese('xander') # Chinese.__call__(Chinese, 'xander')
# print(obj.__dict__)
'''自定义元类控制类的实例化行为的应用'''
# 单例模式 # 实现方式一:
# class MySQL:
# __instance = None
#
# def __init__(self):
# self.host = '127.0.0.1'
# self.port = 3306
# @classmethod
# def singleton(cls):
# if not cls.__instance:
# obj = cls()
# cls.__instance = obj
# return cls.__instance
# # obj1 = MySQL()
# # obj2 = MySQL()
# # print(obj1)
# # print(obj2)
# obj1 = MySQL.singleton()
# obj2 = MySQL.singleton()
# print(obj1 is obj2) # 实现方式二:元类的方式
class Mymeta(type):
def __init__(self, class_name, class_bases, class_dic):
if not class_name.istitle():
raise TypeError('类名首字母必须大写')
if '__doc__' not in class_dic or not class_dic['__doc__'].strip():
raise TypeError('必须有注释,且注释不能为空')
super(Mymeta, self).__init__(class_name, class_bases, class_dic)
self.__instance = None
def __call__(self, *args, **kwargs):
if not self.__instance:
obj = object.__new__(self)
self.__init__(obj)
self.__instance = obj
return self.__instance
class Mysql(object, metaclass=Mymeta):
'''单例模式'''
def __init__(self):
self.host = '127.0.0.1'
self.port = 3306
@classmethod
def singleton(cls):
if not cls.__instance:
obj = cls()
cls.__instance = obj
return cls.__instance
obj1 = Mysql()
obj2 = Mysql()
print(obj1 is obj2)

练习

# 练习一:在元类中控制把自定义类的数据属性都变成大写
class Mymate(type):
def __new__(cls, name, args, kwargs):
obj = {}
print(name)
print(args)
print(kwargs)
for a, b in kwargs.items():
if not a.startswith('__'):
obj[a.upper()] = b
else:
obj[a] = b
return type.__new__(cls, name, args, obj)
class Chinese(object, metaclass=Mymate):
country = 'chinese'
def talk(self):
print('is talking')
print(Chinese.__dict__) # 练习二:在元类中控制自定义的类无需init方法
# 1.元类帮其完成创建对象,以及初始化操作;
# 2.要求实例化时传参必须为关键字形式,否则抛出异常TypeError: must use keyword argument
# 3.key作为用户自定义类产生对象的属性,且所有属性变成大写
class Mymate(type):
def __call__(self, *args, **kwargs):
if args:
raise TypeError(':must use keyword argument')
obj = object.__new__(self) #创建对象,self为类Chinese for k, v in kwargs.items():
obj.__dict__[k.upper()] = v
return obj class Chinese(object, metaclass=Mymate):
country = 'chinese'
def talk(self):
print('is talking')
p = Chinese(name='egon', age=18, sex='male')
print(p.__dict__)

python 元类以及练习的更多相关文章

  1. python元类:type和metaclass

    python元类:type和metaclass python中一切皆对象,所以类本身也是对象.类有创建对象的能力,那谁来创建类的呢?答案是type. 1.用tpye函数创建一个类 class A(ob ...

  2. Python 元类 - Metaclasses

    Python 元类 - Metaclasses 默认情况下儿, classes 是有 type() 构造的. 类的结构体在一个新的 namespace 被执行, 类的名字 class name 绑定( ...

  3. Python进阶丨如何创建你的第一个Python元类?

    摘要:通过本文,将深入讨论Python元类,其属性,如何以及何时在Python中使用元类. Python元类设置类的行为和规则.元类有助于修改类的实例,并且相当复杂,是Python编程的高级功能之一. ...

  4. python 元类

    转载自  http://blog.jobbole.com/21351/ 类也是对象 在理解元类之前,你需要先掌握Python中的类.Python中类的概念借鉴于Smalltalk,这显得有些奇特.在大 ...

  5. [python]python元类

    这两天在看Django框架,里面的filter实现原理搞不明白,最后发现跟python的元类有关系. 原文:http://stackoverflow.com/questions/100003/what ...

  6. Python元类实践--自己定义一个和collections中一样的namedtuple

    大家可能很熟悉在collections模块中有一个很好用的扩展数据类型-namedtuple. 如果你还不知道这个类型,那么请翻看标准手册. 我利用元类轻松定义一个namedtuple. 先把代码贴上 ...

  7. python元类分析

    刚開始接触到Python新式类中的元类的概念的时候非常是纠结了下..不知道这是个啥东西... 用下面几个定义来说明吧: (1)Python中,类也是对象..仅仅只是这样的对象比較的特殊,他用于创建别的 ...

  8. python元类理解2

    恩,对元类理解又有新的收获,其实类似于装饰器,只不过装饰器是修饰函数,元类用来定制一个类. 代码如下,这是一个使用了函数做元类传递给类: input: def upper_attr(class_nam ...

  9. 3.python元类编程

     1.1.propety动态属性 在面向对象编程中,我们一般把名词性的东西映射成属性,动词性的东西映射成方法.在python中他们对应的分别是属性self.xxx和类方法.但有时我们需要的属性需要根据 ...

  10. Python—元类

    什么是元类? 元类是类的类,是类的模板 元类是用来控制如何创建类的,正如类是创建对象的模板一样,而元类的主要目的是为了控制类的创建行为 元类的实例化的结果为我们用class定义的类,正如类的实例为对象 ...

随机推荐

  1. VMware联网问题

    VMware 服务启动优化当虚拟机连不上网,或不显示ip时,先查看vm服务是否启动.控制台运行:services.msc 以下为改为手工启动:1.VMware 服务自动启动影响计算机启动速度,再此对V ...

  2. jdk、jre、jvm的区别联系

    jdk包括以下三个东西: D:\Program Files\jdk1.7.0_21\bin\javac.exe和java.exe D:\Program Files\jdk1.7.0_21\jre D: ...

  3. PCA 学习笔记

    先简单记下,等有时间再整理 PCA 主要思想,把 协方差矩阵 对角化,协方差矩阵是实对称的.里面涉及到矩阵论的一点基础知识: 基变换: Base2 = P · Base1 相应的 坐标变换 P · c ...

  4. html传参数 js工具类

    var QueryUtils = { GetQueryString: function (name) { var reg = new RegExp("(^|&)" + na ...

  5. git post-receive

    1. 将 www 目录设为 777 2. 用git 用户 mkdir 并 git init 3. cat  id_rsa.pub >. authorkeys

  6. sql server锁检测

    有时候系统运行老感觉效率不高,并且有时候sql还有超时的报错,但是并发量并不高.通过排查定位sql是否有执行效率问题 -- 开事务, 以保持锁 BEGIN TRAN -- 更新 update tabl ...

  7. GitHub 出现这样的问题怎么办

    一开始以为是被墙,憋个半死. 后来自己好了(大概过了一上午),虚惊一场.

  8. Currying and Uncurrying Js

    //反科里化Function.prototype.uncurrying = function() { var _this = this; return function() { return Func ...

  9. 多线程“尚未调用coinitialize” 报错

    关于多线程中创建使用TADOConnect.TADODataSet等Com组件时,必须先初始化Com 在多线程启用执行前 CoInitialize(nil); 在多线程启用执行后 CoUninitia ...

  10. 解决Struts2拦截器的对于参数传递无效问题

    今天做项目时,使用拦截器对用户权限检查.拦截器本身没有问题,可是实现权限拦截,但是传递的参数全部都无效了.搞了很久,由于对拦截器的内部机制不是特别熟悉,所以重新研读了一下Struts2的拦截器.找到了 ...