范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文

两句话掌握Python最难知识点元类出处

  每个中国人,都是天生的元类使用者
  学懂元类,你只需要知道两句话:道生一,一生二,二生三,三生万物我是谁?我从哪来里?我要到哪里去?
  在python世界,拥有一个永恒的道,那就是"type",请记在脑海中,type就是道。如此广袤无垠的python生态圈,都是由type产生出来的。
  道生一,一生二,二生三,三生万物。道 即是 type一 即是 metaclass(元类,或者叫类生成器)二 即是 class(类,或者叫实例生成器)三 即是 instance(实例)万物 即是 实例的各种属性与方法,我们平常使用python时,调用的就是它们。道和一,是我们今天讨论的命题,而二、三、和万物,则是我们常常使用的类、实例、属性和方法,用hello world来举例:1
  2
  3
  4
  5
  6
  7
  8
  9
  10
  11# 创建一个Hello类,拥有属性say_hello ----二的起源   class Hello():   def say_hello(self, name="world"):   print("Hello, %s." % name)   # 从Hello类创建一个实例hello ----二生三   hello = Hello()   # 使用hello调用方法say_hello ----三生万物   hello.say_hello()   输出效果:   1
  Hello, world.   这就是一个标准的"二生三,三生万物"过程。 从类到我们可以调用的方法,用了这两步。   那我们不由自主要问,类从何而来呢?回到代码的第一行。   class Hello其实是一个函数的"语义化简称",只为了让代码更浅显易懂,它的另一个写法是:1   2
  3
  4def fn(self, name="world"): # 假如我们有一个函数叫fn   print("Hello, %s." % name)   Hello = type("Hello", (object,), dict(say_hello=fn)) # 通过type创建Hello class ---- 神秘的"道",可以点化一切,这次我们直接从"道"生出了"二"   这样的写法,就和之前的Class Hello写法作用完全相同,你可以试试创建实例并调用   Python1   2
  3
  4
  5# 从Hello类创建一个实例hello ----二生三,完全一样   hello = Hello()   # 使用hello调用方法say_hello ----三生万物,完全一样   hello.say_hello()   输出效果:   1
  Hello, world. ----调用结果完全一样。   我们回头看一眼最精彩的地方,道直接生出了二:   Hello = type(‘Hello’, (object,), dict(say_hello=fn))   这就是"道",python世界的起源,你可以为此而惊叹。   注意它的三个参数!暗合人类的三大永恒命题:我是谁,我从哪里来,我要到哪里去。第一个参数:我是谁。 在这里,我需要一个区分于其它一切的命名,以上的实例将我命名为"Hello"第二个参数:我从哪里来   在这里,我需要知道从哪里来,也就是我的"父类",以上实例中我的父类是"object"——python中一种非常初级的类。第三个参数:我要到哪里去   在这里,我们将需要调用的方法和属性包含到一个字典里,再作为参数传入。以上实例中,我们有一个say_hello方法包装进了字典中。   值得注意的是,三大永恒命题,是一切类,一切实例,甚至一切实例属性与方法都具有的。理所应当,它们的"创造者",道和一,即type和元类,也具有这三个参数。但平常,类的三大永恒命题并不作为参数传入,而是以如下方式传入1   2
  3
  4
  5
  6
  7
  8class Hello(object){   # class 后声明"我是谁"   # 小括号内声明"我来自哪里"   # 中括号内声明"我要到哪里去"   def say_hello(){   }   }造物主,可以直接创造单个的人,但这是一件苦役。造物主会先创造"人"这一物种,再批量创造具体的个人。并将三大永恒命题,一直传递下去。"道"可以直接生出"二",但它会先生出"一",再批量地制造"二"。type可以直接生成类(class),但也可以先生成元类(metaclass),再使用元类批量定制类(class)。元类——道生一,一生二   一般来说,元类均被命名后缀为Metalass。想象一下,我们需要一个可以自动打招呼的元类,它里面的类方法呢,有时需要say_Hello,有时需要say_Hi,有时又需要say_Sayolala,有时需要say_Nihao。   如果每个内置的say_xxx都需要在类里面声明一次,那将是多么可怕的苦役! 不如使用元类来解决问题。   以下是创建一个专门"打招呼"用的元类代码:   Python1   2
  3
  4
  5class SayMetaClass(type):   def __new__(cls, name, bases, attrs):   attrs["say_"+name] = lambda self,value,saying=name: print(saying+","+value+"!")   return type.__new__(cls, name, bases, attrs)   记住两点:   1、元类是由"type"衍生而出,所以父类需要传入type。【道生一,所以一必须包含道】   2、元类的操作都在 __new__中完成,它的第一个参数是将创建的类,之后的参数即是三大永恒命题:我是谁,我从哪里来,我将到哪里去。 它返回的对象也是三大永恒命题,接下来,这三个参数将一直陪伴我们。   在__new__中,我只进行了一个操作,就是   Python   1
  attrs["say_"+name] = lambda self,value,saying=name: print(saying+","+value+"!")   它跟据类的名字,创建了一个类方法。比如我们由元类创建的类叫"Hello",那创建时就自动有了一个叫"say_Hello"的类方法,然后又将类的名字"Hello"作为默认参数saying,传到了方法里面。然后把hello方法调用时的传参作为value传进去,最终打印出来。   那么,一个元类是怎么从创建到调用的呢?   来!一起根据道生一、一生二、二生三、三生万物的准则,走进元类的生命周期吧   Python1   2
  3
  4
  5
  6
  7
  8
  9
  10
  11
  12
  13
  14
  15
  16
  17
  18
  19# 道生一:传入type   class SayMetaClass(type):   # 传入三大永恒命题:类名称、父类、属性   def __new__(cls, name, bases, attrs):   # 创造"天赋"   attrs["say_"+name] = lambda self,value,saying=name: print(saying+","+value+"!")   # 传承三大永恒命题:类名称、父类、属性   return type.__new__(cls, name, bases, attrs)   # 一生二:创建类   class Hello(object, metaclass=SayMetaClass):   pass   # 二生三:创建实列   hello = Hello()   # 三生万物:调用实例方法   hello.say_Hello("world!")   输出为   1
  Hello, world!   注意:通过元类创建的类,第一个参数是父类,第二个参数是metaclass   普通人出生都不会说话,但有的人出生就会打招呼说"Hello","你好","sayolala",这就是天赋的力量。它会给我们面向对象的编程省下无数的麻烦。   现在,保持元类不变,我们还可以继续创建Sayolala, Nihao类,如下:   Python1   2
  3
  4
  5
  6
  7
  8
  9# 一生二:创建类   class Sayolala(object, metaclass=SayMetaClass):   pass   # 二生三:创建实列   s = Sayolala()   # 三生万物:调用实例方法   s.say_Sayolala("japan!")   输出   Python   1
  Sayolala, japan!   也可以说中文   Python1   2
  3
  4
  5
  6
  7
  8
  9# 一生二:创建类   class Nihao(object, metaclass=SayMetaClass):   pass   # 二生三:创建实列   n = Nihao()   # 三生万物:调用实例方法   n.say_Nihao("中华!")   输出   Python   1
  Nihao, 中华!   再来一个小例子:   Python1   2
  3
  4
  5
  6
  7
  8
  9
  10
  11
  12
  13
  14
  15
  16# 道生一   class ListMetaclass(type):   def __new__(cls, name, bases, attrs):   # 天赋:通过add方法将值绑定   attrs["add"] = lambda self, value: self.append(value)   return type.__new__(cls, name, bases, attrs)   # 一生二   class MyList(list, metaclass=ListMetaclass):   pass   # 二生三   L = MyList()   # 三生万物   L.add(1)   现在我们打印一下L   Python1   2
  3print(L)   >>> [1]   而普通的list没有add()方法   Python1   2
  3
  4L2 = list()   L2.add(1)   >>>AttributeError: "list" object has no attribute "add"   太棒了!学到这里,你是不是已经体验到了造物主的乐趣?   python世界的一切,尽在掌握。   年轻的造物主,请随我一起开创新世界。   我们选择两个领域,一个是Django的核心思想,"Object Relational Mapping",即对象-关系映射,简称ORM。   这是Django的一大难点,但学完了元类,一切变得清晰。你对Django的理解将更上一层楼!   另一个领域是爬虫领域(黑客领域),一个自动搜索网络上的可用代理,然后换着IP去突破别的人反爬虫限制。   这两项技能非常有用,也非常好玩!挑战一:通过元类创建ORM准备工作,创建一个Field类   Python1   2
  3
  4
  5
  6
  7
  8class Field(object):   def __init__(self, name, column_type):   self.name = name   self.column_type = column_type   def __str__(self):   return "<%s:%s>" % (self.__class__.__name__, self.name)   它的作用是   在Field类实例化时将得到两个参数,name和column_type,它们将被绑定为Field的私有属性,如果要将Field转化为字符串时,将返回"Field:XXX" , XXX是传入的name名称。准备工作:创建StringField和IntergerField   Python1   2
  3
  4
  5
  6
  7
  8
  9class StringField(Field):   def __init__(self, name):   super(StringField, self).__init__(name, "varchar(100)")   class IntegerField(Field):   def __init__(self, name):   super(IntegerField, self).__init__(name, "bigint")   它的作用是   在StringField,IntegerField实例初始化时,时自动调用父类的初始化方式。道生一   Python1   2
  3
  4
  5
  6
  7
  8
  9
  10
  11
  12
  13
  14
  15
  16class ModelMetaclass(type):   def __new__(cls, name, bases, attrs):   if name=="Model":   return type.__new__(cls, name, bases, attrs)   print("Found model: %s" % name)   mappings = dict()   for k, v in attrs.items():   if isinstance(v, Field):   print("Found mapping: %s ==> %s" % (k, v))   mappings[k] = v   for k in mappings.keys():   attrs.pop(k)   attrs["__mappings__"] = mappings # 保存属性和列的映射关系   attrs["__table__"] = name # 假设表名和类名一致   return type.__new__(cls, name, bases, attrs)   它做了以下几件事创建一个新的字典mapping将每一个类的属性,通过.items()遍历其键值对。如果值是Field类,则打印键值,并将这一对键值绑定到mapping字典上。将刚刚传入值为Field类的属性删除。创建一个专门的__mappings__属性,保存字典mapping。创建一个专门的__table__属性,保存传入的类的名称。一生二   Python1   2
  3
  4
  5
  6
  7
  8
  9
  10
  11
  12
  13
  14
  15
  16
  17
  18
  19
  20
  21
  22
  23
  24class Model(dict, metaclass=ModelMetaclass):   def __init__(self, **kwarg):   super(Model, self).__init__(**kwarg)   def __getattr__(self, key):   try:   return self[key]   except KeyError:   raise AttributeError(""Model" object has no attribute "%s"" % key)   def __setattr__(self, key, value):   self[key] = value   # 模拟建表操作   def save(self):   fields = []   args = []   for k, v in self.__mappings__.items():   fields.append(v.name)   args.append(getattr(self, k, None))   sql = "insert into %s (%s) values (%s)" % (self.__table__, ",".join(fields), ",".join([str(i) for i in args]))   print("SQL: %s" % sql)   print("ARGS: %s" % str(args))如果从Model创建一个子类User:   Python1   2
  3
  4
  5
  6class User(Model):   # 定义类的属性到列的映射:   id = IntegerField("id")   name = StringField("username")   email = StringField("email")   password = StringField("password")   这时   id= IntegerField(‘id’)就会自动解析为:   Model.__setattr__(self, ‘id’, IntegerField(‘id’))   因为IntergerField(‘id’)是Field的子类的实例,自动触发元类的__new__,所以将IntergerField(‘id’)存入__mappings__并删除这个键值对。二生三、三生万物   当你初始化一个实例的时候并调用save()方法时候   Python1   2u = User(id=12345, name="Batman", email="batman@nasa.org", password="iamback")   u.save()   这时先完成了二生三的过程:先调用Model.__setattr__,将键值载入私有对象然后调用元类的"天赋",ModelMetaclass.__new__,将Model中的私有对象,只要是Field的实例,都自动存入u.__mappings__。   接下来完成了三生万物的过程:   通过u.save()模拟数据库存入操作。这里我们仅仅做了一下遍历__mappings__操作,虚拟了sql并打印,在现实情况下是通过输入sql语句与数据库来运行。   输出结果为   Python1   2
  3
  4
  5
  6
  7Found model: User   Found mapping: name ==>   Found mapping: password ==>   Found mapping: id ==>   Found mapping: email ==>   SQL: insert into User (username,password,id,email) values (Batman,iamback,12345,batman@nasa.org)   ARGS: ["Batman", "iamback", 12345, "batman@nasa.org"]   年轻的造物主,你已经和我一起体验了由"道"演化"万物"的伟大历程,这也是Django中的Model版块核心原理。 接下来,请和我一起进行更好玩的爬虫实战(嗯,你现在已经是初级黑客了):网络代理的爬取吧!挑战二:网络代理的爬取准备工作,先爬个页面玩玩   请确保已安装requests和pyquery这两个包。   Python1   2
  3
  4
  5
  6
  7
  8
  9
  10
  11
  12
  13
  14
  15
  16
  17
  18
  19
  20
  21# 文件:get_page.py   import requests   base_headers = {   "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36",   "Accept-Encoding": "gzip, deflate, sdch",   "Accept-Language": "zh-CN,zh;q=0.8"   }   def get_page(url):   headers = dict(base_headers)   print("Getting", url)   try:   r = requests.get(url, headers=headers)   print("Getting result", url, r.status_code)   if r.status_code == 200:   return r.text   except ConnectionError:   print("Crawling Failed", url)   return None   这里,我们利用request包,把百度的源码爬了出来。试一试抓百度   把这一段粘在get_page.py后面,试完删除   Python1   2
  3if(__name__ == "__main__"):   rs = get_page("https://www.baidu.com")   print("result:r ", rs)试一试抓代理   把这一段粘在get_page.py后面,试完删除   Python1   2
  3
  4
  5
  6
  7
  8
  9
  10
  11
  12if(__name__ == "__main__"):   from pyquery import PyQuery as pq   start_url = "http://www.proxy360.cn/Region/China"   print("Crawling", start_url)   html = get_page(start_url)   if html:   doc = pq(html)   lines = doc("p[name="list_proxy_ip"]").items()   for line in lines:   ip = line.find(".tbBottomLine:nth-child(1)").text()   port = line.find(".tbBottomLine:nth-child(2)").text()   print(ip+":"+port)   接下来进入正题:使用元类批量抓取代理批量处理抓取代理   Python1   2
  3
  4
  5
  6
  7
  8
  9
  10
  11
  12
  13
  14
  15
  16
  17
  18
  19
  20
  21
  22
  23
  24
  25
  26
  27
  28
  29
  30
  31
  32
  33
  34
  35
  36
  37
  38
  39
  40
  41
  42
  43
  44
  45
  46
  47
  48
  49
  50
  51
  52
  53
  54
  55
  56
  57
  58
  59
  60
  61
  62
  63
  64
  65
  66
  67
  68
  69
  70
  71
  72
  73
  74
  75
  76
  77
  78
  79
  80
  81
  82
  83
  84
  85
  86from getpage import get_page   from pyquery import PyQuery as pq   # 道生一:创建抽取代理的metaclass   class ProxyMetaclass(type):   """   元类,在FreeProxyGetter类中加入   __CrawlFunc__和__CrawlFuncCount__   两个参数,分别表示爬虫函数,和爬虫函数的数量。   """   def __new__(cls, name, bases, attrs):   count = 0   attrs["__CrawlFunc__"] = []   attrs["__CrawlName__"] = []   for k, v in attrs.items():   if "crawl_" in k:   attrs["__CrawlName__"].append(k)   attrs["__CrawlFunc__"].append(v)   count += 1   for k in attrs["__CrawlName__"]:   attrs.pop(k)   attrs["__CrawlFuncCount__"] = count   return type.__new__(cls, name, bases, attrs)   # 一生二:创建代理获取类   class ProxyGetter(object, metaclass=ProxyMetaclass):   def get_raw_proxies(self, site):   proxies = []   print("Site", site)   for func in self.__CrawlFunc__:   if func.__name__==site:   this_page_proxies = func(self)   for proxy in this_page_proxies:   print("Getting", proxy, "from", site)   proxies.append(proxy)   return proxies   def crawl_daili66(self, page_count=4):   start_url = "http://www.66ip.cn/{}.html"   urls = [start_url.format(page) for page in range(1, page_count + 1)]   for url in urls:   print("Crawling", url)   html = get_page(url)   if html:   doc = pq(html)   trs = doc(".containerbox table tr:gt(0)").items()   for tr in trs:   ip = tr.find("td:nth-child(1)").text()   port = tr.find("td:nth-child(2)").text()   yield ":".join([ip, port])   def crawl_proxy360(self):   start_url = "http://www.proxy360.cn/Region/China"   print("Crawling", start_url)   html = get_page(start_url)   if html:   doc = pq(html)   lines = doc("p[name="list_proxy_ip"]").items()   for line in lines:   ip = line.find(".tbBottomLine:nth-child(1)").text()   port = line.find(".tbBottomLine:nth-child(2)").text()   yield ":".join([ip, port])   def crawl_goubanjia(self):   start_url = "http://www.goubanjia.com/free/gngn/index.shtml"   html = get_page(start_url)   if html:   doc = pq(html)   tds = doc("td.ip").items()   for td in tds:   td.find("p").remove()   yield td.text().replace(" ", "")   if __name__ == "__main__":   # 二生三:实例化ProxyGetter   crawler = ProxyGetter()   print(crawler.__CrawlName__)   # 三生万物   for site_label in range(crawler.__CrawlFuncCount__):   site = crawler.__CrawlName__[site_label]   myProxies = crawler.get_raw_proxies(site)道生一:元类的__new__中,做了四件事:将"crawl_"开头的类方法的名称推入ProxyGetter.__CrawlName__将"crawl_"开头的类方法的本身推入ProxyGetter.__CrawlFunc__计算符合"crawl_"开头的类方法个数删除所有符合"crawl_"开头的类方法   怎么样?是不是和之前创建ORM的__mappings__过程极为相似?一生二:类里面定义了使用pyquery抓取页面元素的方法   分别从三个免费代理网站抓取了页面上显示的全部代理。   如果对yield用法不熟悉,可以查看:   廖雪峰的python教程:生成器二生三:创建实例对象crawler三生万物:遍历每一个__CrawlFunc__在ProxyGetter.__CrawlName__上面,获取可以抓取的的网址名。触发类方法ProxyGetter.get_raw_proxies(site)遍历ProxyGetter.__CrawlFunc__,如果方法名和网址名称相同的,则执行这一个方法把每个网址获取到的代理整合成数组输出。   那么…怎么利用批量代理,冲击别人的网站,套取别人的密码,狂发广告水贴,定时骚扰客户? 呃!想啥呢!这些自己悟!如果悟不到,请听下回分解!年轻的造物主,创造世界的工具已经在你手上,请你将它的威力发挥到极致!   请记住挥动工具的口诀:道生一,一生二,二生三,三生万物我是谁,我来自哪里,我要到哪里去Python元类再谈原文出处: TypingQuietly在Python中一切都是对象,类型也是对象;类比类型和实例的概念,类型也必然有自己的类型,十分合理。事实上,类型的类型其实就是术语元类型的意思,python里面所有类型的元类型都是type。默认情况下我们新建一个类,在不手动指定元类型的前提下,type会被指定为元类型 ,元类型能够控制类型的创建和初始化。一般情况下我们能够通过关键字class来定义一个新的自定义类型,但也能够通过type动态的生成一个新的类型,下面的两种实现方式等价:1234type("SomeKlass", (object,), {"foo":2, "bar": 4})class SomeKlass(object):foo = 2bar = 4借助这个例子,我们还能顺便看一下一些关于默认元类type的信息:Python12345>>> someobject = SomeKlass()>>> someobject.__class__>>> SomeKlass.__class__新定义一个类型,当类型被解析的时候(比如当作模块引入),元类会负责创建和初始化这个新的类型,背后的逻辑基本上包括:执行类的定义代码收集所有的属性和方法查找类的元类执行 Metaclass(name, bases, property_dict),参数分别新建的类的名称,类的父类tuple,收集的属性字典类型创建完成执行初始化在上面描述的过程中,自定义指定元类,然后重写元类的__new__ 和 __init__方法,因为在指定元类的情况下,除去收集信息的过程,类型的创建和初始化两个步骤:12MyKlass = MyMeta.__new__(MyMeta, name, bases, dct)MyMeta.__init__(MyKlass, name, bases, dct)注意这里的表示方式是调用内部方法来表示的,一般来说在重写的new或者init方法的最后都会调用type相应的方法来完成最终的类型创建或初始化工作,这时候也可以使用super关键字动态绑定,或者通过__dict__属性字典访问是一样的:12super(MyMeta, meta).__new__(meta, name, bases, dct)type.__new__(meta, name, bases, dct)对于__init__这样的method来说还可以这样调用:1type.__dict__["__init__"].__get__(cls)(name, bases, dct)插个题外话,这三种方式的使用其实涉及到python的描述符,使用super和get的时候会进行类型或者实例的绑定,相比直接调用内部方法__new__和__init__,由于绑定了self/cls上下文,在传递参数的时候就只用指定除上下文之后的参数了。从网上搜罗了一个例子,将元类创建和初始化新的类型的过程完整展示出来了:1234567891011121314151617181920212223242526272829303132333435class MyMeta(type):def __new__(meta, name, bases, dct):"""this is new doco"""print "-----------------------------------"print "Allocating memory for class", nameprint metaprint nameprint basesprint dctreturn super(MyMeta, meta).__new__(meta, name, bases, dct)# return type.__new__(meta, name, bases, dct)def __init__(cls, name, bases, dct):print "-----------------------------------"print "Initializing class", nameprint clsprint nameprint basesprint dctsuper(MyMeta, cls).__init__(name, bases, dct)# type.__init__(cls, name, bases, dict)# type.__dict__["__init__"].__get__(cls)(name, bases, dct)class MyKlass(object):__metaclass__ = MyMetadef foo(self, param):passbarattr = 2mk = MyKlass()创建和初始化的过程只会发生一此,也就是会是说 __new__, __init__只会被执行一次,并且在执行完之前,类型MyKlass其实并没有生成,直接通过名称访问会报错:Python1234567891011Allocating memory for class MyKlassMyKlass(,){"barattr": 2, "__module__": "__main__", "foo": , "__metaclass__": }-----------------------------------Initializing class MyKlassMyKlass(,){"barattr": 2, "__module__": "__main__", "foo": , "__metaclass__": }在使用元类的过程中,有时候我们会重写他的__call__方法,这个方法的作用其实和__new__有点相似,只不过这次是控制类型实例对象的生成,因为这个方法恰好和生成类型实例时调用的构造方法吻合。关于重写这个call方法的使用场景,一个比较常用的就是实现单例模式:123456789101112131415161718192021222324252627282930class MetaSingleton(type):instance = Nonedef __call__(cls, *args, **kw):"""this is comment"""print "in call method"if cls.instance is None:# cls.instance = super(MetaSingleton, cls).__call__(*args, **kw)# cls.instance = type.__dict__["__call__"].__get__(cls)(*args, **kw)cls.instance = type.__call__(cls, *args, **kw)print cls.instancereturn cls.instanceclass Foo(object):__metaclass__ = MetaSingletondef __init__(self, a, b):self.a = aself.b = ba = Foo(1, 2)b = Foo(3, 4)assert a is bprint a.a, a.b, b.a, b.bprint type(Foo)print Foo.__call__例子很直接,__call__方法里面通过判断是否已经有初始化过的实例,没有就仿照正常未指定元类的情况下调用type的__call__方法(当然这里要么通过super binding要么手动指定cls上下文),生成一个Foo的实例存储和返回出来。但是有一个注意点是,call方法每次初始化实例对象的时候都会被调用,这也和先前说的控制实例的生成一致:Python12345678(, , )in call method<__main__.Foo object at 0x00000000024BFA90>in call method<__main__.Foo object at 0x00000000024BFA90>1 2 1 2>还有一个需要在意的地方是最后的两行打印日志,Foo类型的元类是Metasingleton(调用new生成类型的时候默认指定元类是第一个参数);Foo的__call__方法是绑定了Foo(MetaSingleton的实例)实例的MetaSingleton的方法,也就是从另外的方面证实每次初始化Foo类型市里的时候,其实是在调用元类中重写的__call__方法。元类这个特性大多数情况下确实使用的不多并且需要稍微花点时间来理解,但是需要使用的时候会非常好用,往往能够实现很多优雅的功能,最典型的就是ORM的实现了,只不过会更加的复杂,且pythoning且学习吧, PEACE!参考资料中的链接里面有有几个实际的例子,本文也是学习其中的内容后配合一些其它一些使用经验以及碰到的问题理而成,希望对大家有用。

世界上最精确的时钟是如何改变基础物理学的?锶原子钟是世界上最精确的计时装置之一位于博尔德的科罗拉多大学叶骏教授的实验室中。爱因斯坦的广义相对论认为,像地球这样的大质量物体会弯曲时空,当你接近物体时会导致时间变慢所以山顶上的被湖人送走后,在太阳迎来新生!霍华德,也许你也不该选择湖人NBA常规赛打了快2个月,西部勇士和太阳竞争陷入白热化,两队战绩均为21胜4负,而作为上赛季西部常规赛霸主的爵士,反而成了小透明,被甩开很远。实话实说,勇士和太阳本赛季的爆发,有点一艘飞了200多亿公里的飞船,发回的最后照片,为什么引人深思?人类的梦想随着科技的进步不断地变化着,古时候人们渴望像鸟儿一样飞翔,触碰洁白的云彩。现在的人们渴望飞出太阳系,看看美丽的银河系全景,甚至说有机会能飞出银河系就更好了,我们对外面的世五类专家不让吃的食物,自己特别想吃,该怎么办?如何降低影响?晚上加班,同事去吃快餐带回来一个全家桶,一下子办公室里都是炸鸡的香味,刚刚吃过晚饭的我也难以抵挡诱惑,准备下手拿个鸡块解解馋,但办公室的李姐毫不动心,我说李姐,不来一块尝尝吗?减肥用于高速水下无线光链路的串联太阳能阵列用于高速水下无线光链路的串联太阳能阵列太阳能电池用于促进无线水下通信导读尽管太阳能电池通常设计用于将光转化为电能,但研究人员表明,它们也可用于实现高数据速率的水下无线光通信。这种新太阳能电池可用于促进无线水下通信无线电波在水中的传播表现并不好,因此像ROV这样的设备通常需要通信电缆实现水下操作。不过根据一项新的研究,太阳能电池板可能很快就能实现实用的水下光基通信。激光脉冲在水下传输数据已经海洋卫星监测显示南极一冰山漂流速度加快本报讯近日,国家卫星海洋应用中心工作人员通过我国海洋一号CD卫星数据研究发现,位于南极海域的一座巨大冰山(D28)沿南极大陆近岸向西漂移,在两年多时间漂移了近5000千米,且移动速中国成最大半导体市场全球芯片销量创历史新高一份新的报告显示,去年全球芯片销量创下历史新高。全球市场在2021年表现出色,中国是全球最大的单个半导体市场。事实上,SIA(半导体工业协会)发布了这一消息。根据报告,去年全球芯片全球彩电销量Top15三星第1,小米第5,华为第15,国产8家上榜虽然现在小屏越来越挤占大屏的空间,比如Pad手机电脑等占了彩电的空间,抢走了用户的时间,但对于很多人而言,家里买一台电视还是必须的,不管看不看。所以这些年以来,虽然彩电市场不再增长重大突发!乌克兰炮击卢甘斯!全球股市急速跳水局势风云突变,乌克兰突然动手!据俄新社俄罗斯卫星通讯社当地时间2月17日报道,俄罗斯支持的乌克兰东部民间武装当天指责乌克兰政府军炮轰其控制区,违反了旨在结束该地区冲突的明斯克协议。全球78亿人,每人5000步天,总里程能走出银河系吗?坐地日行八万里,巡天遥看一星河。七律毛泽东每当我们抬头仰望星空时,大家都会看到一条明亮的星河。我们所看到的星河,就是银河系。地球更是银河系的成员之一。这时候,总有人不禁会想,人类探
谷爱凌登杂志封面,身材绝了!年入曝光,从不炫富,社交圈太牛谷爱凌更新个人社交平台,晒出了最新一组的封面杂志,这是她首次登上了新加坡版的时尚芭莎,在镜头前的时尚表现力依旧不错,非常有范儿,身材太绝了。值得一提的是,在谷爱凌晒出照片之后的第一12胜1负!全联盟第一!全联盟最具冠军相的强队诞生,王者归来了本赛季,NBA联盟强队的标准,一直都在凯尔特人队和雄鹿队当中,因为他们此前的战绩一直排名联盟前二,遥遥领先其他球队。但是,经过最近这一段比赛的洗礼,情况有所变化,绿军最近7战2胜543岁章子怡亮相澳门电影节,大晒零赘肉好身材,完胜发福刘亦菲43岁的章子怡和35岁的刘亦菲,代表娱乐圈两个时代的女性朋友颜值天花板。一个是顶级骨相,一个是顶级皮相。但二人同框,谁的状态更好就见仁见智了。日前,澳门国际电影节举行颁奖礼,两位女海月琉璃足之后,嫦娥花边袜也不差,coser还原有点难最近王者荣耀推出了一款新的皮肤,也就是嫦娥的S30战令皮肤名字叫暖冬兔眠。从皮肤的背景故事来看,嫦娥在家门口捡到了一只小兔子,她们两个相互依偎着在一旁烤火,然后逐渐陷入到沉睡当中,捍卫公会的荣耀,曙光一线获2022直播年度盛典王者公会亚军年度盛典是我们公会一年中最重要的活动,也是一场硬仗,希望大家做好充足的准备迎接挑战,都有没有信心?2022快手直播年度盛典公会赛揭幕前,曙光一线公会长王曙光做了一场动员会,他得到了IU酒店打造齐鲁文化旅游发展新高地淄博,位处鲁中,是黄河三角洲生态经济和蓝色经济区的交汇处。四季分明的气候造就了这座齐国故都的生态多样性,南高北低的地理位置使其峻岭平原兼具,鲁中的位置又赋予他交通枢纽的重要性。这里成都滑雪季正式拉开序幕,西岭雪山开放滑雪项目西岭雪山滑雪场开板啦!距成都仅120公里的西岭雪山积雪却越来越厚,目前整个滑雪场景区已被覆盖。据悉,西岭雪山滑雪场景区明日(12月23日)开放滑雪初级道和熊猫道(红房子),标志着成一渠黄河水两岸云共情台湾青年云共享黄河故事台青眼里的黄河台青黄河游记分享会12月20日在厦门卫视看厦门APP厦门广电网央视频央视频移动网运城市县二级新媒体抖音快手视频号微博FacebookYouTube等两岸新媒体平台同步行走在国外的岁月18奥兰A阿尔及尔之于中国,就是北京,那奥兰呢,就是上海了。不过,非洲的这些城市都不是很大,不能和国内的北上广相比。百度能提供的信息并不多,奥兰和国内城市相比估计最多算个N线城市吧。而当年我(时事聚焦)文旅小镇的生与死,失败案例各有不幸!随着国内复工复产的深入,各地方旅游部门企业景区已经开始谋划疫后全面复苏的规划,旅游项目投资建设纷纷重启。重启迎来行业复苏产业向暖,同时也预设着另一面环境变化市场调整及优胜劣汰。当市游拍容县民国小镇一列老火车,带我们走进民国小镇讲到民国建筑,笔者还是推崇天津五大道民国时期遗留下来的各式风格独栋别墅,让笔者不能忘怀的是红砖清水墙中西结合的风格别墅。广西容县有心者,人为打造民国风