1. 程式人生 > >Python基礎-使用type()和元類metaclass

Python基礎-使用type()和元類metaclass

type()函式

檢視一個型別或變數的型別

type()函式可以檢視一個型別或變數的型別

執行示例

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# type()函式可以檢視一個型別或變數的型別

class Hello(object):

    def toString():
        print("helll world")

def runTest():
    mHello = Hello

    # type()函式可以檢視一個型別或變數的型別
    result = type(mHello)
    print(result)

    result = type(mHello.toString)
    print(result)

runTest()

執行結果

D:\PythonProject\sustudy>python main.py
<class 'type'>
<class 'function'>

瞭解即可,個人覺得暫時沒多少卵用

動態建立Class

示例程式碼

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# type() 的執行時動態建立

def functionDemo():
    print("Hello")

def runTest():

    # 動態建立Hello
    # 1. "Hello" 為class名稱
# 2. 繼承的父類集合,主要這裡是tuple包裹起來,有個逗號,不要看漏了 # 3. class 的函式名與函式繫結 Hello = type("Hello", (object,), dict(fun = functionDemo)) Hello.fun() runTest()

執行結果

D:\PythonProject\sustudy>python main.py
Hello

Python面向物件裡最難理解 metaclass

metaclass,直譯為元類,執行時動態控制類的建立行為

我們定義了類以後,就可以根據這個類創建出例項,所以:先定義類,然後建立例項。

但是如果我們想創建出類呢?那就必須根據metaclass創建出類,所以:先定義metaclass,然後建立類。

連線起來就是:先定義metaclass,就可以建立類,最後建立例項。

所以,metaclass允許你建立類或者修改類。換句話說,你可以把類看成是metaclass創建出來的“例項”。

metaclass是Python面向物件裡最難理解,也是最難使用的魔術程式碼。正常情況下,你不會碰到需要使用metaclass的情況,所以,以下內容看不懂也沒關係,因為基本上你不會用到。

List新增add的方法

示例

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# 元類 metaclass

# Demo list新增add的方法

# metaclass 是類的模板,故繼承type
class ListMetaclass(type):

    # cls 當前準備建立的類的物件
    # name 類的名字
    # bases 類繼承的父類集合
    # attrs 類的方法集合
    def __new__(cls, name, bases, attrs):
        # lambda 匿名函式,這裡新增add方法用
        attrs["add"] = lambda self, value: self.append(value)
        return type.__new__(cls, name, bases, attrs)

class MyList(list, metaclass = ListMetaclass):
    pass

def runTest():
    mList = MyList()
    mList.add(1)
    print(mList)

runTest()

執行結果

D:\PythonProject\sustudy>python main.py
[1]

ORM框架

ORM全稱“Object Relational Mapping”,即物件-關係對映,就是把關係資料庫的一行對映為一個物件,也就是一個類對應一個表,這樣,寫程式碼更簡單,不用直接操作SQL語句。

示例

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# ORM框架

#================================================================
# Field類
# 負責儲存資料庫表的欄位名和欄位型別
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);

# IntegerField型別
class StringField(Field):

    def __init__(self, name):
        super(StringField, self).__init__(name, "varchar(varchar(100))")

# IntegerField型別
class IntegerField(Field):

    def __init__(self, name):
        super(IntegerField, self).__init__(name, "bigint")
#================================================================
# ModelMetaclass
# metaclass是Python中非常具有魔術性的物件,它可以改變類建立時的行為。這種強大的功能使用起來務必小心。
class 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 mappings %s -> %s" % (k, v))
                mappings[k] = v

        # 排除掉對Modle的修改
        for k in mappings.keys():
            attrs.pop(k)

        # 儲存屬性和列的對映關係
        attrs["__mappings__"] = mappings
        # 假設表名和類名一致
        attrs["__table__"] = name

        return type.__new__(cls, name, bases, attrs)

#================================================================
# 基類
class Model(dict, metaclass=ModelMetaclass):

    def __init__(self, **kw):
        super(Model, self).__init__(**kw)

    def __getattr__(self, key):
        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 = []
        params = []
        args = []
        for k, v in self.__mappings__.items():
            fields.append(v.name)
            params.append('?')
            args.append(getattr(self, k, None))
        sql = 'insert into %s (%s) values (%s)' % (self.__table__, ','.join(fields), ','.join(params))
        print('SQL: %s' % sql)
        print('ARGS: %s' % str(args))

#================================================================
# User 呼叫介面
class User(Model):
    # 定義類的屬性到列的對映
    id = IntegerField("id")
    name = StringField("username")

# 建立一個例項
u = User(id = 1, name = "法迪")
# 儲存到資料庫
u.save()        

執行結果

D:\PythonProject\sustudy>python main.py
Found model User
Found mappings id -> <IntegerField : id>
Found mappings name -> <StringField : username>
SQL: insert into User (id,username) values (?,?)
ARGS: [1, '法迪']

上述瞭解即可,真正用到再詳細理解