Python中调用的函数中的函数是什么?

时间:2019-06-14 21:19:18

标签: 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

因此,我将编写一个“获取”功能,并在其中编写一个“版本”,“正常运行时间”,“ cisco”,“ arris”和“ motorola”功能。在这些函数中,我将编写更多函数。

在Python中这叫什么?如何实施?我只需要知道我在寻找什么,就可以在文档中找到并学习。

3 个答案:

答案 0 :(得分:1)

将它们概念化为嵌套方法声明有点奇怪,除非您使用有限制的lambda,否则这在python中无法正常工作。这是您通常将类用于的功能类型,因为嵌套这些确实有效。因此,让我们将其实现为类!唯一的障碍是,get()必须要有一定的技巧,才能使其按您希望的方式工作,但是我们可以解决此问题。

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)

它的作用或多或少都相同。

答案 1 :(得分:0)

有多种方法可以实现此目的,而这些嵌套函数的术语取决于您的操作方式。最直接的方法是将函数定义为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建议的包含静态方法和嵌套类的类,但无论如何,fluent interface对于客户端仍然是可疑的。我认为可以肯定地说它不是特别Pythonic。

答案 2 :(得分:0)

您可以使用嵌套函数,但这不是一个好主意。您可以使用前缀名称命名函数