Python 如何检查传递给函数的任何参数是否为None?

Python 如何检查传递给函数的任何参数是否为None?,python,Python,我有一个类似的方法 @staticmethod def add_transaction(name, date, amount, debit, user, category_id): pass 如果其中任何一个是None,最好的测试方法是什么 if not (name or date or amount or debit or user or category_id): raise ValueError 如果没有人会抛出错误,您可以直接使用函数,按照自己

我有一个类似的方法

    @staticmethod
    def add_transaction(name, date, amount, debit, user, category_id):
        pass
如果其中任何一个是
None
,最好的测试方法是什么

if not (name or date or amount or debit or user or category_id):
    raise ValueError

如果没有人会抛出错误,您可以直接使用函数,按照自己的意愿处理错误,而不是提前检查

if any(arg is None for arg in (name, date, amount, debit, user, category_id))):
    raise ValueError("I hate None")
您需要测试
arg是否为None
,而不仅仅是使用
not
。使用
not
,如果任何参数是
False
0
[]
等,则最终会引发异常,而这不是您想要的

@DSM建议,如果(姓名、日期…中没有,则
也有效-取决于您的喜好


旁注:您的函数需要很多参数。我想知道您是否能够以某种方式重构它-也许您可以创建一个封装此数据的
事务
类,并将此方法签名更改为
add\u事务(Transaction)< /p> > 

如果这是你计划使用的东西,你可能需要考虑一个装饰器:

import functools
def None_is_dumb_and_does_not_deserve_to_enter_this_function(func):
    @functools.wraps(func)
    def new_func(*args,**kwargs):
        if None in args:
            raise ValueError("None's aren't welcome here")
        return func(*args,**kwargs)
    return new_func

@None_is_dumb_and_does_not_deserve_to_enter_this_function
def foo(a,b,c):
    """Docstring"""
    print a,b,c

foo(1,2,3)
print foo.__doc__
foo(None,'bar','baz')
如果调用
foo(1,2,c=3)
,仍然会出现这种情况。我们可以使用以下模块解决此问题:


可以使用装饰师并执行以下操作:

from functools import wraps

def no_none(f):
  def wrapper(*args, **kwargs):
    if any(parm is None for parm in args):
      raise ValueError('None not allowed')
    return f(*args, **kwargs)
  return wrapper

class Testing(object):
  @staticmethod
  @no_none
  def add_transaction(name, date, amount, debit, user, category_id):
    pass

Testing.add_transaction(1, 2, 3, 4, 5, 6)
Testing.add_transaction(1, 2, 3, 4, 5, None)

pythonic的答案是:除非是从用户输入(或其他程序或子系统或设置文件等)获取数据的子系统入口点,否则不要浪费时间进行这种“验证”调用方有责任传递有效的参数,如果他不这样做,那么尝试使用这些参数将引发异常。

您确定要使用'or'和'not'和'?他想要
,这样,如果至少有一个参数是
None
my,就会引发
ValueError
糟糕,我纠正了它你的意图是什么?像关键字参数这样的东西可能更好!如果这是我的代码,我会把这些参数放在一个列表中,并说
如果不是全部(列表参数)
…为什么不
在(名称…)中没有
?因为
在(名称…)中没有
测试的是平等,而不是身份。@Lennartreegebro:如果有人不正当地制造了一个测试结果等于
无的对象,你是谁来反驳他呢?6个论点不是“很多”而且我们没有足够的上下文来知道添加事务类型是否是正确的做法。@Brunodesshuilliers:我们不知道上下文是对的,这只是一个建议。“多少就是太多了”这是一个个人偏好的问题-我想说六个参数太多了。缺点是你没有为未指定的关键字获取默认值,或者为无效的关键字获取错误。对于自动文档来说,下选-命名参数是一个好东西(tm),并且**Kwarg应该为两个通用函数保留(decorators等)或可选参数。向上投票-只要您的函数不是子系统的入口点,调用方就有责任传递有效的参数。True-fact.Was[不合理地]继续那个假设。@JonClements--谢谢。我实际上是想弄清楚我是否可以检查参数,并用相同的签名创建一个
new_func
,但我不确定这是可能的。这不需要。唯一的情况是我们的答案(我现在能想到)如果提供了太多的参数,并且装饰程序会失败,这将是错误的,因为其中一个参数是None,而不是函数调用失败,因为参数太多arguments@JonClements--出于文档目的,这很好,我在你的帖子上发布了另一个案例,我们的案例将失败。装饰师太棒了,我写了我的第一个案例根据您的建议,非常感谢!这个(和我的)唯一的问题是,如果用户通过关键字调用参数:
Testing.add\u transaction(1,2,3,4,5,category\u id=None)
import functools
def None_is_dumb_and_does_not_deserve_to_enter_this_function(func):
    @functools.wraps(func)
    def new_func(*args,**kwargs):
        if None in args:
            raise ValueError("None's aren't welcome here")
        return func(*args,**kwargs)
    return new_func

@None_is_dumb_and_does_not_deserve_to_enter_this_function
def foo(a,b,c):
    """Docstring"""
    print a,b,c

foo(1,2,3)
print foo.__doc__
foo(None,'bar','baz')
import decorator

@decorator.decorator
def no_none(f,*args,**kwargs):
    if None in args:
        raise ValueError("None's aren't welcome here")
    return f(*args,**kwargs)

@no_none
def foo(a,b,c):
    """Docstring"""
    print a,b,c

foo(1,2,3)
print foo.__doc__

try:
    foo(None,'bar','baz')
except ValueError as e:
    print ('Good, raised ValueError')

try:
    foo("bar","baz",c=None)
except ValueError as e:
    print ('Good, raised ValueError')
from functools import wraps

def no_none(f):
  def wrapper(*args, **kwargs):
    if any(parm is None for parm in args):
      raise ValueError('None not allowed')
    return f(*args, **kwargs)
  return wrapper

class Testing(object):
  @staticmethod
  @no_none
  def add_transaction(name, date, amount, debit, user, category_id):
    pass

Testing.add_transaction(1, 2, 3, 4, 5, 6)
Testing.add_transaction(1, 2, 3, 4, 5, None)