HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythonModerate

One Time Pad in Python

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
padonepythontime

Problem

I'm new to Python, but I really want to get into the swing of doing things the pythonic way. First, does my code follow the pythonic path? Or does it run screaming bloody murder, as it zig-zags through my C++ thought of mind? Probably the latter.

```
import sys, random, string
#import pdb
#pdb.set_trace()

def read(name):
inFile=open(name, 'r')
content=inFile.read()
content=list(content.strip())
return content

#this function will take a file name and a list of numbers
#it will convert the nums to chars and write to file
def write(name, nList):
outFile=open(name, 'w')
cList=convertToChar(nList)
outFile.write(''.join(cList))

#takes a key length, based on message size and gens rand key
def gen(keylen):
i=0
key=[]
while i <keylen:
k=random.SystemRandom()
k=k.choice(string.printable)
key.append(k) #append random letter to key list
i+=1
key=convertToNum(key) #conver the key to numbers for xor later
write("key.txt", key)
return key #for xor'ing later in enc

#takes a list of chars, converts to nums, and writes to list
#returns a numList
def convertToNum(charList):
numList=[]
i=0
for i in charList:
numList.append(ord(i))
return numList

#takes list of nums, converts to chars, and writes to new list
#retursn the charlist
def convertToChar(numList):
charList=[]
i=0
for i in numList:
charList.append(chr(i))
return charList

#This will ask the user for a file name
#converts the
def enc():
fileName= raw_input("Please enter a name for your message file")
#fileName="plaintext.txt"
plaintext=read(fileName) #gets a list form of the file
m= convertToNum(plaintext) #the message in nums
mLen=len(m) #len of message for size of key
k=gen(mLen) #generate the key
c=[]

Solution

Here are some of your functions translated to be more pythonic:

Context managers mean never having to say your closed():

We can recast thse 2 functions (including fixing the bug of not closing the files):

def read(name):
    inFile = open(name, 'r')
    content = inFile.read()
    content = list(content.strip())
    return content

def write(name, nList):
    outFile = open(name, 'w')
    cList = convertToChar(nList)
    outFile.write(''.join(cList))


to:

def read(name):
    with open(name, 'r') as f:
        return f.read().strip()

def write(name, n_list):
    with open(name, 'w') as f:
        f.write(''.join(convertToChar(n_list)))


big key here is using context managers to automatically close the file, and not bothering to assign intermediate results to a variable.

List comprehensions can save a lot of looping boilerplate:

We will trim down:

def gen(keylen):
    i = 0
    key = []
    while i < keylen:
        k = random.SystemRandom()
        k = k.choice(string.printable)
        key.append(k)
        i += 1
    key = convertToNum(key)
    write("key.txt", key)
    return key

def convertToNum(charList):
    numList = []
    i = 0
    for i in charList:
        numList.append(ord(i))
    return numList

def convertToChar(numList):
    charList = []
    i = 0
    for i in numList:
        charList.append(chr(i))
    return charList


To:

def gen(keylen):
    key = convertToNum([random.SystemRandom().choice(string.printable)
                        for k in range(keylen)])
    write("key.txt", key)
    return key

def convertToNum(charList):
    return [ord(i) for i in charList]

def convertToChar(numList):
    return [chr(i) for i in numList]


All three of these functions now make use of list comprehensions to remove 75% of the lines of code.

NOTE

I did not test these changes they were just typed out in the editor.

Code Snippets

def read(name):
    inFile = open(name, 'r')
    content = inFile.read()
    content = list(content.strip())
    return content

def write(name, nList):
    outFile = open(name, 'w')
    cList = convertToChar(nList)
    outFile.write(''.join(cList))
def read(name):
    with open(name, 'r') as f:
        return f.read().strip()

def write(name, n_list):
    with open(name, 'w') as f:
        f.write(''.join(convertToChar(n_list)))
def gen(keylen):
    i = 0
    key = []
    while i < keylen:
        k = random.SystemRandom()
        k = k.choice(string.printable)
        key.append(k)
        i += 1
    key = convertToNum(key)
    write("key.txt", key)
    return key

def convertToNum(charList):
    numList = []
    i = 0
    for i in charList:
        numList.append(ord(i))
    return numList

def convertToChar(numList):
    charList = []
    i = 0
    for i in numList:
        charList.append(chr(i))
    return charList
def gen(keylen):
    key = convertToNum([random.SystemRandom().choice(string.printable)
                        for k in range(keylen)])
    write("key.txt", key)
    return key

def convertToNum(charList):
    return [ord(i) for i in charList]

def convertToChar(numList):
    return [chr(i) for i in numList]

Context

StackExchange Code Review Q#158097, answer score: 13

Revisions (0)

No revisions yet.