1. 程式人生 > >python 元類的使用(orm框架搭建)

python 元類的使用(orm框架搭建)

元類是python面向物件程式設計裡面很難理解的一個東西,所謂元類的就是類的類,它用來建立類,在python裡面,類也是一個物件!!!.元類的作用就是動態的建立類.

在python裡面type就是元類,我們所有的class定義類的語句都會被python解釋為使用用type來建立一個類.

廢話少說,首先看一下怎麼用元類來解決一個動態建立類的需求,要求我們對於某一型別的類的滿足某個條件的屬性名字都變成大寫!比如:

class test:
 a = 1
 b = 2
 c = 3

然後test裡面的屬性是A,B,C。當然這個需求比較奇怪,我們完全可以手動的把類屬性定義為大寫,但是如果對於類的動態建立要求比較高的話,自己定義類就會很麻煩.這個以後再說.

程式碼如下:

class TestMetaclass(type):
    def __new__(cls,name,bases,attrs):
        print(attrs)
        attr_names = [ (attr_name.upper(),value) for attr_name,value in attrs.items() if not attr_name.startswith('__')]
        print(attr_names)
        return super().__new__(cls,name,bases,attrs)
class
Test(dict,metaclass = TestMetaclass):
f1 = 1 f2 = 2 sS = 3

這樣得到的Test就是所有不以_開頭的屬性都是大寫.而且除了Test,任何從TestMetaclass繼承的類都是有這樣的效果.

=====================我是分隔線========================

下面給出一種元類真正用的比較多的需求,構建ORM,ORM全稱“Object Relational Mapping”,即物件-關係對映,就是把關係資料庫的一行對映為一個物件,也就是一個類對應一個表,這樣,寫程式碼更簡單,不用直接操作SQL語句。

[0]首先需要構建頂層的介面.我們希望這個框架能夠給我們提供這樣的介面.

class User(Model):
    # 定義類的屬性到列的對映:
    id = IntegerField('id')
    name = StringField('username')
    email = StringField('email')
    password = StringField('password')

# 建立一個例項:
u = User(id=12345, name='Michael', email='[email protected]', password='my-pwd')
# 儲存到資料庫:
u.save()

這樣很方便,因為我可以隨意建立其他的user1,user2等類,只需要呼叫相應的介面就可以執行相應的sql操作.但是這裡就對orm框架有一個要求,我們的資料庫的結構是不定的,可能另外的一個user1需要10個屬性,user2需要8個屬性,而且每個屬性還不一樣,這樣你就必須讓你的類在建立的時候執行一些你規定的操作,比如將所有的屬性都收集起來,然後執行sql操作的時候在使用.簡單的說就是抽象這些屬性,讓它們在orm框架中可以動態的建立和操作,而不是依靠屬性的名字.

所以現在先構建Field類,它用來描述各個屬性的名字和屬性型別,比如id屬性的名字就叫’id’,屬性的型別就是’bigint’(我們自己定義的).

class 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)
class 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')

現在需要來編寫orm框架的核心內容:元類的繼承體系.

class ModelMetaclass(type):
    def __new__(cls,name,bases,attrs):
        if(name == 'Model'):#如果是Model類的話,就不需要做任何修改
            return super().__new__(cls,name,bases,attrs)
        mappings = dict()#建立一個對映字典,用來儲存當前建立的類的屬性
        for k,v in attrs.items():#遍歷所有屬性
            if(isinstance(v,Field)):#注意k都是str,v才可能是Filed型別.使用者定義的用來描述表的屬性,需要修改.其他的屬性不要亂動
                print('Found mapping: %s ==> %s' % (k,v ))
                mappings[k] = v#把這個屬性新增到mappings裡面,同時刪除attrs裡面的屬性,防止例項屬性和類屬性衝突
        for k in mappings.keys():
            attrs.pop(k)
        attrs['__mappings__'] = mappings#為attrs新增mappings這個屬性,就是把所有自定義的屬性都收集到attrs[__mapppings__]
        attrs['__table__'] = name#新增表的名字,這裡偷個懶,表的名字就是類的名字
        return super().__new__(cls,name,bases,attrs)
class Model(dict,metaclass = ModelMetaclass):
    def __init__(self, **kw):
        super(Model, self).__init__(**kw)

    def __getattr__(self, key):#目的是讓dict的keyerror變成attributeerror,因為使用getattr時處理的是AttributeError
        try:
            return self[key]
        except KeyError:
            raise AttributeError(r"'Model' object has no attribute '%s'" % key)

    def __setattr__(self, key, value):
        self[key] = value
    def save(self):
        fields = []#fields用來儲存屬性的名字
        params = []#params用來
        args = []#args用來
        for k,v in self.__mappings__.items():
            fields.append(v.name)
            params.append('?')#新增佔位符
            args.append(getattr(self,k,None))#將例項屬性的值新增到args裡面
        sql = 'inser into %s (%s) value (%s)'%(self.__table__,','.join(fields),','.join(params))
        print('SQL %s'%sql)
        print('ARGS %s'%str(args))

這樣就完成了一個orm框架的初步結構

相關推薦

python 的使用orm框架搭建

元類是python面向物件程式設計裡面很難理解的一個東西,所謂元類的就是類的類,它用來建立類,在python裡面,類也是一個物件!!!.元類的作用就是動態的建立類. 在python裡面type就是元類,我們所有的class定義類的語句都會被python解釋為使

Python中的編寫ORM框架

部落格轉載: https://blog.csdn.net/givemefive_y/article/details/79806348 https://blog.csdn.net/eye_water/article/details/78777870 https://www.liaoxue

javascript面向物件程式設計--繼承--多重繼承+摻多親繼承

繼承一般包括 單向繼承 和 多重繼承   多重繼承:一個子類繼承多個超類 function A(x){this.x=x;} A.prototype.getx=function(){return  this.x;} function B(y){this.y=y;}

使用python 實現ORM關係對映

元類實現ORM 1. ORM是什麼 ORM 是 python程式語言後端web框架 Django的核心思想,“Object Relational Mapping”,即物件-關係對映,簡稱ORM。 一個句話理解就是:建立一個例項物件,用建立它的類名當做資料表名,用建立它的類屬性對應資料表的

專案總結—校園辦公管理系統SSM框架搭建

登入頁面 學以致用,學習完SSM框架之後,獨立完成一個小院辦公管理系統,熟悉框架的開發流程,熟悉專案的開發流程,完成一個簡單的校園辦公管理系統,下圖是自己畫的UML圖,實現相關功能。 開發環境:Windows + Tomcat 開發工具:My

python中的metaclass

優先 裝飾器 target {} pass get tac 搜索 items 認識python中元類的準備工作。 1,首先需要明白一個概念就是python中一切皆為對象。 input: class Trick(object): pass print type(‘1234

pythonmetaclass中attrs的使用

metaclass可以使用attrs檢視、修改子類的屬性 其中是class的屬性,不是(建立之後的,self.)物件的 可以從輸出carry在最後看到,Test定義之後馬上生成,而不是等到有語句。 self.d是不存在的,__init__也被看成屬性(attrs),然後

Python技巧:Metaclasses和利用Type構建的動態Dynamic Classes

`metaclass`和`type`關鍵字在Python程式碼中較少被使用(也正因如此,它們的作用也沒有很好的被理解)。在這篇文章中,我們將探究`type()`的型別(types)和跟`metaclasses`相關的`type`的用法。 這是我的型別麼?首先來看`ty

深刻理解Python中的metaclass

1.類也是物件 在理解元類之前,你需要先掌握Python中的類。Python中類的概念借鑑於Smalltalk,這顯得有些奇特。在大多數程式語言中,類就是一組用來描述如何生成一個物件的程式碼段。在Python中這一點仍然成立: >>> class ObjectCreato

理解python中的metaclass

本文是根據stackoverflow上關於“What are metaclasses in Python?”的回答翻譯總結而成的。原資料連線:https://stackoverflow.com/questions/100003/what-are-metaclasses-in-

Python中的metaclass以及黑魔法__metaclass__

一、Python中的類 首先在這裡討論的python類,都是基於新式類進行討論。 在python中,一切皆為物件。 在理解元類之前我們先來重新理解一下python中的類。 class Joker: pass 當Python在執行帶clas

Python實戰,通過實現資料庫ORM框架

本文始發於個人公眾號:**TechFlow**,原創不易,求個關注 今天是Python專題的第19篇文章,我們一起來用元類實現一個簡易的ORM資料庫框架。 本文主要是受到了廖雪峰老師Python3入門教程的啟發,不過廖老師的部落格有些精簡,一些小白可能看起來比較吃力。我在他的基礎上做了一些補充和註釋

Python

bject class -1 div 所在 公開 nts 被調用 默認 一、類的重寫   對於父類的方法,只要它不符合子類模擬的實物的行為,都可對其進行重寫。為此,可在子類中定義一個這樣的方法,即它與要重寫的父類方法同名。這樣, Python將不會考慮這個父類方法,而只關註

python——tuple基本操作

name 逗號 print 一個個 gpo 類型 元組 多個 對象 元組被稱為只讀列表,數據可被查詢,但不能被修改,類似於列表的切片操作,元組寫在小括號裏面()元素之前用逗號隔開 對於一些不想被修改的數據,可以用元組來保存 # 創建元組 1)創建空元組 # 創建空元組

pythontuple

strong 第一個 class 返回 eve pos 位置 出現的次數 tro 元組tuple 元組一旦創建後便不可更改 表示方法: name1=("luo","gu","hu") 在一個元組中,可以是字符串,數字或混合型的 一、對於元組操作有以下函數: #1、cmp(n

Python 統一動態創建多個model對應的modelFormtype()函數

strong rgs tro BE ace 後臺 參數 函數 model 一、ModelForm的用法 ModelForm對用戶提交的數據有驗證功能,但比Form要簡單的多 from django.forms import ModelForm # 導入ModelForm

python:序列_常用基礎知識

err error: 指定 序列相加 針對 enumerate 最小值 推導式 ror 詳細如下: #元組:不可變列表,值不可修改,順序不可變 #元組有很多繼承序列的內容如下: #序列索引從0開始,從最後起則索引為-1 a = (1,8,3,9,5,6) b = (‘小

分散式系統詳解--框架Hadoop-叢集搭建

                 分散式系統詳解--框架(Hadoop-叢集搭建)        前面的文章也簡單介紹了,hadoop的環境搭建分為三種,單機版,偽分

python基礎二之列表和索引和切片

在python中,有幾種重要的操作可以適用於所有的序列,其中包括索引、切片、相加、相乘和成員資格檢查,另外Python中提供了一些內建函式,包含序列的長度,序列中最大值、最小值等。      1、索引:序列中的所有元素都有索引,且從0開始遞增。我們可以通過索引的

python原生程式碼框架,無AJAX技術前後端資料互動

採用form表格的post請求向後端傳遞資料 本系列即儘量採用原生程式碼方式實現瀏覽器與web伺服器之間進行互動;幫助小白們理解web伺服器的工作原理。 採用form表格從前端瀏覽器向後端提交資料是一種最原始的前端傳遞資料的方式,雖然程式碼執行較為麻煩,但是卻有助於深刻理解前後端的互動原