第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號(hào)安全,請及時(shí)綁定郵箱和手機(jī)立即綁定
已解決430363個(gè)問題,去搜搜看,總會(huì)有你想問的

將導(dǎo)入的函數(shù)設(shè)置為靜態(tài)字典中的成員

將導(dǎo)入的函數(shù)設(shè)置為靜態(tài)字典中的成員

有一個(gè)簡單的類,我想使用不同的方式在字典中靜態(tài)存儲(chǔ)一些函數(shù):import os, sysclass ClassTest():    testFunc = {}    def registerClassFunc(self,funcName):        ClassTest.testFunc[funcName] = eval(funcName)    @classmethod    def registerClassFuncOnClass(cls,funcName):        cls.testFunc[funcName] = eval(funcName)    @staticmethod    def registerClassFuncFromStatic(funcName):        ClassTest.testFunc[funcName] = eval(funcName)一些示例方法:def user_func():    print("I run therefore I am self-consistent")def user_func2():    print("I am read therefore I am interpreted")def user_func3():    print("I am registered through a meta function therefore I am not recognized")def user_func4():    print("I am registered through an instance function therefore I am not recognized")def user_func5():    print("I am registered through a static function therefore I am not recognized")還有一個(gè)小測試:if __name__ == "__main__":    a = ClassTest()    a.testFunc["user_func"] = user_func    a.testFunc["user_func"]()    a.testFunc["user_func2"] = eval("user_func2")    a.testFunc["user_func2"]()    ClassTest.testFunc["user_func"] = user_func    ClassTest.testFunc["user_func"]()    ClassTest.testFunc["user_func2"] = eval("user_func2")    ClassTest.testFunc["user_func2"]()    a.registerClassFunc("user_func5")  # does not work on import    a.testFunc["user_func5"]()    ClassTest.registerClassFuncFromStatic("user_func3") # does not work on import    ClassTest.testFunc["user_func3"]()    ClassTest.registerClassFuncOnClass("user_func4") # does not work on import    ClassTest.testFunc["user_func4"]()所有這些作品提供了所有這些元素都在同一個(gè)文件。一旦功能被分成 2 個(gè)文件和一個(gè)主文件:from ClassTest import ClassTestfrom UserFunctions import user_func,user_func2, user_func3, user_func4, user_func5if __name__ == "__main__":    a = ClassTest()    a.testFunc["user_func"] = user_func    ...只有前兩個(gè)繼續(xù)工作(直接設(shè)置函數(shù)),其他的 - 使用一個(gè)函數(shù)來做同樣的事情 -NameError在所有eval調(diào)用上給出一個(gè)。例如:NameError: name 'user_func5' is not defined。使用方法與直接設(shè)置功能時(shí)失去范圍的邏輯是什么?我可以使用來自其他包的導(dǎo)入來讓它工作,這樣我就可以使用方法而不是直接在類中放置任何函數(shù)嗎?
查看完整描述

1 回答

?
白豬掌柜的

TA貢獻(xiàn)1893條經(jīng)驗(yàn) 獲得超10個(gè)贊

問題

你是對的,這不起作用的原因是由于范圍問題。您可以通過檢查以下文檔eval來弄清楚發(fā)生了什么:


評估(表達(dá)式,全局=無,本地=無)


...如果兩個(gè)字典 [即全局變量和局部變量] 都被省略,則表達(dá)式在調(diào)用 eval() 的環(huán)境中執(zhí)行。


因此,可以合理地假設(shè)您遇到的問題歸結(jié)為被調(diào)用的內(nèi)容globals和locals上下文(即在 的定義(和可能的單獨(dú)模塊)內(nèi)ClassTest)eval。由于eval被調(diào)用的上下文通常不是您定義和/或?qū)氲纳舷挛?,因此就相關(guān)而言user_func, user_func2....,這些函數(shù)是未定義的eval。這一思路得到以下文檔的支持globals:


全局變量()


...這始終是當(dāng)前模塊的字典(在函數(shù)或方法中,這是定義它的模塊,而不是調(diào)用它的模塊)。


修復(fù)

對于如何修復(fù)此代碼,您有幾種不同的選擇。所有這些都將涉及l(fā)ocals從您調(diào)用的上下文傳遞,例如,ClassTest.registerClassFunc傳遞到定義該方法的上下文。此外,您應(yīng)該借此機(jī)會(huì)eval從您的代碼中排除使用(它的使用被認(rèn)為是不好的做法,它是一個(gè)巨大的安全漏洞,yadda yadda yadda)。鑒于locals這user_func是定義的范圍的字典,您可以隨時(shí)執(zhí)行以下操作:


locals['user_func'] 

代替:


eval('user_func')

修復(fù) #1

鏈接到此修復(fù)程序的實(shí)時(shí)版本


這將是最容易實(shí)現(xiàn)的修復(fù),因?yàn)樗恍枰獙?的方法定義進(jìn)行一些調(diào)整ClassTest(并且不需要更改任何方法簽名)。它依賴于可以inspect在函數(shù)中使用包直接獲取locals調(diào)用上下文的事實(shí):


import inspect


def dictsGet(s, *ds):

    for d in ds:

        if s in d:

            return d[s]

    # if s is not found in any of the dicts d, treat it as an undefined symbol

    raise NameError("name %s is not defined" % s)


class ClassTest():

    testFunc = {}

    def registerClassFunc(self, funcName):

        _frame = inspect.currentframe()

        try:

            _locals = _frame.f_back.f_locals

        finally:

            del _frame


        ClassTest.testFunc[funcName] = dictsGet(funcName, _locals, locals(), globals())


    @classmethod

    def registerClassFuncOnClass(cls, funcName):

        _frame = inspect.currentframe()

        try:

            _locals = _frame.f_back.f_locals

        finally:

            del _frame


        cls.testFunc[funcName] = dictsGet(funcName, _locals, locals(), globals())


    @staticmethod

    def registerClassFuncFromStatic(funcName):

        _frame = inspect.currentframe()

        try:

            _locals = _frame.f_back.f_locals

        finally:

            del _frame


        ClassTest.testFunc[funcName] = dictsGet(funcName, _locals, locals(), globals())

如果您使用上面給出的 定義ClassTest,您編寫的導(dǎo)入測試現(xiàn)在將按預(yù)期運(yùn)行。


優(yōu)點(diǎn)

完全提供最初預(yù)期的功能。


不涉及對函數(shù)簽名的更改。


缺點(diǎn)

調(diào)用inspect.currentframe()可能會(huì)導(dǎo)致性能下降,因此如果您計(jì)劃ClassTest每秒調(diào)用一百萬次方法,則可能無法使用此修復(fù)程序。


inspect.currentframe()只能保證在 CPython 上工作。將此代碼與 Python 的其他實(shí)現(xiàn)一起運(yùn)行時(shí),里程可能會(huì)有所不同。


修復(fù) #2

Fix #2 與 fix #1 基本相同,除了在此版本中您在調(diào)用點(diǎn)顯式傳遞locals到 的方法ClassTest。例如,在此修復(fù)下, 的定義ClassTest.registerClassFunc將是:


def registerClassFunc(self, funcName, _locals):

        ClassTest.testFunc[funcName] = dictsGet(funcName, _locals, locals(), globals())

你會(huì)像這樣在你的代碼中調(diào)用它:


a = ClassTest()

a.registerClassFunc("user_func5", locals())

優(yōu)點(diǎn)

不依賴于inspect.currentframe(),因此可能比修復(fù) #1 更具性能/便攜性。

缺點(diǎn)

您必須修改方法簽名,因此您還必須更改使用這些方法的任何現(xiàn)有代碼。


從這里開始,您必須將locals()樣板添加到每個(gè)ClassTest方法的每次調(diào)用中。


查看完整回答
反對 回復(fù) 2021-09-11
  • 1 回答
  • 0 關(guān)注
  • 164 瀏覽
慕課專欄
更多

添加回答

舉報(bào)

0/150
提交
取消
微信客服

購課補(bǔ)貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動(dòng)學(xué)習(xí)伙伴

公眾號(hào)

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號(hào)