【问题标题】:Explaining get() method with **kwargs?用 **kwargs 解释 get() 方法?
【发布时间】:2018-04-22 02:36:48
【问题描述】:

试图弄清楚这段代码是如何工作的。

我知道**kwargs 返回一个字典,get() 函数在字典中搜索给定键,如果找不到则返回默认值。 但是在我不明白的代码中,get() 方法是否正在搜索例如:“clock”或 self.clock 或两者兼而有之。

def update(self, *args, **kwargs):
    self.screen = kwargs.get("screen",self.screen)
    self.clock = kwargs.get("clock",self.clock)
    self.active = kwargs.get("active",self.active)

这里是一个调用这个方法的例子:

debug.update(active = numActive)

根据我的理解,变量 numActive 通过 update 方法作为 active 传递,然后作为 **kwargs 传递,然后通过 get() 方法搜索。既然我知道需要多少参数,我就不能删除kwargs 的使用吗?

感谢您对理解的任何帮助。

【问题讨论】:

    标签: python methods keyword-argument


    【解决方案1】:

    get方法中的第二个参数是默认值。

    根据Python2.7的文档:

    get(key[, 默认])

    如果键在字典中,则返回键的值,否则返回默认值。如果 默认没有给出,它默认为None,所以这个方法永远不会 引发 KeyError。

    来源:https://docs.python.org/2/library/stdtypes.html#dict.get

    说明 当您尝试从字典中“获取”某些内容时,如果找不到键或值为 None,它将返回 None。

    但是,如果您提供第二个参数(这是默认值),当且仅当没有找到该键时,才会返回默认值。

    没有默认值的示例

    对于以下代码:

    some_dict = {
        "key_1": 1,
        "key_2": None,
    }
    print some_dict.get("key_1")
    print some_dict.get("key_2")
    print some_dict.get("key_3")
    

    你会得到输出:

    1
    None
    None
    

    默认示例

    如下代码

    some_dict = {
        "key_1": 1,
        "key_2": None,
    }
    print some_dict.get("key_1", 1)
    print some_dict.get("key_2", 2)
    print some_dict.get("key_3", 3)
    

    你会得到输出:

    1
    None
    3
    

    查看您的代码

    我会在 cmets 中解释你的代码:

    def update(self, *args, **kwargs):
        # If the kwargs contain the key 'screen', the following get method will
        # return its value, or else it would remain whatever value was in 
        # self.screen's variable before
        self.screen = kwargs.get("screen",self.screen)
    
    
        # If the kwargs contain the key 'clock', the following get method will
        # return its value, or else it would remain whatever value was in 
        # self.clock's variable before
        self.clock = kwargs.get("clock",self.clock)
    
        # If the kwargs contain the key 'active', the following get method will
        # return its value, or else it would remain whatever value was in 
        # self.active's variable before
        self.active = kwargs.get("active",self.active)
    

    希望这会有所帮助。干杯。

    【讨论】:

      【解决方案2】:

      这个表达式:

      kwargs.get("screen",self.screen)
      

      等价于这个表达式:

      kwargs["screen"] if "screen" in kwargs else self.screen
      

      此声明:

      self.screen = kwargs.get("screen",self.screen)
      

      等价于这些语句:

      if "screen" in kwargs:
          self.screen = kwargs["screen"]
      else:
          self.screen = self.screen
      

      请注意,它等同于这些语句:

      if "screen" in kwargs:
          self.screen = kwargs["screen"]
      

      因为声明

      self.screen = self.screen
      

      如果self.screen 尚未定义,则引发AttributeError。通过运行以下程序查看该错误:

      d = {}
      x = object()
      x.attr = d.get("attr", x.attr)
      

      您可以通过实现update 来取消kwargs,而不是:

      def update(self, screen=None, clock=None, active=None):
          if screen is not None: self.screen = screen
          if clock is not None: self.clock = clock
          if active is not None: self.active = active
      

      然后您可以调用debug.update 并指定您想要的任何关键字参数。以这种方式定义它的优点是,如果您尝试使用 screenclockactive 以外的关键字参数调用它,它会引发 TypeError

      需要注意的是,如果你真的想说debug.update(screen = None),那么这样称呼它实际上什么也没做;它没有将debug.screen 设置为None。解决此问题的一种方法是将其写在文件顶部:

      _UNSPECIFIED = object()
      

      然后将update实现为:

      def update(self, screen=_UNSPECIFIED, clock=_UNSPECIFIED, active=_UNSPECIFIED):
          if screen is not _UNSPECIFIED: self.screen = screen
          if clock is not _UNSPECIFIED: self.clock = clock
          if active is not _UNSPECIFIED: self.active = active
      

      【讨论】:

      • 这很完美,我认为按照您建议的方式删除 kwargs 是最好的解决方案,因为屏幕、时钟和活动中的任何一个都没有设置为无。感谢您的回复!
      【解决方案3】:

      kwargs.get() 检索传递给函数的关键字参数。

      第一个参数是关键字,如果没有为关键字提供参数,则第二个是默认值。

      from uuid import uuid4
      
      def my_function(**kwargs):
          id = kwargs.get("id", uuid4().hex[:6])
          name = kwargs.get("name", None)
          print(f"{id} - {name}")
      
      my_function(name="Alice")
      

      a1b2c3 - 爱丽丝

      my_function(name="Bob", id="d4e5f6")
      

      d4e5f6 - 鲍勃

      my_function()
      

      g7h8i9 - 无

      【讨论】:

        【解决方案4】:
        self.screen = kwargs.get("screen",self.screen)
        

        这会从kwargs 获取“屏幕”值。如果它不存在,它只是使用此刻恰好在屏幕中的任何内容并将其塞回屏幕。和它一样

        if "screen" in kwargs:
            self.screen = kwargs["screen"]
        

        换句话说,update 仅更改作为关键字参数传递的值。这似乎是做一件简单事情的复杂方法。它必须有一个用例,但一般来说,很糟糕。

        既然我知道需要多少参数,我就不能删除 kwargs 的使用吗?

        在示例中,没有。它将设置零、一个两个或三个属性,具体取决于它们是否在kwarg 中。您甚至可以输入其他值,例如 update(foo="bar"),它会忽略它们。

        所以,这里有两种设置属性的方法:

        debug.update(active = numActive)
        debug.active = numActive
        

        我倾向于第二种方式。俯身方式

        【讨论】:

        • 嗨,我很难理解这一点,但使用 debug.active = numActive 对我来说似乎更有意义。我在想有没有办法摆脱使用kwargs?我认为用例没有你想象的那么严重。
        • 你必须搜索你的代码库并修复使用它的人。我做了一些类似的事情(只是有点!),以便对象可以在运行时挑选和选择动态配置参数。看看它是如何使用的,如果它看起来不合理,那么我肯定会改变它。
        • 感谢您的回复,但我认为您有点高估了我哈哈,这是我第一次使用类并在 python 中编写项目!我会不好意思向你展示我自己的代码,更不用说从你的代码中汲取灵感了。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-01-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多