簡體   English   中英

Python 中調用的函數中的函數是什么?

[英]What are functions within functions called in Python?

這將是一個非常n00b的問題......

在python中,我想編寫一些函數來檢索幾種不同類型設備的軟件版本和系統正常運行時間。 我可以只為每個需求編寫一個函數,但我不想那樣做。 我想在函數中編寫函數,所以我可以用點號來調用它們。

以下是我希望創建的函數示例:

get(device)   # Determine device type and get software version and uptime
get.version(device)   # Determine device type and get software version 
get.uptime(device)    # Determine device type and get device up time
get.cisco.version(device)   # Get software version for a Cisco device
get.cisco.uptime(device)   # Get device up time for a Cisco device
get.arris.version(device)   # Get software version for an Arris device
get.arris.uptime(device)   # Get device up time for an Arris device
get.motorola.version(device)   # Get software versino for a Motorola device
get.motorola.uptime(device)   # Get device up time for a Motorola device

所以,我會寫一個“get”函數,然后我會寫一個“version”、“uptime”、“cisco”、“arris”和“motorola”函數。 在這些函數中,我會編寫更多函數。

這在 Python 中叫什么? 它是如何實施的? 我只需要知道我在尋找什么,這樣我就可以在文檔中找到它並學習。

將這些概念化為嵌套方法聲明有點奇怪,除非您使用 lambdas,否則在 python 中不能正常工作,這是有限制的。 這是您通常使用類來實現的功能類型,因為嵌套它們確實有效。 所以讓我們把它作為類來實現! 唯一的障礙是get()需要有點hacky才能讓它按照你想要的方式工作,但我們可以解決這個問題。

class get:
    # inner class cisco
    class cisco:
        @staticmethod
        def version(device):
            # do stuff

        @staticmethod
        def uptime(device):
            # do stuff

    # inner class motorola
    class motorola:
        ...

    # inner class arris
    class arris:
        ...

    # and now we define the stuff for the get class itself
    # (after the inner classes, because we need them to be defined
    # before we refer to them in the below methods

    def __new__(cls, device):
        # this is *supposed* to return a new instance of a `get`. 
        # We can override that behavior and have it return other things when `get()` is invoked
        return (get.version(device), get.uptime(device))

    @staticmethod
    def version(device):
        # do stuff

    @staticmethod
    def uptime(device):
        # do stuff

這允許以下所有內容按預期運行:

get(device)
get.version(device)
get.cisco.uptime(device)

缺點是您必須明確地編寫所有這些方法。 如果您像這樣嵌套類,則不能將get類用作get.ciscoget.motorola或其他東西的超類。

我還在上面使用了@staticmethod ,它允許您將方法放入類中,而無需使用額外的(隱式) clsself參數。 你可以更換

@staticmethod
def version(device)

@classmethod
def version(cls, device)

它的行為或多或少是一樣的。

有多種方法可以實現這一點,這些嵌套函數的術語取決於您如何做到這一點。 最直接的方法是將函數定義為 lambda:

a = lambda dev: "a"
a.b = lambda dev: "b"
a.b.c = lambda dev: "c"

print(a("foo"), a.b("bar"), a.b.c("baz"))

輸出:

a b c

這是一個稍微不那么做作的例子作為概念證明,盡管我沒有聲稱這是一個好的設計(我認為嵌套字典會更可取,並且您的“后端”(字典)可能應該以不同的方式組織,即使如果你確實像這樣嘗試)。

devices = {"baz": "some device"}
versions = {
    "motorola": "morotola thing",
    "arris": "arris thing",
    "cisco": "cisco thing"
}
cisco_versions = {"foo": "cisco foo thing"}

get = lambda dev: devices[dev]
get.version = lambda dev: versions[dev]
get.cisco = lambda: ""
get.cisco.version = lambda dev: cisco_versions[dev]

print(get("baz"))
print(get.version("arris"))
print(get.cisco.version("foo"))

輸出:

some device
arris thing
cisco foo thing

您也可以按照Green Cloak Guy 的建議使用包含靜態方法和嵌套類的類,但無論哪種方式,流暢的界面對於客戶端來說仍然是值得懷疑的。 我認為可以肯定地說它不是特別 Pythonic。

您可以使用嵌套函數,但這不是一個好主意。 您可以使用前綴名稱命名函數

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM