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

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

蟒蛇 | 實例化前的類方法裝飾器

蟒蛇 | 實例化前的類方法裝飾器

偶然的你 2023-05-23 14:25:30
前言:這個問題可能比標題所暗示的要簡單我正在嘗試實現一個簡單的事件處理程序系統,使用裝飾器將各種方法和函數“訂閱”到一個事件。1. 事件處理程序的簡單方法一種簡單的方法是創建一個類來添加和運行事件:# class for adding and running functions, aka an event handlerclass Runner:    def __init__(self):        self.functions = []    def add(self, function):        self.functions.append(function)    def run(self):        for function in self.functions:            function()runner = Runner()然后添加各種功能或方法:# random example functiondef myFunction():    print('myFunction')# random example classclass MyClass:    def myMethod(self):        print('myMethod')# getting instance of class & methodmyObject = MyClass()myObjectMethod = myObject.myMethodrunner.add(myFunction)runner.add(myObjectMethod)runner.run()這導致:> py main.pymyFunctionmyMethod好的!它按預期工作2.裝飾器方法所以這沒關系,但我最近了解了裝飾器,并認為我可以通過替換有點丑陋的runner.add()方法來整理語法。首先,我將Runner.add()方法更改為裝飾器:class Runner:    def __init__(self):        self.functions = []    def add(self, function):        self.functions.append(function)        return function # <-- returns function    def run(self):        for function in self.functions:            function()runner = Runner()然后我刪除runner.add()調用并插入裝飾器:@runner.adddef myFunction():    print('myFunction')class MyClass:    @runner.add    def myMethod(self):        print('myMethod')# myObject = MyClass()# myObjectMethod = myObject.myMethodrunner.run()這顯然會導致:> py main.pymyFunctionTraceback (most recent call last):...TypeError: myMethod() missing 1 required positional argument: 'self'顯然,這里的問題是我將“靜態”(或者它是“未綁定”?)添加myMethod到事件中,該事件與實例無關,因此沒有任何實例self。諸如此類的答案指的是實現裝飾器以在調用時包裝方法,但是我使用裝飾器的原因是您在初始代碼執行時獲得的訪問權限。一個想法是必須在MyClass.__init__()構造函數中運行一些東西,因為只有這樣才能創建一個實例并且您可以訪問self,但是那么如何僅在實例化時運行裝飾器呢?更不用說實現我們在這里追求的結果了。問題我有什么選擇來實現示例 1 中所示的行為,但語法盡可能接近示例 2(或任何其他“看起來干凈”的變體),因為它有點冗長、丑陋,而且肯定不像裝飾器那樣精簡runner.add()。
查看完整描述

1 回答

?
慕桂英4014372

TA貢獻1871條經驗 獲得超13個贊

函數和方法的處理方式略有不同,而不是一視同仁:

功能:

  • [A]正常添加函數到列表

方法:

  • self調用裝飾器時的未綁定方法,因此還沒有關聯的實例或值

  • [B]_tagged我們通過設置其屬性在方法未綁定時(在創建實例之前)“標記”該方法

  • [C]一旦創建了一個實例(并且self變量已經被填充),__init__()我們在里面搜索并添加所有標記的方法

  • 我們可以在之后添加方法,因為一旦它們被綁定到一個實例,參數self就會被填充(這意味著它在技術上沒有參數,類似于functools.partial()

import inspect


class Runner:

    def __init__(self):

        self.functions = []


    def add(self, function):

        if len(inspect.signature(function).parameters) == 0:

            # [A] adds if has no parameters

            self.functions.append(function)

        else:

            # [B] tags if has 1 parameter (unbound methods have "self" arg)

            function._tagged = True

        return function


    # [C] search through object and add all tagged methods

    def add_all_tagged_methods(self, object):

        for method_name in dir(object):

            method = getattr(object, method_name)

            if hasattr(method, '_tagged'):

                self.functions.append(method)


    def run(self):

        for function in self.functions:

            function()


runner = Runner()

然后使用與下面相同的初始代碼


@runner.add

def myFunction():

    print('myFunction')


class MyClass:

    def __init__(self):

        runner.add_all_tagged_methods(self)


    @runner.add

    def myMethod(self):

        print('myMethod')


myObject = MyClass()

myObjectMethod = myObject.myMethod


runner.run()


查看完整回答
反對 回復 2023-05-23
  • 1 回答
  • 0 關注
  • 138 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

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

幫助反饋 APP下載

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

公眾號

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