是否有更多的Pythonic方法来测试一个对象是一个数字还是返回它的值?

时间:2013-12-07 00:26:39

标签: python python-2.7

我还没有尝试装饰器或功能内的功能,但这种当前的非pythonic方法似乎有点复杂。当我检查return_type(3次)时,我不喜欢我需要重复自己吗?

欢迎任何建议,特别是如果可以优雅地处理重复。请注意,如果对象是一个数字,我对众多参考测试并不感兴趣,因为我相信这部分已经包含在我的解决方案中。我有兴趣解决3x重复问题以处理返回类型。此外,虽然我很欣赏locale方法是处理国际化的更严格的方法,但我更喜欢简单地允许调用者更灵活地选择字符。

由于

def is_number(obj, thousand_sep=',', decimal_sep=None, return_type='b'):
    """ determines if obj is numeric.

    if return_type = b, returns a boolean True/False
    otherwise, it returns the numeric value

    Examples
    --------
    >>> is_number(3)
    True
    >>> is_number('-4.1728')
    True
    >>> is_number('-4.1728', return_type='n')
    -4.1728
    >>> is_number(-5.43)
    True
    >>> is_number("20,000.43")
    True
    >>> is_number("20.000,43", decimal_sep=",", thousand_sep=",")
    True
    >>> is_number("20.000,43", decimal_sep=",", thousand_sep=".", return_type="n")
    20000.43
    >>> is_number('Four')
    False
    # I am a few light years away from working that one out!!!
    """
    try:
        if is_string(obj):
            if decimal_sep is None:
                value = float(obj.replace(thousand_sep, ""))
            else:
                value = float(obj.replace(thousand_sep, "").replace(decimal_sep, "."))
            if return_type.lower() == 'b':
                return True
            else:
                return value
        else:
            value = float(obj)
            if return_type.lower() == 'b':
                return True
            else:
                return value
    except ValueError:
        return False
        if return_type.lower() == 'b':
            return False
        else:
            return None

2 个答案:

答案 0 :(得分:2)

我可能将这些逻辑分开......我认为这可以做你想做的事情......

def get_non_base_10(s):
    #support for base 2,8,and 16
    if s.startswith("O") and s[1:].isdigit():
       return int(s[1:],8)
    elif s.startswith("0x") and s[2:].isdigit():
       return int(s[2:],16)
    elif s.startswith("0b") and s[2:].isdigit():
         return int(s[2:],2)

def get_number(s,decimal_separator=".",thousands_separator=","):
    if isinstance(s,basestring):
       temp_val = get_non_base_10(s)
       if temp_val is not None:
          return temp_val
       s = s.replace(decimal_separator,".").replace(thousands_separator,"")
    try:
       return float(s)
    except ValueError:
       return "nan"

def is_number(s,decimal_separator=".",thousands_separator=",",return_type="b"):
    numeric = get_number(s,decimal_separator,thousands_separator)
    return numeric if return_type != "b" else numeric != "nan"

答案 1 :(得分:2)

使用正则表达式,您可以这样做:

import re
regex = re.compile( r'[+-]{0,1}\d{1,3}(,\d\d\d)*(\.\d+)*'

现在,如果您有字符串txt,请执行以下操作

regex.sub( '', txt, count=1 )

如果该字符串是,为千位分隔符且.为小数分隔符的数字,则最终会出现一个空字符串。

此方法强制执行严格 3位千位分隔符。所以例如20,0001.43不是数字,因为千位分隔符是错误的。 1220,001.43不是一个数字,因为它缺少,

def numval( txt ):
    import re
    regex = re.compile( r'[+-]{0,1}\d{1,3}(,\d\d\d)*(\.\d+)*'
    if regex.sub( '', txt.strip(' '), count=1 ) != '':
        raise ValueError ( 'not a number' )
    else:
        return float( txt.replace( ',', '' ))