电子商务物流网站建设,m开头的网站开发工具,wordpress mp4 插件,烈焰网页游戏传奇什么是元编程
软件开发中很重要的一条原则就是“不要重复自己的工作#xff08;Don’t repeat youself#xff09;”#xff0c;也就是说当我们需要复制粘贴代码时候#xff0c;通常都需要寻找一个更加优雅的解决方案#xff0c;在python中#xff0c;这类问题常常会归类…什么是元编程
软件开发中很重要的一条原则就是“不要重复自己的工作Don’t repeat youself”也就是说当我们需要复制粘贴代码时候通常都需要寻找一个更加优雅的解决方案在python中这类问题常常会归类为“元编程”
元编程目的
是创建函数和类并用他们操作代码例如修改生成或者包装自己已有的代码。尽可能的使代码优雅简洁。具体而言通过编程的方法在更高的抽象层次上对一种层次的抽象的特性进行修改
元编程应用
给函数添加一个包装装饰器
注意对wraps装饰器的使用进行补充说明在类装饰器中使用闭包会导致生成的对象不再是被装饰的类的实例而是在装饰器函数创建的子类的实例这会影响__name__和__doc__等属性在上篇我们使用wraps装饰器对函数装饰器进行操作让问题得到解决但在类装饰器中这一方法无效。
元类
在理解元类之前您需要掌握Python中的类。Python对于从Smalltalk语言借用的类是非常奇怪的。在大多数语言中类只是描述如何生成对象的代码片段。在Python中也是如此 1 2 3 4 5 6 7 class ObjectCreator(object): ... pass ... my_object ObjectCreator() print(my_object) __main__.ObjectCreator object at 0x8974f2c 一旦使用关键字classPython就会执行它并创建一个OBJECT。指示 1 2 3 class ObjectCreator(object): ... pass ... 在内存中创建一个名为“ObjectCreator”的对象。这个对象类本身能够创建对象实例这就是为什么它是一个类。但是它仍然是一个对象因此 您可以将其分配给变量你可以复制它你可以添加属性您可以将其作为函数参数传递
例如 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 print(ObjectCreator) # you can print a class because its an object class __main__.ObjectCreator def echo(o): ... print(o) ... echo(ObjectCreator) # you can pass a class as a parameter class __main__.ObjectCreator print(hasattr(ObjectCreator, new_attribute)) False ObjectCreator.new_attribute foo # you can add attributes to a class print(hasattr(ObjectCreator, new_attribute)) True print(ObjectCreator.new_attribute) foo ObjectCreatorMirror ObjectCreator # you can assign a class to a variable print(ObjectCreatorMirror.new_attribute) foo print(ObjectCreatorMirror()) __main__.ObjectCreator object at 0x8997b4c 动态创建类
由于类是对象因此您可以像任何对象一样动态创建它们。首先您可以使用class以下命令在函数中创建类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 def choose_class(name): ... if name foo: ... class Foo(object): ... pass ... return Foo # return the class, not an instance ... else: ... class Bar(object): ... pass ... return Bar ... MyClass choose_class(foo) print(MyClass) # the function returns a class, not an instance class __main__.Foo print(MyClass()) # you can create an object from this class __main__.Foo object at 0x89c6d4c 但它还不是我们想要的创建类应该有更优的方法由于类是对象因此它们必须由某些东西生成。
使用class关键字时Python会自动创建此对象。但与Python中的大多数内容一样它为您提供了手动执行此操作的方法。我们可用通过type函数查看对象的类型 1 2 3 4 5 6 7 8 print(type(1)) type int print(type(1)) type str print(type(ObjectCreator)) type type print(type(ObjectCreator())) class __main__.ObjectCreator type除了可以查看数据类型外,还有一个特殊的能力它也可以动态创建类。type可以将类的描述作为参数并返回一个类。查看type内部原理 1 2 3 type(name of the class, tuple of the parent class (for inheritance, can be empty), dictionary containing attributes names and values) 例如 1 2 class MyShinyClass(object): ... pass 可以通过以下方式手动创建 1 2 3 4 5 MyShinyClass type(MyShinyClass, (), {}) # returns a class object print(MyShinyClass) class __main__.MyShinyClass print(MyShinyClass()) # create an instance with the class __main__.MyShinyClass object at 0x8997cec type接受字典来定义类的属性。所以 1 2 class Foo(object): ... bar True 可以翻译成 1 Foo type(Foo, (), {bar:True}) 并用作普通类 1 2 3 4 5 6 7 8 9 print(Foo) class __main__.Foo print(Foo.bar) True f Foo() print(f) __main__.Foo object at 0x8a9b84c print(f.bar) True 当然你可以继承它所以 1 2 class FooChild(Foo): ... pass 会解释成 1 2 3 4 5 FooChild type(FooChild, (Foo,), {}) print(FooChild) class __main__.FooChild print(FooChild.bar) # bar is inherited from Foo True 最后如果想要为我们创建的类添加方法只需使用正确的签名定义函数并将其指定为属性即可。 1 2 3 4 5 6 7 8 9 10 11 def echo_bar(self): ... print(self.bar) ... FooChild type(FooChild, (Foo,), {echo_bar: echo_bar}) hasattr(Foo, echo_bar) False hasattr(FooChild, echo_bar) True my_foo FooChild() my_foo.echo_bar() True 在动态创建类之后您可以添加更多方法就像向正常创建的类对象添加方法一样。 1 2 3 4 5 6 def echo_bar_more(self): ... print(yet another method) ... FooChild.echo_bar_more echo_bar_more hasattr(FooChild, echo_bar_more) True 在Python中类是对象您可以动态地动态创建类。这是Python在您使用关键字时所执行的操作class它通过使用元类来实现。 什么是元类终于讲到重点了
元类是创建类的“类”。我们可以定义类来创建实例python一切皆对象类也不列外它是通过元类来创建。类是创建实例的蓝图元类是创建类的蓝图。可以很容易地看出Python类中也需要是第一类对象才能启用此行为。
例如 1 2 MyClass MetaClass() my_object MyClass() 通过type来创建 1 MyClass type(MyClass, (), {}) 这是因为该函数type实际上是一个元类。type是Python用于在幕后创建所有类的元类。
为什么是小写type而不是大学Type type与str创建字符串对象int的类创建整数对象的类类似它也只是创建类对象的类。我们通过检查__class__属性来查看。
一切一切一切重要的事情说三遍都是Python中的一个对象。这包括整数字符串函数和类。所有这些都是对象。所有这些都是从一个类创建的 1 2 3 4 5 6 7 8 9 10 11 12 13 age 35 age.__class__ type int name bob name.__class__ type str def foo(): pass foo.__class__ type function class Bar(object): pass b Bar() b.__class__ class __main__.Bar 那么__class__的__class__ 1 2 3 4 5 6 7 8 age.__class__.__class__ type type name.__class__.__class__ type type foo.__class__.__class__ type type b.__class__.__class__ type type 因此元类只是创建类对象的东西。我们也称它为类工厂
type 是Python使用的内置元类我们也可以创建自己的元类。
__mataClass__属性 在Python 2中我们在编写类时添加属性 1 2 3 class Foo(object): __metaclass__ something... [...] 如果引用__mataClass__属性python将使用元类类创建Foo但是这样class Foo(object)类对象Foo并不是在内存中创建的
Python将会在父类中查找__metaclass__如果没有就继续向父类的父类查找如果还是没有就在模块中找还是没有的话就用缺省的MetaClass即type创建类。
当你这样做时 1 2 class Foo(Bar): pass Python会执行以下操作
如果有__metaclass__属性将会在内存中创建一个类对象名称Foo使用是__metaclass__。如果Python找不到__metaclass__它将__metaclass__在MODULE级别查找并尝试执行相同的操作但仅适用于不继承任何内容的类基本上是旧式类。
如果还是找不到__metaclass__它将使用Bars第一个父级自己的元类可能是默认的type来创建类对象。 Python中的元类3
在Python 3中更改了设置元类的语法 1 2 class Foo(object, metaclasssomething): ... 即__metaclass__不再使用该属性而是支持基类列表中的关键字参数。但是并不会影响元类的功能。
python3中我们可以将属性作为关键字参数传递给元类如下所示 1 2 class Foo(object, metaclasssomething, kwarg1value1, kwarg2value2): ... 自定义元类
一个类没有声明自己的元类默认他的元类就是type,除了使用元类type用户也可以通过继承type来自定义元类
自定义元类的主要目的是 拦截类的创建读取类的信息可以做修改返回新的类
通过传入不同的字符串动态的创建不同的类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 def create_class(name): if name user: class User: def __str__(self): return user return User elif name company: class Company: def __str__(self): return company return Company if __name__ __main__: Myclass create_class(user) my_obj Myclass() print(my_obj) #user print(type(my_obj)) #class __main__.create_class.locals.User 用type创建 1 2 3 4 5 6 7 8 9 10 11 12 13 14 # 一个简单type创建类的例子 #type(object_or_name, bases, dict) #type里面有三个参数第一个类名第二个基类名第三个是属性 User type(User,(),{name:derek}) my_obj User() print(my_obj.name) #derek#带方法的创建brbrdef say(self): #必须加self return i am derek User type(User,(),{name:derek,say:say}) my_obj User() print(my_obj.name) #derek print(my_obj.say()) #i am derek 让type创建的类继承一个基类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 def say(self): #必须加self return i am derek class BaseClass: def answer(self): return i am baseclass #type里面有三个参数第一个类名第二个基类名第三个是属性 User type(User,(BaseClass,),{name:derek,say:say}) if __name__ __main__: my_obj User() print(my_obj.name) #d erek print(my_obj.say()) # i am derek print(my_obj.answer()) # i am baseclass 但是在实际编码中我们一般不直接用type去创建类而是用元类的写法自定义一个元类metaclass去创建 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 # 把User类创建的过程委托给元类去做这样代码的分离性比较好 class MetaClass(type): def __new__(cls, *args, **kwargs): return super().__new__(cls,*args, **kwargs) class User(metaclassMetaClass): def __init__(self,name): self.name name def __str__(self): return test if __name__ __main__: #python中类的实例化过程会首先寻找metaclass通过metaclass去创建User类 my_obj User(namederek) print(my_obj) #test 还有一个典型的自定义元类例子就是Django ORM。元类的主要用例是创建API。
它允许您定义如下内容
class Person(models.Model):name models.CharField(max_length30)age models.IntegerField()但是如果你这样做
guy Person(namebob, age35)
print(guy.age)它不会返回一个IntegerField对象。它将返回一个int甚至可以直接从数据库中获取它。
因为models.Model定义__metaclass__它会使用一些魔法将Person您刚刚使用简单语句定义的内容转换为数据库字段的复杂sql。
Django通过公开一个简单的API并使用元类从这个API中重新创建代码来完成幕后的实际工作从而使复杂的外观变得简单。 文章转载自: http://www.morning.pfggj.cn.gov.cn.pfggj.cn http://www.morning.jbtwq.cn.gov.cn.jbtwq.cn http://www.morning.yprnp.cn.gov.cn.yprnp.cn http://www.morning.skkmz.cn.gov.cn.skkmz.cn http://www.morning.nrcbx.cn.gov.cn.nrcbx.cn http://www.morning.nzlqt.cn.gov.cn.nzlqt.cn http://www.morning.gwjqq.cn.gov.cn.gwjqq.cn http://www.morning.smcfk.cn.gov.cn.smcfk.cn http://www.morning.jbgzy.cn.gov.cn.jbgzy.cn http://www.morning.cbnjt.cn.gov.cn.cbnjt.cn http://www.morning.yckrm.cn.gov.cn.yckrm.cn http://www.morning.lblsx.cn.gov.cn.lblsx.cn http://www.morning.amonr.com.gov.cn.amonr.com http://www.morning.rjkfj.cn.gov.cn.rjkfj.cn http://www.morning.lwbhw.cn.gov.cn.lwbhw.cn http://www.morning.nmkbl.cn.gov.cn.nmkbl.cn http://www.morning.nlpbh.cn.gov.cn.nlpbh.cn http://www.morning.qnwyf.cn.gov.cn.qnwyf.cn http://www.morning.gfqj.cn.gov.cn.gfqj.cn http://www.morning.mzbyl.cn.gov.cn.mzbyl.cn http://www.morning.zzaxr.cn.gov.cn.zzaxr.cn http://www.morning.ghslr.cn.gov.cn.ghslr.cn http://www.morning.ndcjq.cn.gov.cn.ndcjq.cn http://www.morning.jpjxb.cn.gov.cn.jpjxb.cn http://www.morning.hcbky.cn.gov.cn.hcbky.cn http://www.morning.bfybb.cn.gov.cn.bfybb.cn http://www.morning.pnjsl.cn.gov.cn.pnjsl.cn http://www.morning.rhlhk.cn.gov.cn.rhlhk.cn http://www.morning.rqqmd.cn.gov.cn.rqqmd.cn http://www.morning.nnqrb.cn.gov.cn.nnqrb.cn http://www.morning.jspnx.cn.gov.cn.jspnx.cn http://www.morning.qykxj.cn.gov.cn.qykxj.cn http://www.morning.zpqk.cn.gov.cn.zpqk.cn http://www.morning.trrhj.cn.gov.cn.trrhj.cn http://www.morning.tjndb.cn.gov.cn.tjndb.cn http://www.morning.jgnjl.cn.gov.cn.jgnjl.cn http://www.morning.gnzsd.cn.gov.cn.gnzsd.cn http://www.morning.gyqnp.cn.gov.cn.gyqnp.cn http://www.morning.ckxd.cn.gov.cn.ckxd.cn http://www.morning.ymtbr.cn.gov.cn.ymtbr.cn http://www.morning.xdnhw.cn.gov.cn.xdnhw.cn http://www.morning.3ox8hs.cn.gov.cn.3ox8hs.cn http://www.morning.knlgk.cn.gov.cn.knlgk.cn http://www.morning.cgmzt.cn.gov.cn.cgmzt.cn http://www.morning.mgwdp.cn.gov.cn.mgwdp.cn http://www.morning.tqsmc.cn.gov.cn.tqsmc.cn http://www.morning.ghrlx.cn.gov.cn.ghrlx.cn http://www.morning.nkrmh.cn.gov.cn.nkrmh.cn http://www.morning.kkjlz.cn.gov.cn.kkjlz.cn http://www.morning.mnnxt.cn.gov.cn.mnnxt.cn http://www.morning.xpqdf.cn.gov.cn.xpqdf.cn http://www.morning.xpgwz.cn.gov.cn.xpgwz.cn http://www.morning.qhtlq.cn.gov.cn.qhtlq.cn http://www.morning.jtszm.cn.gov.cn.jtszm.cn http://www.morning.jjwzk.cn.gov.cn.jjwzk.cn http://www.morning.dkbsq.cn.gov.cn.dkbsq.cn http://www.morning.zthln.cn.gov.cn.zthln.cn http://www.morning.cgdyx.cn.gov.cn.cgdyx.cn http://www.morning.bmzxp.cn.gov.cn.bmzxp.cn http://www.morning.ggxbyhk.cn.gov.cn.ggxbyhk.cn http://www.morning.qcslh.cn.gov.cn.qcslh.cn http://www.morning.dwhnb.cn.gov.cn.dwhnb.cn http://www.morning.xqnzn.cn.gov.cn.xqnzn.cn http://www.morning.wqpr.cn.gov.cn.wqpr.cn http://www.morning.dkgtr.cn.gov.cn.dkgtr.cn http://www.morning.pamdeer.com.gov.cn.pamdeer.com http://www.morning.bmhc.cn.gov.cn.bmhc.cn http://www.morning.mngh.cn.gov.cn.mngh.cn http://www.morning.fxxmj.cn.gov.cn.fxxmj.cn http://www.morning.mgbsp.cn.gov.cn.mgbsp.cn http://www.morning.cfjyr.cn.gov.cn.cfjyr.cn http://www.morning.cfocyfa.cn.gov.cn.cfocyfa.cn http://www.morning.zrkp.cn.gov.cn.zrkp.cn http://www.morning.jqsyp.cn.gov.cn.jqsyp.cn http://www.morning.kuaijili.cn.gov.cn.kuaijili.cn http://www.morning.tmbfz.cn.gov.cn.tmbfz.cn http://www.morning.rxydr.cn.gov.cn.rxydr.cn http://www.morning.tymnr.cn.gov.cn.tymnr.cn http://www.morning.rmdwp.cn.gov.cn.rmdwp.cn http://www.morning.glxdk.cn.gov.cn.glxdk.cn