python 元类以及练习
'''
# 知识储备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 元类以及练习的更多相关文章
- python元类:type和metaclass
python元类:type和metaclass python中一切皆对象,所以类本身也是对象.类有创建对象的能力,那谁来创建类的呢?答案是type. 1.用tpye函数创建一个类 class A(ob ...
- Python 元类 - Metaclasses
Python 元类 - Metaclasses 默认情况下儿, classes 是有 type() 构造的. 类的结构体在一个新的 namespace 被执行, 类的名字 class name 绑定( ...
- Python进阶丨如何创建你的第一个Python元类?
摘要:通过本文,将深入讨论Python元类,其属性,如何以及何时在Python中使用元类. Python元类设置类的行为和规则.元类有助于修改类的实例,并且相当复杂,是Python编程的高级功能之一. ...
- python 元类
转载自 http://blog.jobbole.com/21351/ 类也是对象 在理解元类之前,你需要先掌握Python中的类.Python中类的概念借鉴于Smalltalk,这显得有些奇特.在大 ...
- [python]python元类
这两天在看Django框架,里面的filter实现原理搞不明白,最后发现跟python的元类有关系. 原文:http://stackoverflow.com/questions/100003/what ...
- Python元类实践--自己定义一个和collections中一样的namedtuple
大家可能很熟悉在collections模块中有一个很好用的扩展数据类型-namedtuple. 如果你还不知道这个类型,那么请翻看标准手册. 我利用元类轻松定义一个namedtuple. 先把代码贴上 ...
- python元类分析
刚開始接触到Python新式类中的元类的概念的时候非常是纠结了下..不知道这是个啥东西... 用下面几个定义来说明吧: (1)Python中,类也是对象..仅仅只是这样的对象比較的特殊,他用于创建别的 ...
- python元类理解2
恩,对元类理解又有新的收获,其实类似于装饰器,只不过装饰器是修饰函数,元类用来定制一个类. 代码如下,这是一个使用了函数做元类传递给类: input: def upper_attr(class_nam ...
- 3.python元类编程
1.1.propety动态属性 在面向对象编程中,我们一般把名词性的东西映射成属性,动词性的东西映射成方法.在python中他们对应的分别是属性self.xxx和类方法.但有时我们需要的属性需要根据 ...
- Python—元类
什么是元类? 元类是类的类,是类的模板 元类是用来控制如何创建类的,正如类是创建对象的模板一样,而元类的主要目的是为了控制类的创建行为 元类的实例化的结果为我们用class定义的类,正如类的实例为对象 ...
随机推荐
- Oracle 递归
当对象存在父节点.子节点时,通过特定的方式获取父节点.子节点数据构建树状结构或其它形式结构时,通常都会使用递归,如:一个公司有多个部门.每个部门下可能有多个小部门,小部门下面又有组-.为了数据容易 ...
- JS中关于位置和尺寸的api
HTMLElement.offsetParent 由于offsetTop 和 offsetLeft 都是相对于 offsetParent 内边距边界的,故offsetParent的意义十分重大.off ...
- windows cmd命令相关知识和经验的碎片化记录
1.循环遍历当前文件夹下的所有*.dll文件,并打印其绝对路径和相对路径 ``` for /f "tokens=*" %%a in ('dir /s/b/a-d "*.d ...
- MySQL 存储过程 -光标的使用
#四.光标的使用 #声明光标 语法:DECLARE 光标名字 CURSOR FOR sql语句 #打开光标 OPEN 光标名称 #使用光标 FETCH 光标名称 into ... #关闭光标 CLOS ...
- 39 编写一个函数,输入n为偶数时,调用函数求1/2+1/4+...+1/n,当输入n为奇数时,调用函数1/1+1/3+...+1/n(利用指针函数)
题目:编写一个函数,输入n为偶数时,调用函数求1/2+1/4+...+1/n,当输入n为奇数时,调用函数1/1+1/3+...+1/n(利用指针函数) public class _039PrintFu ...
- Windows Live Writer发布CSDN离线博客教程及测试
目前大部分的博客作者在用Word写博客这件事情上都会遇到以下3个痛点: 1.所有博客平台关闭了文档发布接口,用户无法使用Word,Windows Live Writer等工具来发布博客.使用Word写 ...
- Spark 0.9.1和Shark 0.9.1分布式安装指南
目录 目录 1 1. 约定 1 2. 安装Scala 1 2.1. 下载 2 2.2. 安装 2 2.3. 设置环境变量 2 3. 安装Spark 2 3.1. 部署 2 3.2. 下载 3 3.3. ...
- 编写高质量代码改善C#程序的157个建议——建议131:用PascalCasing命名公开元素
建议131:用PascalCasing命名公开元素 开放给调用者的属性.字段和方法都应该采用PascalCasing命名方法,比如: class Person { public string Firs ...
- 编写高质量代码改善C#程序的157个建议——建议82:Parallel简化但不等同于Task默认行为
建议82:Parallel简化但不等同于Task默认行为 建议81说到了Parallel的使用方法,不知道大家是否注意到文中使用的字眼:在同步状态下简化了Task的使用.也就是说,在运行Paralle ...
- WSAGetOverlappedResult函数
WSAGetOverlappedResult函数 通过WSAWaitForMultipleEvents函数来得到重叠操作完成的通知,那么自然也需要一个函数来查询一下重叠操作的结果,定义如下 BOOL ...