【问题标题】:Check If Parameter Was Passed To Function Without Checking Value检查参数是否在不检查值的情况下传递给函数
【发布时间】:2020-01-11 12:16:57
【问题描述】:

我不确定这在 Python 中是否可行,我想知道是否有任何方法可以在运行时检查参数是否传递给 Python 函数而不对参数值进行某种检查?

def my_func(req, opt=0):
    return was_opt_passed() # Returns bool 

print(my_func(0)) # Prints False
print(my_func(0, 0)) # Prints True

如果可能的话,这在某些情况下会更好,因为它消除了记住和检查标记值的需要。有可能吗?

【问题讨论】:

  • 常见的约定是使用opt=None。如果有一种方法可以做你想做的事,那么这个约定就不会变得普遍。

标签: python python-3.x function parameter-passing


【解决方案1】:

正如 Mark 在他的评论中已经说明的那样,典型的约定是使用默认值 None。然后你可以在调用时检查它是否仍然是None

def my_func(req, opt=None):
    if opt is None:
        #opt wasn’t passed.
        return False
    #opt was passed
    return True

尽管如果您想对其他选项进行更多研究(在大多数情况下是非常规的),请随时查看these answers

【讨论】:

  • 他仍然可以将None作为参数传递,这意味着参数被传递。
  • 这就是为什么我链接到更复杂的答案,因为它们可以提供更深入的传递参数。尽管很少需要它。我的想法是这个问题已经按原样回答了。
【解决方案2】:

一种解决方案是使用装饰器/包装器。它们允许您与在运行时传递给您的函数的内容进行交互,然后按照您认为合适的方式处理所说的事情考虑以下代码:

def check_keywords(func):
    def wrapper(*args, **kwargs):
        if kwargs:
            print('Keyword was passed!')
        return func(*args, **kwargs)
    return wrapper

@check_keywords
def my_func(req, opt=0):
    print(req)

check_keywords 捕获该函数,如果它检测到关键字被传递到my_func,它就会打印一些东西。这个打印语句可以转换成你想要的任意代码。

例如:

my_func(1)
>>> 1

my_func(1, opt = 1)
>>> Keyword was passed!
>>> 1

【讨论】:

    【解决方案3】:

    检测参数是否被传递的标准方法是标记值;但是,如果你愿意丢失你的函数签名,你可以使用**kwargs

    def my_func(**kwargs):
      return 'opt' in kwargs
    print(my_func()) #=> False
    print(my_func(opt=0)) $=> True
    

    【讨论】:

      【解决方案4】:

      最好的方法是使用 *args 或 **kwargs。

      def was_opt_passed(*args, **kwargs):
        return len(args) > 0 or 'opt' in kwargs
      
      def my_func(req, *args, **kwargs):
          return was_opt_passed(*args, **kwargs) # Returns bool 
      
      print(my_func(0)) # Prints False
      print(my_func(0, 0)) # Prints True
      print(my_func(0, opt=0)) # Prints True
      print(my_func(0, not_opt=0)) # Prints False
      

      *args 收集传递给函数但尚未枚举的任何位置参数,而 **kwargs 收集传递给函数但尚未枚举的任何关键字参数。如果 args 包含位置参数,我们假设它是 opt 的,并且它必须已被传递。否则,如果它在 kwargs 中,它就通过了,然后如果我们在任何一个地方都没有找到它,它一定没有通过。

      另见https://docs.python.org/3/tutorial/controlflow.html#keyword-arguments

      【讨论】:

      • 虽然kwargs 是一个选项,但这个要求 OP 不指定关键字参数吗?例如,OP 不能使用命名关键字 opt 并让此代码工作。
      • 我已经修改为也处理位置参数您实际上可以在 **kwargs catchall 之前指定关键字参数,这些参数将被单独提取(例如,fn(req, opt=0, **kwargs )),但是如果你想在 kwargs 中找到它,你不能单独指定它。
      【解决方案5】:

      使用装饰器

          def check_opt_passed(methd):
              def m(req, *args, **kwarg):
                  # this will check even if opt is passed as positional argument
                  # and check if opt is passed not any other keyword
                  if args or (kwarg and 'opt' in kwarg):
                      print('opt is passed')
                  else:
                      print('opt is not passed')
                  return methd(req, *args, **kwarg)
      
              return m
      
          @check_opt_passed
          def my_func(req, opt=0):
              # dummy expression for testing
              return req * opt
      
      
          print(my_func(1))           # opt is not passed
          print(my_func(1, 0))        # opt is passed
          print(my_func(1, opt=0))    # opt is passed
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-11-14
        • 1970-01-01
        • 2016-11-26
        • 2022-08-18
        • 2017-01-27
        • 2016-05-07
        • 2014-07-09
        • 1970-01-01
        相关资源
        最近更新 更多