【引子】

  虽然我们可以通过“class”语句来定义“类”,但是要想更加细粒度的控制“类”的创建,要使用元类编程才能实现。

  比如说我们要实现这样的一个约束、所有项目中用到的类都应该要为它定义的方法提供文档字符字符串。有两条可行

  的路径 1):依赖工程师的自觉、自律 让他们在定义每一个方法的时候都为方法增加文档字符串, 2):通过元类来做一些

  控制,如果工程师没有为方法提供文档字符,那么就直接报错,直到工程师为方法提供字符串为止。

【实现1】

  依赖工程师的自觉、自律为方法增加文档字符串

class Person(object):
name = None
def __init__(self,name):
self.name=name def say_hello(self):
"""
print hello My name is xxx ...
"""
print("hello My name is {self.name}".format(self=self))

  我们如何能保证每一个方法都增加了文档字符串呢?我一方面要依靠“自觉”另一方面要依靠“纪律性”,最好要有专门的人来做代码

  审核。

【实现2】

  通过元类来实现这个约束

  第一步:定义一个元类来审核class

class DocMeta(type):
"""
检查方法是否有提供文档字符串
"""
def __init__(self,name,base,attrs):for key,value in attrs.items():
if key.startswith('__'):
#跳过魔术方法
continue
if not hasattr(value,"__call__"):
#跳过字段
continue
#如果能进入到这里、那么一定是方法了、于是检查方法有没有文档字符串.
if not getattr(value,"__doc__"):
#没有文档字符串的情况下就报错
raise TypeError("{0} must have a docstring".format(key))
super().__init__(name,base,attrs)

  

  第二步:定义一个通用的基类、以后所有要实现这一约束的类都继承自它

class Documented(metaclass=DocMeta):
pass

  注意这个项的元类是我们刚才定义的“DocMeta”类

  第三步:让项目中的类继承自这个基类

class Person(Documented):
name = None
def __init__(self,name):
self.name=name def say_hello(self):
"""
print hello My name is xxx ...
"""
print("hello My name is {self.name}".format(self=self))

  

  第四步:和使用普通的类一样使用Person类

if __name__=="__main__":
p = Person("welson")
p.say_hello() #hello My name is welson

【总结】

  以上代码由于在say_hello 方法中提供了文档字符串、如果没有提供的话、在创建Person类的时候就会报错了

Traceback (most recent call last):
File "main.py", line 31, in <module>
class Person(Documented):
File "main.py", line 24, in __init__
raise TypeError("{0} must have a docstring".format(key))
TypeError: say_hello must have a docstring

  全部代码如下:

"""
Python元类编程的一个例子
""" __version__ = '0.1'
__author__ = '蒋乐哥哥' class DocMeta(type):
"""
检查方法是否有提供文档字符串
"""
def __init__(self,name,base,attrs):
for key,value in attrs.items():
if key.startswith('__'):
#路过魔术方法
continue
if not hasattr(value,"__call__"):
#跳过字段
continue
#如果能进入到这里、那么一定是方法了、于是检查方法有没有文档字符串.
if not getattr(value,"__doc__"):
#没有文档字符串的情况下就报错
raise TypeError("{0} must have a docstring".format(key))
super().__init__(name,base,attrs) class Documented(metaclass=DocMeta):
pass class Person(Documented):
name = None
def __init__(self,name):
self.name=name def say_hello(self):
"""
print hello My name is xxx ...
"""
print("hello My name is {self.name}".format(self=self)) # 在不为方法提供文档字符串的情况下会直接报错
#class Person(Documented):
# name = None
# def __init__(self,name):
# self.name=name
#
# def say_hello(self):
# print("hello My name is {self.name}".format(self=self)) if __name__=="__main__":
p = Person("welson")
p.say_hello()

----------------------------------------

python3 元类编程的一个例子的更多相关文章

  1. Python 元类编程实现一个简单的 ORM

    概述 什么是ORM? ORM全称"Object Relational Mapping",即对象-关系映射,就是把关系数据库的一行映射为一个对象,也就是一个类对应一个表,这样,写代码 ...

  2. Python进阶开发之元类编程

    系列文章 √第一章 元类编程,已完成 ; 本文目录 类是如何产生的如何使用type创建类理解什么是元类使用元类的意义元类实战:ORM . 类是如何产生的 类是如何产生?这个问题肯定很傻.实则不然,很多 ...

  3. Python元类编程

    来源:http://python.jobbole.com/88582/ @property装饰器,是将类中的函数当做属性调用 Python类中定义的属性,如果属性名前面只有一个下划线,那么就是一种规范 ...

  4. PythonI/O进阶学习笔记_7.python动态属性,__new__和__init__和元类编程(上)

    content: 上: 1.property动态属性 2.__getattr__和__setattr__的区别和在属性查找中的作用 3.属性描述符 和属性查找过程 4.__new__和__init__ ...

  5. python的元类编程

    廖雪峰的python教程有python元类编程示例,综合代码如下 https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df ...

  6. 元类理解与元类编程 《Python3网络爬虫开发》中第九章代理的使用代码Crawler中代码的理解

    __new__与__init__的理解 __new__()方法是在创建实例之前被调用的,它的作用是创建一个实例,然后返回该实例对象,它是一个静态方法. __init__() 当实例被创建完成之后被调用 ...

  7. 3.python元类编程

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

  8. gj8 元类编程

    8.1 property动态属性 from datetime import date, datetime class User: def __init__(self, name, birthday): ...

  9. 元类编程-- metaclass

    #类也是对象,type创建类的类 def create_class(name): if name == "user": class User: def __str__(self): ...

随机推荐

  1. SSH小问题:WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!

    @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @ WARNING: REMOTE HOST IDENTIFICATION HA ...

  2. Android学习笔记四:activity的四种启动模式

    Activity有四种启动模式:standard,singleTop,singleTask,singleInstance. 1.standard:标准启动模式 默认模式,这个模式下启动的Activit ...

  3. Java继承Exception自定义异常类教程以及Javaweb中用Filter拦截并处理异常

    转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/6403033.html 在项目中的应用见: https://github.com/ygj0930/CoupleS ...

  4. spring & java 面试

    https://blog.csdn.net/u014079773/article/details/52453002 1.Spring中AOP的应用场景.Aop原理.好处? 答:AOP--Aspect ...

  5. 【Android】ant编译aidl的错误

    使用ant编译Android应用程序工程时,出现的错误: 错误信息(Cygwin): [aidl] This application has requested the Runtime to term ...

  6. Solidworks 2016中导出URDF文件

    安装SolidWorks to URDF exporter插件 下载SolidWorks to URDF Exporter插件后按照网站上的步骤进行安装(目前该插件已经在Win 7 64位系统+Sol ...

  7. V-rep学习笔记:vrep中的实用工具

    在V-REP的模型浏览器中可以找到一个工具文件夹tools,点开后会在下面一栏中显示许多方框图,将这些方框拖到场景模型中可以实现一些特定的功能,方便建模或其它操作. Center of mass vi ...

  8. python 面向对象编程案例01

    # -*- coding: utf-8 -*- #python 27 #xiaodeng #面向对象编程案例01 class Behave(): def __init__(self,name): se ...

  9. 查看Win系统激活状态

    Win键+R调出运行框,在运行框中输入cmd slmgr.vbs -dlv winver            回车后就能看到当前系统的版本 slmgr.vbs -dli 显示:操作系统版本.部分产品 ...

  10. Heroku第三方服务接入指南(二)

    上文我们讲了第三方服务.Heroku.用户三者的关系,这一篇进入正题,了解第三方厂商(下文简称厂商)怎样为Heroku开发服务.这里仅仅做简介,了解heroku大致是怎么做的.假设你的平台.希望接入第 ...