亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

是否有允許您正確覆蓋魔術方法的 PyObject 類的實現?

是否有允許您正確覆蓋魔術方法的 PyObject 類的實現?

一只斗牛犬 2022-12-20 15:28:44
list所以我在一本書中讀到,如果你想從,dict或等內置類型擴展str,并想覆蓋魔術方法,你應該分別使用UserList,UserDict和UserString來自collections模塊。顯然,這是因為基類是在 CPython 中實現的,其中這些方法不會相互調用,因此覆蓋它們不會產生不良影響。我想知道是否與UserList類等類似,是否存在一個可用于“正確”從類擴展的object類。我查看了PyObject 文檔并找到了這篇文章以及這篇文章,但我既不想在 C 中擴展,也不想說出來。collections我在模塊或其他任何地方都找不到任何東西。
查看完整描述

1 回答

?
一只萌萌小番薯

TA貢獻1795條經驗 獲得超7個贊

正如評論中所述 - 沒有這樣的東西,也不需要它 - 中的所有魔術方法都object可以被覆蓋并且可以正常工作。


字典、列表和其他集合會發生什么,正如 MisterMiyagi 在評論中解釋的那樣,例如,dictget不會使用該__getitem__方法,因此如果您要自定義其行為,您還必須重寫get. 正確解決這個問題的類,允許人們用最少的可重用代碼創建完全可用的映射、序列和集合,這些類是在collections.abc模塊中定義的。


現在,如果您希望其中一種魔術方法對一個對象的類而不是該類的實例起作用,則必須在該類的類中實現這些方法——這就是“元類”。


這與“超類”有很大不同——超類定義了子類繼承的方法和屬性,這些方法和屬性在子類中可用。但是類上的魔術方法只影響實例,而不影響類本身(__init_subclass__, 和當然除外__new__,它可以更改為做其他事情而不是創建新實例)。


元類控制類的構建方式 (使用__new__,__init__和__call__方法) - 并且允許擁有關于它們如何通過魔術方法表現的方法 - 我認為元類中的魔術方法如何在類中工作沒有特殊情況,與它們在類與普通實例的關系中的工作相比。如果您在元類上實現__add__, __getitem__,__len__所有這些都將適用于使用該元類創建的類。


如果您不想在元類本身中為該類編寫魔術方法,可以做的是創建一個元類,該元類將在被調用時自動創建另一個動態元類,并復制 dunder 方法到那個班級。但很難將其視為任何嚴肅應用程序中的“健康”設計——將魔法方法應用于類已經有點過頭了——盡管在某些情況下這樣做很方便。


因此,例如,如果您希望一個類具有一個__geitem__允許您檢索該類的所有實例的類,這將起作用:


class InstanceRegister(type):

    def __init__(cls, name, bases, namespace, **kw):

        super().__init__(name, bases, namespace, **kw)


        cls._instances = []


        original_new = cls.__new__

        def new_wrapper(cls, *args, **kw):

            if original_new is object.__new__:

                instance = original_new(cls)

            else:

                instance = original_new(cls, *args, **kw)

            cls._instances.append(instance)

            return instance


        cls.__new__ = new_wrapper


    def __len__(cls):

        return len(cls._instances)


    def __getitem__(cls, item):

        return cls._instances[item]

這將起作用,正如在本次互動會議中所顯示的那樣:


In [26]: class A(metaclass=InstanceRegister): pass                                                                                   


In [27]: a = A()                                                                                                                     


In [28]: len(A)                                                                                                                      

Out[28]: 1


In [29]: A[0] is a                                                                                                                   

Out[29]: True


查看完整回答
反對 回復 2022-12-20
  • 1 回答
  • 0 關注
  • 101 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號