让这段代码看起来更优雅

Make this code look more elegant

我在 python 和编程方面绝对是新手,我做了这个 bifid cipher,我想听听有关如何改进并使其看起来更优雅的意见,在此先感谢。

我一直在 Codecademy 和 Udacity 上课,学到了很多东西。

import itertools


#Genera coodernadas-Generate Coordinates
coordinates = [[x,y] for x in range(1,6) for y in range(1,6)]

#Genera alfabeto-Generate Alphabet
alfa = []
for i in range(97,123):
    alfa.append(chr (i))
alfa.remove("i")

#Genera diccionario de coordenadas y alfabeto - Generate dictionary and coordinates alphabet 
alfacor = {}
alfacor = dict(zip(alfa,coordinates))


#Leer Txt - Read txt
document = open("Z:\R\Desktop\BIFIDO\easy.txt")
contenido = document.read()
print (contenido)
document.close()

#Encripta fase1 - Get's coordinates of txt
encripta = []
for e in contenido:
    encripta.append(alfacor[e])

#Unir lista encripta - Merge content of encropita in a new list
merged = list(itertools.chain.from_iterable(encripta))

#Divido lista merge en partes iguales - Divide meged list to get new coordinates
B = merged[:len(merged)/2]
C = merged[len(merged)/2:]

#Unir B y C - Zip B and C to get a new list of coordinates
zipped = zip(B,C)

#Make a new list from zipped to convert from tuple to list
final_list = [list(elem) for elem in zipped]

#Convert contect of alfacor to tuples
inv_alfacor = {}
for letter, coordinate in alfacor.iteritems():
inv_alfacor[tuple(coordinate)] = letter

#Substitude coordinates of final_list from elements of inv_alfacor
encripta_f = []
for element in final_list:
    element = tuple(element)
    if element in inv_alfacor:
        encripta_f.append(inv_alfacor[element])

print "Tu palabra ",encripta_f    
  1. 使用with语句

您可以在 python docs or in this article Understanding Python's "with" statement

中阅读更多内容

建议修改:

#Leer Txt - Read txt
with open("Z:\R\Desktop\BIFIDO\easy.txt", "r") as document:
    contenido = document.read()
    print (contenido)
  1. 使用列表理解

更多信息在 Python docs or in the tutorial Python Tutorial: List Comprehensions

建议修改:

#Genera alfabeto-Generate Alphabet
alfa = [chr(i) for i in xrange(97, 123) if chr(i) != "i"]

(请注意,此更改还包括列表理解中的条件 - example at SO question

还有:

#Encripta fase1 - Get's coordinates of txt    
encripta = [alfacor[e] for e in contenido]
  1. 使用生成器

您可以开始的第一件事是以下内容。当你写一个列表理解并且你知道你一次只会迭代列表中的一个项目时,将括号从 [] 更改为 ()。这确实很简单,但这是您可以做的第一件事。另一个相关提示,当您像 for i in range(x) 一样使用 range(x) 时,请改用 xrange(x)xrangerange.

的生成器版本

更多信息见Python Wiki

建议的更改:

#Make a new list from zipped to convert from tuple to list
final_list = (list(elem) for elem in zipped)
  1. 打印

在这种情况下,使用您所使用的打印就可以了,但请查看字符串格式。

更多内容在 Python docs and a few examples here

可能的变化:

print "Tu palabra {}".format(encripta_f)
  1. 不需要初始化所有变量。

当您为变量分配一个全新的值时,您不需要初始化 alfacor 字典。但是,以后使用它时需要初始化变量。

因此两者之间存在差异

# no need for initialization
alfacor = {}
# because you assign a new value here to the variable `alfacor`
alfacor = dict(zip(alfa,coordinates))

还有这个:

# you need to initialize this
alfacor = {}
# because you are working with the empty dictionary here
alfacor["my_key"] = "my_value"

除了可能使用理解并避免不必要的元组 -> 列表 -> 元组转换之外,减少中间变量的数量可能会稍微更容易阅读。我也会考虑让它成为一个函数,你传入一个字符串并返回一个加密的字符串:

from itertools import chain, product

def bifid(data):
    # Leave coordinates as tuples and appropriate use of itertools.product
    coordinates = product(range(1, 6), repeat=2)

    # Using comprehensions and generators to construct the list/dicts vs loops
    # Leave alfa as a generator as it is only used once
    alfa = (chr(i) for i in range(97, 123) if chr(i) != 'i')
    alfacor = dict(zip(alfa, coordinates))
    inv_alfacor = {coordinate: letter for letter, coordinate in alfacor.iteritems()}
    encripta = (alfacor[e] for e in data)

    merged = list(chain(*encripta))
    final_list = zip(merged[:len(merged)//2], merged[len(merged)//2:])

    return "".join(inv_alfacor[e] for e in final_list if e in inv_alfacor)

# Use with it closes automatically and handles exceptions correctly
with open("Z:\R\Desktop\BIFIDO\easy.txt") as document:
    data = document.read()]

print "Tu palabra: {}".format(bifid(data))

输出:

"helloworld" -> Tu palabra: kmcyobnalt