引入大整数常量的最优雅/Pythonic方式是什么?

3

我需要引入大整数常量(Diffie-Hellman密钥交换中的质数)。

以符合PEP8标准的方式,最Pythonic / 美观的方法是什么?最好不要使用反斜杠。

我目前的方法大致如下:

N = '''FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1
       29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD
       EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245
       E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED
       EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE65381
       FFFFFFFF FFFFFFFF'''
PRIME = int('0x{0}'.format(N.replace('\n', '').replace(' ', '')), 16)

不是非常美观,但比这个美观:

PRIME = 179769313486231590770839156793787453197860296048756011706444423684197180216158519368947833795864925541502180565485980503646440548199239100050792877003355816639229553136239076508735759914822574862575007425302077447712589550957937778424442426617334727629299387668709205606050270810842907692932019128194467627007L

编辑:

更改为PRIME = int(re.sub('\s+', '', N), 16)


1
0xffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece65381ffffffffffffffff(L)可以使用,但你的N更加优美。 - glglgl
你可以考虑一下,别人在查看你的源代码时可能会如何使用这个常量。无论你怎么写,他们都不会在脑海中验证它是否为质数。因此,他们实际上唯一会“阅读”它的方式可能是将其复制到其他代码或Mathematica中以验证其属性等。也许,你应该针对这种用例进行优化。也就是说,使用不太美观的解决方案 PRIME = 1797...。请记住,在正确性之后,源代码的主要目的不是漂亮,而是对读者有用。 - Steve Jessop
2
除此之外,我更喜欢使用''.join(N.split())而不是N.replace('\n', '').replace(' ', '') - Steve Jessop
我会将该值放入文本文件中,并使用Python读取它。问题解决了。 - Paco
3个回答

4

来自PEP 8风格指南

但最重要的是:知道何时不一致--有时候风格指南并不适用。如果不确定,就要根据自己的判断力来决定。看看其他例子,决定哪个看起来最好。不要犹豫,尽管问!

因此,将常量保留为原样,因为它比任何其他不明显的技巧更易读

最重要的是可读性至上。

没有什么比Python核心原则更重要了

但必须有一种更优雅的方法来执行PRIME = int('0x{0}'.format(N.replace('\n', '').replace(' ', '')), 16)...

如果您坚持

PRIME=long('17976931348623159077083915679378745319786029604875601'
          '17064444236841971802161585193689478337958649255415021805654859805'
          '03646440548199239100050792877003355816639229553136239076508735759'
          '91482257486257500742530207744771258955095793777842444242661733472'
          '7629299387668709205606050270810842907692932019128194467627007L')

+1 - 但是肯定有更优雅的方法来执行 PRIME = int('0x{0}'.format(N.replace('\n', '').replace(' ', '')), 16)... - Kimvais
实际上,我自己找到了这个方法:int(re.sub('\s+', '', N), 16) - Kimvais
这并不更优雅。:/ - Ethan Furman
顺便提一下,我的评论是针对Abhijit的 PRIME=long...,而不是 re.sub - Ethan Furman

3

坦率地说,你所拥有的已经相当不错。唯一明显的改变是最后的转换:您可以放弃 "0x{0}".format部分,直接将替换后的字符串作为十六进制数传递给int函数。

除此之外,您还可以将其隐藏在一个函数中:

def PrimeInt(string):
    return int(string.replace('\n','').replace(' ',''), 16)

PRIME = PrimeInt("""
        FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1
        29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD
        EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245
        E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED
        EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE65381
        FFFFFFFF FFFFFFFF
        ''')

1
如果您想让某些东西看起来好看,也许可以将字符串转换为整数。虽然这可能不是最佳实践,因为我从未在实践中见过它的使用,但我认为它比原始方法更清晰,因为转换受到限制。
number = (
    "179769313486231590770839156793787453197860296048756011"
    "706444423684197180216158519368947833795864925541502180"
    "565485980503646440548199239100050792877003355816639229"
    "553136239076508735759914822574862575007425302077447712"
    "589550957937778424442426617334727629299387668709205606"
    "050270810842907692932019128194467627007"
)
number = int(number)
179769313486231590770839156793787453197860296048756011706444423684197180216158519368947833795864925541502180565485980503646440548199239100050792877003355816639229553136239076508735759914822574862575007425302077447712589550957937778424442426617334727629299387668709205606050270810842907692932019128194467627007L

你也可以在原始赋值处直接放置 int - Ethan Furman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接