精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

Python 元類(Meta Class):解密 Python 面向對象編程的幕后推手

開發(fā) 前端
元類是 Python 中一個強大的特性,它允許我們控制類的創(chuàng)建過程。雖然在日常編程中可能用不到,但在框架開發(fā)中經常會用到。理解元類的工作原理對于深入理解 Python 的類型系統(tǒng)很有幫助。

架構在 Python 編程中,我們每天都在和類打交道,但是你是否也和我一樣想過:類本身是什么?是誰創(chuàng)建了類?元類(Meta Class)就是用來創(chuàng)建類的"類"。今天讓我們一起深入理解這個強大而神秘的特性。

從一個簡單的類說起

class Person:
    def __init__(self, name):
        self.name = name
    
    def greet(self):
        return f"Hello, I'm {self.name}"

# 創(chuàng)建實例
p = Person("Alice")
print(p.greet())  # 輸出: Hello, I'm Alice

當我們定義這個類時,Python 實際上在背后做了什么?讓我們用 type 來看看:

print(type(p))        # <class '__main__.Person'>
print(type(Person))   # <class 'type'>

看到了嗎?Person 類的類型是 type。實際上,type 就是 Python 中的默認元類。

用 type 動態(tài)創(chuàng)建類

在 Python 中,我們可以用 type 動態(tài)創(chuàng)建類:

def greet(self):
    return f"Hello, I'm {self.name}"

# 動態(tài)創(chuàng)建類
PersonType = type('PersonType', 
                 (object,),                # 基類
                 {
                     '__init__': lambda self, name: setattr(self, 'name', name),
                     'greet': greet
                 })

# 使用動態(tài)創(chuàng)建的類
p = PersonType("Bob")
print(p.greet())  # 輸出: Hello, I'm Bob

是的,我也很奇怪。Python 中的 type 函數有兩個用法,二者意義相去甚遠:

  • type(name, bases, dict):創(chuàng)建一個新的類對象
  • type(object):返回對象的類型

自定義元類

當我們需要在類創(chuàng)建時進行一些特殊的控制或修改時,就可以使用自定義元類:

class LoggedMeta(type):
    def __new__(cls, name, bases, attrs):
        # 在類創(chuàng)建前,為所有方法添加日志
        for key, value in attrs.items():
            if callable(value) and not key.startswith('__'):
                attrs[key] = cls.log_call(value)
        
        return super().__new__(cls, name, bases, attrs)
    
    @staticmethod
    def log_call(func):
        def wrapper(*args, **kwargs):
            print(f"Calling method: {func.__name__}")
            return func(*args, **kwargs)
        return wrapper

# 使用自定義元類
class MyClass(metaclass=LoggedMeta):
    def foo(self):
        print("foo")

    def bar(self):
        print("bar")

# 測試
obj = MyClass()
obj.foo()  # 輸出: Calling method: foo \n foo
obj.bar()  # 輸出: Calling method: bar \n bar

輸出:

Calling method: foo
foo
Calling method: bar
bar

與繼承的區(qū)別?

  • 繼承是在實例創(chuàng)建時起作用,而元類是在類定義時就起作用
  • 繼承控制的是實例的行為,而元類控制的是類的行為
  • 繼承遵循 MRO (Method Resolution Order) 規(guī)則,而元類工作在更底層,在類被創(chuàng)建之前就介入

繼承實現上述的功能:

class Logged:
    def __getattribute__(self, name):
        attr = super().__getattribute__(name)
        if callable(attr) and not name.startswith('__'):
            print(f"Calling method: {name}")
        return attr

class MyClass(Logged):
    def foo(self):
        print("foo")

    def bar(self):
        print("bar")

# 測試
obj = MyClass()
obj.foo()
obj.bar()

這種繼承方案和元類方案的關鍵區(qū)別是:

  • 繼承方案在每次調用方法時都要經過 __getattribute__ ,性能開銷較大
  • 元類方案在類定義時就完成了方法的包裝,運行時幾乎沒有額外開銷
  • 繼承方案更容易理解和調試,元類方案更底層和強大

這里補充一下 __getattribute__ ,參考[1]:A key difference between __getattr__ and __getattribute__ is that __getattr__ is only invoked if the attribute wasn't found the usual ways. It's good for implementing a fallback for missing attributes, and is probably the one of two you want. 翻譯:__getattr__ 和 __getattribute__ 之間的一個關鍵區(qū)別是,只有當屬性無法通過常規(guī)方式找到時,才會調用 __getattr__ 。它非常適合實現缺失屬性的后備,并且可能是您想要的兩個方法之一。

元類的實際應用場景

1. 接口強制實現

from abc import ABCMeta, abstractmethod

class InterfaceMeta(ABCMeta):
    def __init_subclass__(cls, **kwargs):
        super().__init_subclass__(**kwargs)
        # 獲取所有抽象方法
        abstracts = {name for name, value in cls.__dict__.items()
                     if getattr(value, "__isabstractmethod__", False)}
        # 檢查子類是否實現了所有抽象方法
        if abstracts and not getattr(cls, '__abstractmethods__', False):
            raise TypeError(f"Can't instantiate abstract class {cls.__name__} "
                            f"with abstract methods {abstracts}")


class Interface(metaclass=InterfaceMeta):
    @abstractmethod
    def my_interface(self):
        pass


# 這個類會在實例化時報錯
class BadImplementation(Interface):
    pass


# 這個類可以正常使用
class GoodImplementation(Interface):
    def my_interface(self):
        return "Implementation"


# 測試
try:
    good = GoodImplementation()  # 正常
    print("GoodImplementation instantiated successfully:", good.my_interface())
except TypeError as e:
    print("Error in GoodImplementation:", e)

try:
    bad = BadImplementation()  # TypeError: Can't instantiate abstract class...
except TypeError as e:
    print("Error in BadImplementation:", e)

注意這里的 __init_subclass__ 方法,它在子類被定義時被調用。在這個方法中,我們檢查子類是否實現了所有抽象方法。如果沒有實現,我們就拋出一個 TypeError 異常。

或許出于 Python 動態(tài)類型的特性,我們依然只能在 bad = BadImplementation() 實例化時才會報錯,而不是像靜態(tài)語言那樣,在 class BadImplementation 定義時就報錯。

借助 pylint 這類靜態(tài)代碼檢查工具,我們可以在 class BadImplementation 定義時就發(fā)現這個錯誤。但是 Python 語言本身似乎做不到(或許你有好辦法?可以評論區(qū)告訴我)。

但這也要比 class Interface 中定義一個 raise NotImplementedError 更優(yōu)雅一些?

2. ORM 框架中的應用

這是一個簡化版的 ORM 示例,展示了元類在實際項目中的應用:

class ModelMeta(type):
    def __new__(cls, name, bases, attrs):
        fields = {}
        for key, value in attrs.items():
            if isinstance(value, Field):
                fields[key] = value
                
        attrs['_fields'] = fields
        return super().__new__(cls, name, bases, attrs)

class Field:
    def __init__(self, field_type):
        self.field_type = field_type

class Model(metaclass=ModelMeta):
    def __init__(self, **kwargs):
        for key, value in kwargs.items():
            if key in self._fields:
                setattr(self, key, value)
    
    def validate(self):
        for name, field in self._fields.items():
            value = getattr(self, name, None)
            if not isinstance(value, field.field_type):
                raise TypeError(f"{name} must be of type {field.field_type}")

# 使用這個簡單的 ORM
class User(Model):
    name = Field(str)
    age = Field(int)

# 測試
user = User(name="Alice", age=25)
user.validate()  # 正常
user.age = "not an integer"
try:
    user.validate()  # 將拋出 TypeError
except TypeError as e:
    print(e)

使用元類的注意事項

  1. 不要過度使用:元類是強大的工具,但也容易導致代碼難以理解和維護。大多數情況下,普通的類和裝飾器就足夠了。
  2. 性能考慮:元類會在類創(chuàng)建時執(zhí)行額外的代碼,如果使用不當可能影響性能。
  3. 調試困難:使用元類的代碼往往較難調試,因為它們改變了類的創(chuàng)建過程。

總結

元類是 Python 中一個強大的特性,它允許我們控制類的創(chuàng)建過程。雖然在日常編程中可能用不到,但在框架開發(fā)中經常會用到。理解元類的工作原理對于深入理解 Python 的類型系統(tǒng)很有幫助。

最后提醒一下,請記住 Python 之禪中的一句話:


Simple is better than complex.

除非確實需要元類的強大功能,否則使用更簡單的解決方案可能是更好的選擇。

參考資料

[1]參考: https://stackoverflow.com/questions/3278077/difference-between-getattr-and-getattribute

責任編輯:武曉燕 來源: Piper蛋窩
相關推薦

2023-09-27 23:28:28

Python編程

2023-11-02 07:55:31

Python對象編程

2019-03-26 10:50:22

Python面向對象編程語言

2023-01-10 09:06:17

2023-12-11 15:32:30

面向對象編程OOPpython

2010-02-02 13:15:26

Python類

2010-02-26 14:40:15

Python應用程序

2021-02-28 21:25:13

比特幣加密貨幣基金

2023-04-26 00:15:32

python面向對象java

2021-07-02 14:14:14

Python對象設計

2021-07-16 10:23:47

Python設計對象

2023-04-19 08:43:52

Python面向對象編程

2009-01-16 08:52:26

面向對象OOP編程

2010-07-20 09:13:55

Perl面向對象編程

2024-05-27 00:00:00

C# 類參數數據

2016-11-15 14:53:15

2021-09-15 09:12:56

Python元編程元數據

2013-01-24 09:55:10

ARM英特爾移動芯片

2023-07-06 08:31:50

Python對象編程

2017-04-21 09:07:39

JavaScript對象編程
點贊
收藏

51CTO技術棧公眾號

一区二区国产精品视频| 色综合天天综合网天天看片| 999视频在线免费观看| 久久午夜鲁丝片午夜精品| 欧美a级网站| 欧美亚洲图片小说| 999一区二区三区| 中文字幕在线观看日本| 高清成人免费视频| 国产精品丝袜久久久久久不卡| 国产午夜福利100集发布| 五月婷婷六月色| 免费成人在线观看| 97国产精品人人爽人人做| 大胸美女被爆操| 欧美18xxxx| 7777精品伊人久久久大香线蕉| 浮妇高潮喷白浆视频| 成人免费在线| 国产日韩av一区二区| 波多野结衣成人在线| 中文字幕网址在线| 亚洲一区一卡| 欧美激情18p| 最新av电影网站| 国产剧情在线观看一区| 欧美大胆一级视频| 伊人色在线视频| 国产一区二区主播在线| 精品久久久视频| 久久亚洲a v| av软件在线观看| 亚洲国产精品传媒在线观看| 国产在线精品一区在线观看麻豆| 久久99国产精品久久久久久久久| 国产又粗又猛又爽又黄的视频小说| 欧美黑人巨大videos精品| 日韩免费观看高清完整版| 天堂一区在线观看| 日韩高清中文字幕一区二区| 偷拍一区二区三区| 国产freexxxx性播放麻豆| а√天堂资源地址在线下载| 国产va在线播放| 深夜福利一区二区三区| 欧美日韩久久久一区| 欧美 日韩精品| 黄在线观看免费网站ktv| 一区二区三区免费网站| 国产资源第一页| 国产黄大片在线观看画质优化| 国产精品午夜在线| 亚洲欧美精品在线观看| 永久免费av在线| 国产欧美日韩另类一区| 日韩成人av电影在线| 日本福利片高清在线观看| 99久久国产免费看| 精品日本一区二区| 亚洲 欧美 自拍偷拍| 91女人视频在线观看| 裸模一区二区三区免费| 黄色网址在线播放| 国产精品久久久久婷婷| 中文字幕黄色大片| 亚洲七七久久综合桃花剧情介绍| 一区二区三区四区不卡在线 | 国内av一区二区| 国产一区精品二区| 欧美精品一区在线观看| 中文字幕一区二区人妻在线不卡| 伊人久久大香线蕉| 在线播放国产一区二区三区| 亚洲熟女毛茸茸| 国产福利第一页| 波多野结衣一区| xxxxxxxxx欧美| 综合五月激情网| 亚洲国产一区二区三区a毛片| 97av视频在线| 中文字幕在线观看精品| 国产裸体歌舞团一区二区| 粉嫩精品一区二区三区在线观看 | 国产精品久久久久久久久毛片 | 亚洲国产日韩美| 久久久久久国产精品免费无遮挡 | 久久久久久夜精品精品免费| 亚洲日本欧美在线| 蜜桃传媒在线观看免费进入| 色综合网色综合| 91亚洲一区二区| 少妇久久久久| 欧美成人亚洲成人| 91浏览器在线观看| 久久精品国产一区二区| 高清日韩一区| 波多野结衣在线网站| 一区二区三区精品久久久| 女人另类性混交zo| 日韩亚洲精品在线观看| 亚洲石原莉奈一区二区在线观看| 男女羞羞免费视频| 日韩激情视频网站| ts人妖另类在线| av播放在线| 性欧美疯狂xxxxbbbb| 五月天激情播播| 婷婷综合成人| 色综合久久悠悠| 中文字幕在线观看免费| 久久一二三国产| 91久久免费观看| 三级4级全黄60分钟| 美女精品视频在线| 在线视频欧美性高潮| 国产精品500部| 国产精品一区免费视频| 日韩一本精品| 五月天av在线| 精品久久99ma| 最新一区二区三区| 日本女人一区二区三区| 欧美精品二区三区四区免费看视频| av黄在线观看| 欧美久久免费观看| 亚洲成人网在线播放| 精品动漫av| 91国产在线播放| 黄网站免费在线观看| 欧美亚洲综合网| 日韩人妻无码一区二区三区| 亚洲第一黄网| 国产精品国产精品国产专区不卡| 岛国成人毛片| 884aa四虎影成人精品一区| 日韩不卡av在线| 久久久国产亚洲精品| 久精品国产欧美| 成人免费网站观看| 精品国产不卡一区二区三区| 欧美成人一二三区| 国产高清久久久| xxxxxx在线观看| 香港久久久电影| 欧美久久精品一级黑人c片| 国产一区二区在线视频聊天 | 九九热最新地址| 久久狠狠亚洲综合| 一区二区在线不卡| 欧美亚洲综合视频| 久久精品福利视频| 国产成人精品免费看视频| 亚洲激情av在线| 不许穿内裤随时挨c调教h苏绵| 欧美成人国产| 国产精品一区二区在线观看| sm在线播放| 亚洲欧美日韩图片| 久草热在线观看| 欧美久久一区二区三区| 亚洲国产精品久久久久秋霞不卡 | 性猛交娇小69hd| 日韩不卡手机在线v区| 亚洲免费视频一区| 精品成人18| 久久久久久久久久久人体 | 精品国产一区二区三区久久| 亚洲专区在线播放| 亚洲精品中文字幕在线观看| 亚洲色图欧美另类| 久久国产精品亚洲77777| 色噜噜狠狠一区二区三区| 97久久中文字幕| 国产做受高潮69| 国产在线黄色| 欧美一区二区视频在线观看2020| 国产一级视频在线播放| 久久久久久**毛片大全| 九九热99视频| 国精品一区二区| 热re99久久精品国产99热| 国产精品一区二区精品| 亚洲91av视频| 午夜免费福利在线观看| 精品久久久久av影院| 免费的毛片视频| 亚洲卡通动漫在线| 成人午夜剧场视频网站| 国产曰批免费观看久久久| av高清在线免费观看| 成人三级视频| 国产伦精品一区二区三区高清| 少妇一区视频| 欧美大片欧美激情性色a∨久久| 外国精品视频在线观看| 欧美日本在线看| 三级黄色在线视频| 日韩一区中文字幕| 国产福利在线观看视频| 久久精品国产精品亚洲精品| 日韩欧美亚洲天堂| 99久久99热这里只有精品| 国产一区高清视频| 日韩一级特黄| 日韩美女视频免费看| 三级网站视频在在线播放| 中文日韩在线观看| 天天摸天天碰天天爽天天弄| 欧美一区二区在线视频| 中文字幕+乱码+中文乱码www| 亚洲成av人在线观看| 男女全黄做爰文章| 久久久久久久免费视频了| 日本xxxx免费| 久久99国产精品尤物| 美女网站免费观看视频| 亚洲另类视频| 日本丰满大乳奶| 久久精品不卡| 日本三级中国三级99人妇网站 | 日产中文字幕在线精品一区 | 一区二区免费在线观看| 久久av免费| 精品久久久久久乱码天堂| 99re久久| 国产精品毛片a∨一区二区三区|国| 黑人玩欧美人三根一起进| 久久伊人精品一区二区三区| 免费国产a级片| 丁香婷婷久久| 日韩av电影手机在线| h片在线观看下载| 欧美精品videos性欧美| 性欧美高清come| 欧美老女人在线视频| 182tv在线播放| 精品自拍视频在线观看| 自由的xxxx在线视频| 久热在线中文字幕色999舞| 黄色成人影院| 美女性感视频久久久| 在线观看wwwxxxx| 精品中文字幕视频| 日本动漫理论片在线观看网站| 成年无码av片在线| 天堂av中文在线| 欧美激情视频一区二区三区不卡| 波多野结衣人妻| 亚洲一区二区三区四区在线| 97在线观看免费高| 亚洲欧美一区二区视频| 久久嫩草捆绑紧缚| 日韩理论在线观看| 神马久久精品综合| 亚洲精品乱码久久久久久日本蜜臀| 亚洲精品卡一卡二| 一区二区三区欧美| 欧美精品亚洲精品日韩精品| 丁香五六月婷婷久久激情| 中文字字幕在线中文| 台湾亚洲精品一区二区tv| 国产欧美在线看| 国产在线不卡一区二区三区| 99三级在线| 欧美在线关看| 色播亚洲婷婷| 一本一道久久a久久精品蜜桃| 第九区2中文字幕| 亚洲三级视频| 成人久久久久久久久| 日韩精品亚洲一区二区三区免费| 美女网站色免费| 国产老女人精品毛片久久| 日本精品一二三区| 久久众筹精品私拍模特| 国产精品无码无卡无需播放器| 国产精品美女久久久久久久久| 91九色丨porny丨极品女神| 亚洲二区在线观看| 波多野结衣黄色| 欧美一区二区三区免费| 日韩在线视频观看免费| 伊是香蕉大人久久| 精品人妻人人做人人爽夜夜爽| 97久久夜色精品国产| 成人在线视频一区二区三区| 久久人人精品| 爱情岛论坛亚洲自拍| 久久综合久久久久88| 欧美成人精品欧美一级私黄| 日本道精品一区二区三区| 不卡视频免费在线观看| 亚洲网站在线播放| 香蕉成人app免费看片| 国产大片精品免费永久看nba| 91国内精品白嫩初高生| 日本在线视频不卡| 999在线观看精品免费不卡网站| 男女污污的视频| 不卡av电影在线播放| 99久久久无码国产精品不卡| 欧美日韩免费在线观看| av网站在线观看免费| 亚洲香蕉伊综合在人在线视看| 伦理在线一区| 成人激情视频在线播放| 国产精品一区二区三区av麻| 国产色一区二区三区| 国产在线精品国自产拍免费| 懂色av蜜桃av| 欧美日韩中文字幕在线| 亚洲乱码精品久久久久..| 色吧影院999| 三级成人黄色影院| 韩国精品一区二区三区六区色诱| 欧美黄色免费| 伊人影院综合在线| 国产性天天综合网| 青草视频在线观看免费| 亚洲电影免费观看高清| 超碰电影在线播放| 成人网在线视频| 欧美熟乱15p| 91蝌蚪视频在线观看| 99久久精品免费看| 久久精品视频8| 日韩亚洲欧美高清| 国产精品白嫩白嫩大学美女| 免费在线观看一区二区三区| 免费黄色三级网站| 亚洲国产精品久久久久秋霞影院| 99热这里只有精品在线观看| 日韩中文字幕精品视频| 日韩毛片一区| 日韩精品另类天天更新| 久久午夜电影| 国产美女永久免费无遮挡| 在线免费观看成人短视频| 国产一区二区三区福利| 日产精品久久久一区二区福利| 婷婷综合电影| 国产黄色特级片| 中文字幕欧美国产| 中文字幕精品无码亚| 久久精品久久久久久国产 免费| 免费日韩成人| 色呦呦网站入口| 国产精品亚洲一区二区三区妖精| 激情五月少妇a| 精品成a人在线观看| 精精国产xxxx视频在线播放| 久热这里只精品99re8久 | 国产亚洲精品福利| 最近中文字幕在线观看视频| 色偷偷91综合久久噜噜| 国产精品欧美一区二区三区不卡 | 日韩av综合在线| 日韩av网站在线| 蜜臀国产一区| 亚洲国产一区二区在线| 国产制服丝袜一区| 久久久久亚洲天堂| 日韩成人在线免费观看| 日韩成人亚洲| 三年中文高清在线观看第6集| 国产精品1区2区3区| 好吊操这里只有精品| 国产午夜精品全部视频在线播放 | heyzo高清国产精品| 鲁鲁狠狠狠7777一区二区| 美女视频一区二区三区| 欧美成人aaa片一区国产精品| 欧美精品一区二区久久久| 日韩三区免费| 国产成人三级视频| 91蜜桃婷婷狠狠久久综合9色| 久久精品偷拍视频| 欧美日韩爱爱视频| 国产欧美日韩免费观看| 亚洲自拍第三页| 狠狠做深爱婷婷久久综合一区 | 亚洲国产日韩综合久久精品| 欧美日韩国产亚洲沙发| 国产日韩欧美在线视频观看| 亚洲视频精品| 国产精品久久久久无码av色戒| 91成人免费| 国产3p露脸普通话对白| 欧美韩国一区二区| va视频在线观看| 国产成人精品免高潮在线观看| 亚洲精品小说| 精品成人av一区二区三区| 欧美一级生活片| 欧美精品高清| 97中文字幕在线| 国产精品区一区二区三| 天天综合天天综合| 91传媒在线免费观看| 日韩av电影天堂|