精品欧美一区二区三区在线观看 _久久久久国色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技術棧公眾號

久久久精品91| 人妻换人妻a片爽麻豆| 免费a级人成a大片在线观看| 国产一区二区三区在线观看精品| 欧美激情精品在线| 人人人妻人人澡人人爽欧美一区| 91成人短视频在线观看| 亚洲成人av一区二区三区| 三区精品视频| 空姐吹箫视频大全| 美女一区二区三区在线观看| 久久99热精品| 四季av中文字幕| 国产精品45p| 欧美日韩一区视频| 国产97在线 | 亚洲| 麻豆视频免费在线观看| 久久综合久色欧美综合狠狠| 99久久久精品免费观看国产| 中文字幕乱伦视频| 日韩一级网站| 久久69精品久久久久久久电影好 | 久久精品网站免费观看| 91传媒视频免费| 国产无遮挡又黄又爽又色视频| 欧美国产91| 中文字幕欧美在线| 法国伦理少妇愉情| 成人激情自拍| 91精品国产欧美一区二区18| 热久久精品国产| 精品人人视频| 亚洲一区二区三区在线看| 亚洲人体一区| 搞黄视频在线观看| 久久久精品免费网站| 国产精品日韩一区二区免费视频| 国产精品无码AV| 青娱乐精品视频| 日本免费一区二区三区视频观看| 国产无套内射又大又猛又粗又爽| 欧美在线高清| 欧美国产在线电影| 波多野结衣亚洲色图| 99久精品视频在线观看视频| 中文精品99久久国产香蕉| 中文字幕一区二区三区人妻电影| 日韩av中文字幕一区| 欧美变态口味重另类| 一级黄色片国产| 国产亚洲观看| 日韩情涩欧美日韩视频| 两女双腿交缠激烈磨豆腐 | 国产一级精品aaaaa看| 亚洲av无码乱码国产麻豆| 国产麻豆成人精品| 成人在线免费网站| 天堂中文在线资源| 99国产精品一区| 欧美精品欧美精品| 成人免费在线视频网| 国产精品乱人伦中文| 宅男av一区二区三区| 国产色在线观看| 一区二区三区加勒比av| 青青青青在线视频| 678在线观看视频| 富二代精品短视频| 国产成人av影视| 日韩专区视频网站| 日韩一区二区免费电影| 精品无码av一区二区三区| 国产精品美女在线观看直播| 亚洲国内精品视频| 精品无人区无码乱码毛片国产| 欧美色图一区| 久热爱精品视频线路一| 国产精品99re| 久久久精品五月天| 国产精品一区二区久久| www.国产.com| 久久久综合视频| 一本一道久久久a久久久精品91 | 奇米四色中文综合久久| 日本一区二区三区久久| 国产成人av电影在线观看| 久久99热只有频精品91密拍| 91精彩视频在线观看| 亚洲欧美日韩国产综合在线| 国产免费裸体视频| 日韩精品三区| 日韩三级在线免费观看| 波多野结衣 在线| 亚洲欧美文学| 国产成人avxxxxx在线看| 国产手机av在线| 26uuu精品一区二区| 中文字幕一区二区三区在线乱码 | 欧美午夜激情影院| 欧美日韩国产高清| 国产精品吊钟奶在线| 精品久久久无码中文字幕| 久久综合九色综合97婷婷女人 | 黄色精品视频在线观看| 亚洲三级观看| 91精品啪aⅴ在线观看国产| 四虎在线视频免费观看| 日韩美女视频19| 免费在线观看的av网站| 婷婷综合国产| 日韩中文字幕在线视频| 中文字幕亚洲精品一区| 国产精品一区二区不卡| 日韩性感在线| 免费成人在线电影| 欧美tk—视频vk| 一区二区三区在线播放视频| 亚洲欧美日韩国产综合精品二区| 91久久国产综合久久蜜月精品| 狠狠狠综合7777久夜色撩人| 亚洲国产精品欧美一二99| 在线播放av中文字幕| 怕怕欧美视频免费大全| 国内揄拍国内精品少妇国语| 国产精品国产三级国产aⅴ| 久久久三级国产网站| 99久久免费观看| 国产一区二区视频在线看| 伊人久久久久久久久久久| 久久久午夜影院| 99这里只有久久精品视频| 污污污污污污www网站免费| 日韩深夜福利网站| 中文字幕综合在线| 国产午夜麻豆影院在线观看| 久久综合给合久久狠狠狠97色69| 亚洲 欧美 综合 另类 中字| 秋霞午夜一区二区三区视频| 久久久精品免费| 97超碰人人模人人人爽人人爱| 国产日韩精品一区二区三区在线| 亚洲国产精品久久久久婷蜜芽| 97久久综合区小说区图片区| 欧美激情综合亚洲一二区 | 丰满岳乱妇一区二区三区| 91免费视频黄| 日本一区二区三区播放| 欧美多人乱p欧美4p久久| aaa级黄色片| 亚洲男人的天堂av| 久久久无码人妻精品无码| 激情综合自拍| 精品国产一区二区三区四区vr| h片在线观看视频免费免费| 亚洲成人网久久久| 天堂网一区二区三区| 久久中文娱乐网| 黄色国产小视频| 成久久久网站| 91中文在线视频| 激情网站在线| 日韩成人在线观看| 成人毛片一区二区三区| 中文字幕不卡三区| 久久久九九九热| 精品成人免费| 欧美大香线蕉线伊人久久| 美女福利一区二区三区| 中日韩美女免费视频网站在线观看| 中文字幕福利视频| 亚洲欧美日韩中文播放| 亚洲啪av永久无码精品放毛片| 夜夜精品视频| 天天人人精品| 深夜激情久久| 欧美中文在线字幕| 在线免费黄色| 欧美mv和日韩mv的网站| 国产美女激情视频| 18成人在线观看| 亚洲欧美日韩色| 日本不卡一二三区黄网| 特级毛片在线免费观看| 国产另类在线| 国产精品自拍网| 欧美日韩经典丝袜| 亚洲一区二区国产| 精品国产av 无码一区二区三区| 亚洲第一搞黄网站| 亚洲一级片在线播放| 成人一区二区视频| 性chinese极品按摩| 亚洲第一黄色| 中文字幕一区二区三区5566| 欧美顶级毛片在线播放| 成人免费激情视频| 欧美巨大丰满猛性社交| 麻豆国产精品va在线观看不卡| 五月婷婷狠狠干| 91精品在线免费观看| 国产精品777777| 亚洲色图清纯唯美| 第一次破处视频| 成人晚上爱看视频| 国产一区二区在线观看免费视频| 亚洲伦理一区| 欧美交换配乱吟粗大25p| 九九久久婷婷| 国产日韩一区欧美| 日本免费精品| 91精品国产综合久久香蕉最新版 | 日韩中文字幕91| 中文字幕剧情在线观看一区| 影视先锋久久| 国产精品国产精品国产专区蜜臀ah | 日韩黄色网络| 国产a一区二区| 日韩精品中文字幕一区二区| 国产欧美日韩亚洲精品| 欧美精品日日操| 97久久超碰福利国产精品…| gogo在线观看| 日韩一区二区久久久| 国产一级片在线| 日韩av资源在线播放| 亚洲国产精品久久久久久久| 欧美精品一卡二卡| 在线观看中文字幕网站| 日本精品一区二区三区高清| 日操夜操天天操| 一区二区三区日韩欧美| h色网站在线观看| 亚洲人xxxx| 久久久久久视频| 国产精品二三区| 一区二区三区在线播放视频| 国产精品蜜臀av| 国产精品视频在| 中文字幕人成不卡一区| 国产中文字幕久久| 日韩理论片一区二区| 久久嫩草捆绑紧缚| 亚洲色图清纯唯美| 欧美精品videos极品| 亚洲制服丝袜av| 国产一级视频在线观看| 亚洲高清视频中文字幕| 国产精品第9页| 色综合久久久久综合99| 日本视频免费观看| 欧美吻胸吃奶大尺度电影| 中文字幕在线观看免费| 欧美另类z0zxhd电影| 国产又粗又猛又黄| 777久久久精品| 国产av无码专区亚洲av麻豆| 精品国产一区二区三区久久久蜜月 | 精品视频久久久久久久| 青青草超碰在线| 国产亚洲欧美日韩美女| 麻豆传媒视频在线观看| 理论片在线不卡免费观看| 91精选在线| 97精品国产91久久久久久| 女厕盗摄一区二区三区| 国产精品7m视频| 成人国产精品一区二区网站| av在线不卡一区| 你懂的视频欧美| 亚洲欧洲一区二区在线观看| 2023国产精品久久久精品双| 4444亚洲人成无码网在线观看 | 做a视频在线观看| 国产激情视频一区二区三区欧美| 亚洲高清无码久久| 国产校园另类小说区| 女性裸体视频网站| 亚洲一区免费在线观看| 日韩综合在线观看| 日韩天堂在线观看| 人人九九精品| 久久综合伊人77777蜜臀| 新版的欧美在线视频| 国产精品一区二区性色av | jizz亚洲女人高潮大叫| 91成人免费在线观看| 一区三区在线欧| 国产一区一区三区| 久久午夜激情| 人妻激情偷乱视频一区二区三区| 久久奇米777| 欧美日韩一级大片| 欧洲国内综合视频| 好吊色一区二区三区| 在线日韩精品视频| av成人影院在线| 成人精品视频99在线观看免费 | 一区二区三区视频| 99精品热6080yy久久| 日韩欧美国产片| 久久亚洲精品国产精品紫薇| 永久看片925tv| 欧美无乱码久久久免费午夜一区| 色窝窝无码一区二区三区| 日韩亚洲一区二区| 粉嫩一区二区三区| 九九九九久久久久| 欧美午夜久久| 成人不卡免费视频| 国产欧美一区二区三区鸳鸯浴| 日韩和一区二区| 精品区一区二区| 麻豆视频在线观看免费网站| 国产成人一区三区| 私拍精品福利视频在线一区| 久久人人爽人人爽人人av| 激情五月激情综合网| 潮喷失禁大喷水aⅴ无码| 色综合久久综合网欧美综合网| 亚洲精品一区二区三区蜜桃| 精品国偷自产在线视频| 日韩欧美精品电影| 久久久久欧美| 一本色道久久精品| 国产+高潮+白浆+无码| 亚洲伊人伊色伊影伊综合网| 99久久久久久久| 久久成人免费视频| 久久99久久久精品欧美| 日韩成人av网站| 日韩国产欧美视频| 亚洲黄色免费视频| 色菇凉天天综合网| 户外极限露出调教在线视频| 日本三级韩国三级久久| 日韩av午夜| 激情六月丁香婷婷| 久久久夜色精品亚洲| 色屁屁影院www国产高清麻豆| 亚洲国产精品久久久久秋霞不卡| 伦理在线一区| 国产伦精品一区二区三区高清 | 8x海外华人永久免费日韩内陆视频 | 国产亚洲永久域名| 99久久国产精| 色视频成人在线观看免| 精品久久久久一区二区三区 | 欧美成人性生活| 亚洲**毛片| 欧美一区二区中文字幕| 91丨porny丨户外露出| av黄色在线播放| 亚洲欧美制服另类日韩| 偷拍中文亚洲欧美动漫| 亚洲欧洲一区二区| 国产一区二区三区香蕉| av资源吧首页| 亚洲天堂av综合网| 香蕉久久久久久| 久久www视频| 99re8在线精品视频免费播放| 免费看污视频的网站| 综合av色偷偷网| 国产精品一区免费在线| 日韩中字在线观看| 久久久久久黄色| 97超碰人人草| 久久久久久久香蕉网| 亚洲美女久久| www.污污视频| 亚洲国产成人精品视频| 九色视频在线观看免费播放| 国产日韩精品在线观看| 黄色国产精品| 在线国产视频一区| 欧美狂野另类xxxxoooo| 三级网站视频在在线播放| 久久综合久久综合这里只有精品| 日本亚洲一区二区| 青娱乐在线视频免费观看| 精品视频久久久久久久| 日本免费一区二区三区等视频| 日本一道在线观看| 久久精品人人做人人综合| 国产精品爽爽久久| 国产91对白在线播放| 91精品国产自产拍在线观看蜜 | 色狼人综合干| 天堂中文av在线| 色就色 综合激情| av软件在线观看| 日韩国产精品一区二区三区| 国产一区二区毛片| 久久精品视频2| 欧美高清视频在线播放| 日本道不卡免费一区| 成人做爰69片免费| 欧美日韩三级一区| 妞干网免费在线视频| 成人短视频在线观看免费|