开发者社区> 问答> 正文

将Python复杂字符串输出(-0-0j)转换为等效的复杂字符串

在Python中,我希望有一种好方法可以将它的复数字符串输出转换为等效的字符串表示形式,在Python解释时,它会给出相同的值。 基本上,我希望函数complexStr2str(s: str): str具有eval(complexStr2str(str(c))与c不可区分的属性,对于任何类型为complex的c。然而,complexStr2str()只需要处理针对复杂值输出的str()或repr()类型的字符串模式。注意,对于复杂的值,str()和repr()执行相同的操作。 这里的“无法区分”并不是指Python意义上的==;你可以定义(或重新定义)它来表示你想要的任何东西;“区别”意味着如果字符串一分之一项目代表某个值,用绳子和替换程序中的b(这可能完全是一个),然后没有办法区分Python程序的运行和更换程序,程序的缺乏自省。 注意(-0-0j)与-0j不是一回事,尽管前者是Python将输出str(-0j)或repr(-0j)的内容。如下面的交互式会话所示,-0j的实部和虚部是-0,而-0-0j的实部和虚部是正0.0。 虽然在Python 3.5+ ish中可以从math中导入这些值,但是出于各种原因,我希望避免这样做。但是使用float(“nan”)是可以的。 考虑一下这个Python会话:

>>> -0j
(-0-0j)
>>> -0j.imag
-0.0
>>> -0j.real
-0.0
>>> (-0-0j).imag
0.0  # this is not -0.0
>>> (-0-0j).real
0.0  # this is also not -0.0
>>> eval("-0-0j")
0j # and so this is -0j
>>> atan2(-0.0, -1.0)
-3.141592653589793
>>> atan2((-0-0j).imag, -1.0)
3.141592653589793
>>> -1e500j
(-0-infj)
>>> (-0-infj)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'infj' is not defined

附录: 这个问题引起了一些骚动(例如,有一些人对这个问题及其公认的解决方案投了反对票)。这个问题已经被修改了很多次,所以有些评论可能已经过时了。 批评的主要观点是,一个人不应该这样做。从现有程序的文本中解析数据是一件经常发生的事情,有时您无法控制生成数据的程序。 一个相关的问题是,可以控制输出程序,但需要将其显示在文本中,即编写一个更好的repr()函数,该函数更适合浮点数和复数,并遵循最后描述的原则。这样做很简单,即使它有点难看,因为要完全做到这一点,您还需要在复合类型(如列表、元组、集合和字典)中处理float/complex。 最后,我要说的是,Python对复杂值的str()或repr()输出似乎没有帮助,因此,与其他支持复数作为基本数据类型或通过库支持复数的语言相比,这个问题对Python来说更具体。 这是一个展示这一点的环节:

>>> complex(-0.0, -0.0)
(-0-0j)  # confusing and can lead to problems if eval'd
>>> repr(complex(-0.0, -0.0))
'(-0-0j)' # 'complex(-0.0, -0.0)' would be the simplest, clearest, and most useful

注意,在执行诸如print()之类的输出时,会调用str()。repr()是这种用法的首选方法,但在这里它与str()相同,并且都存在inf和nan之类的问题。 对于任何内置类型(eval(repr(c))都应该与c难以区分。 问题来源StackOverflow 地址:/questions/59384884/converting-python-complex-string-output-like-0-0j-into-an-equivalent-complex

展开
收起
kun坤 2019-12-26 10:52:45 1049 0
1 条回答
写回答
取消 提交回答
  • 正如@wim在评论中指出的,这可能不是解决真正问题的正确方法;最好一开始就不要通过str将这些复数转换成字符串。关心正0和负0之间的差也是很不寻常的。但是我可以想象在一些罕见的情况下你确实关心这个差异,在它们得到str()'d之前访问复数是不可能的;这是一个直接的答案。 我们可以用正则表达式来匹配这些部分;[+-]?(?: [0-9.]|[eE][+-]?)我们需要在匹配的部分上使用str(float(…))来确保它们作为浮点字符串是安全的;所以如。'-0'映射到'-0'我们还需要无穷大和NaN的特殊情况,因此它们被映射到可执行的Python代码“float('…')”,这将生成正确的值。

    import re
    
    FLOAT_REGEX = r'[+-]?(?:(?:[0-9.]|[eE][+-]?)+|nan|inf)'
    COMPLEX_PATTERN = re.compile(r'^\(?(' + FLOAT_REGEX + r'\b)?(?:(' + FLOAT_REGEX + r')j)?\)?$')
    
    def complexStr2str(s):
        m = COMPLEX_PATTERN.match(s)
        if not m:
            raise ValueError('Invalid complex literal: ' + s)
    
        def safe_float(t):
            t = str(float(0 if t is None else t))
            if t in ('inf', '-inf', 'nan'):
                t = "float('" + t + "')"
            return t
    
        real, imag = m.group(1), m.group(2)
        return 'complex({0}, {1})'.format(safe_float(real), safe_float(imag))
    

    例子:

    >>> complexStr2str(str(complex(0.0, 0.0)))
    'complex(0.0, 0.0)'
    >>> complexStr2str(str(complex(-0.0, 0.0)))
    'complex(-0.0, 0.0)'
    >>> complexStr2str(str(complex(0.0, -0.0)))
    'complex(0.0, -0.0)'
    >>> complexStr2str(str(complex(-0.0, -0.0)))
    'complex(-0.0, -0.0)'
    >>> complexStr2str(str(complex(float('inf'), float('-inf'))))
    "complex(float('inf'), float('-inf'))"
    >>> complexStr2str(str(complex(float('nan'), float('nan'))))
    "complex(float('nan'), float('nan'))"
    >>> complexStr2str(str(complex(1e100, 1e-200)))
    'complex(1e+100, 1e-200)'
    >>> complexStr2str(str(complex(1e-100, 1e200)))
    'complex(1e-100, 1e+200)'
    

    字符串输入的例子:

    >>> complexStr2str('100')
    'complex(100.0, 0.0)'
    >>> complexStr2str('100j')
    'complex(0.0, 100.0)'
    >>> complexStr2str('-0')
    'complex(-0.0, 0.0)'
    >>> complexStr2str('-0j')
    'complex(0.0, -0.0)'
    
    2019-12-26 10:52:53
    赞同 展开评论 打赏
问答排行榜
最热
最新

相关电子书

更多
From Python Scikit-Learn to Sc 立即下载
Data Pre-Processing in Python: 立即下载
双剑合璧-Python和大数据计算平台的结合 立即下载