3
\$\begingroup\$

I have been teaching myself python in my spare time and so far I think I have figured out the basics. However, I am fairly certain that my code is extremely unprofessional and the way I write it is incorrect. So far, I have been going on a "If it works don't screw with it" philosophy but I would like to learn how to actually write Python correctly. If anyone could just take a look at what I have written that would be great.

Here is my code that implements a voting machine, called "VoteBot":

import time
import os

#colors
os.system('color')
black = lambda text: '\033[0;30m' + text + '\033[0m'
red = lambda text: '\033[0;31m' + text + '\033[0m'
green = lambda text: '\033[0;32m' + text + '\033[0m'
yellow = lambda text: '\033[0;33m' + text + '\033[0m'
blue = lambda text: '\033[0;34m' + text + '\033[0m'
magenta = lambda text: '\033[0;35m' + text + '\033[0m'
cyan = lambda text: '\033[0;36m' + text + '\033[0m'
white = lambda text: '\033[0;37m' + text + '\033[0m'

#Start Menu
print('                                                     --------------------------------------------------------------------------------')
print('                                                     VoteBot v1.5.0')
print('                                                     Copyright 2020.')
print('                                                     Author:')
print(' ')
print('                                                     Hit any key and press enter to begin.')
print('                                                     --------------------------------------------------------------------------------')
vote = input('                                                     ')

#start of main code
while vote == 'start' or '1' or '2' or '3' or '4':
    print("\n" * 5000)
    print(blue('                                                     --------------------------------------------------------------------------------------------------------'))
    print(blue('                                                     @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@'))
    print(blue('                                                     --------------------------------------------------------------------------------------------------------'))
    print(blue('                                                     @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@'))
    print(blue('                                                     --------------------------------------------------------------------------------------------------------'))
    print(blue('                                                     @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@'))
    print(blue('                                                     @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@'))
    print(blue('                                                     @@@@@@@   @@@@@   @@@@     #@@@         @@      /@@@@@@   %@@@@,  @@@@@     #@@@   @@@@   @@@@   @@@@@@@'))
    print(blue('                                                     @@@@@@@@   @@@&  @@&   @@@@   @@@@   @@@@@  @@@@@@@@@@@     @@@,  @@%   @@@@   @@   @@&    @@@  @@@@@@@@'))
    print(blue('                                                     @@@@@@@@@   @@  %@@   @@@@@@  (@@@   @@@@@      @@@@@@@   @   @,  @@   @@@@@@  (@@  @@  @  .@  /@@@@@@@@'))
    print(blue('                                                     @@@@@@@@@@  @  *@@@   @@@@@   @@@@   @@@@@  @@@@@@@@@@@   @@@  *  @@   @@@@@   @@@     #@@  @  @@@@@@@@@'))
    print(blue('                                                     @@@@@@@@@@@    @@@@@%        @@@@@   @@@@@       @@@@@@   @@@@.   @@@%        @@@@@    @@@/   @@@@@@@@@@'))
    print(blue('                                                     @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@'))
    print(blue('                                                     @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@'))
    print(blue('                                                     --------------------------------------------------------------------------------------------------------'))
    print(blue('                                                     @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@'))
    print(blue('                                                     --------------------------------------------------------------------------------------------------------'))
    print(blue('                                                     @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@'))
    print(blue('                                                     --------------------------------------------------------------------------------------------------------'))
    print(' ')
    print('                                                     --------------------------------------------------------------------------------------------------------')
    print('                                                     Vote here to choose the winning team. Please choose by entering the number corresponding to your choice.')
    print('                                                     --------------------------------------------------------------------------------------------------------')
    print(red('                                                     1. Team 1 (Cantidate 1, Cantidate 2)'))
    print(yellow('                                                     2. Team 2 (Cantidate 1, Cantidate 2)'))
    print(green('                                                     3. Team 3 (Cantidate 1, Cantidate 2)'))
    print(blue('                                                     4. Team 4 (Cantidate 1, Cantidate 2)'))
    print('                                                     --------------------------------------------------------------------------------------------------------')
    print('                                                     Please make your selection now. Remember, if you do not input a NUMBER your vote will not be counted.')
    vote = input('                                                     Enter your vote: ')
    file = open('votedata.txt', 'a')
    file.write(vote + '\n')
    print('                                                     The system is adding your vote. The next person can vote in 3 seconds.')
    time.sleep(3)
    if vote == 'tally':
        break

#start of tally
with open("votedata.txt") as fp:
    results = {}
    for row in fp:
        try:
            v = int(float(row))
            if v not in results:
                results[v] = 0
            results[v] += 1
        except:
            print(red("Invalid Numeric entry"))

    print(results)

print('The program will automatically shut down in 5 minutes.')
time.sleep(300)
\$\endgroup\$
  • \$\begingroup\$ Can you please give a high level description of what votebot does? \$\endgroup\$ – pacmaninbw Feb 16 at 21:29
  • \$\begingroup\$ Have you taken a look at streamlit library? I find it pretty nice. \$\endgroup\$ – Wolfy Feb 17 at 1:11
6
\$\begingroup\$

Some high level coding style notes:

  1. Try to eliminate code that looks like it's copied and pasted (DRY - Don't Repeat Yourself), and define it in functions. Your various color functions are mostly identical with the exception of one digit (the color code) -- you can avoid repeating yourself by defining a function that implements the shared part and defining the colors in terms of that.

  2. Professional coders (especially those working on large shared codebases) rely heavily on static typing to improve correctness and readability; modern Python has built in support for static typing, and while it's optional it goes a long way toward making code look professional IMO. If you get in the habit of using typing and a static type checker (mypy) you'll find that you spend a lot less time debugging silly typos too!

  3. It's generally considered good style to not have lines of code be super long -- opinion varies on this, but modern style guides usually suggest a maximum width of 120 characters, and I personally try to keep it under 80. The fact that your output contains lots of blank space that might make it annoying to view in a normal terminal is more of a UX issue than a code review one, but assuming it's actually a requirement to left-pad everything with 53 spaces, I think that should be implemented in code (again, in a reusable function because DRY) rather than copy+pasted into all your strings.

  4. Again this is more UX than actual coding, but: proofread! It's "candidate", not "cantidate". :)

Here's how I'd apply those notes to the print statements in your code:

from enum import IntEnum
from typing import Optional

# Command prompt colors.
class Color(IntEnum):
    """MS-DOS command prompt color codes."""
    BLACK = 0
    RED = 1
    GREEN = 2
    YELLOW = 3
    BLUE = 4
    MAGENTA = 5
    CYAN = 6
    WHITE = 7
    GRAY = 8

def color_text(text: str, color: Optional[Color]) -> str:
    """Wraps text in the specified color."""
    if color is None:
        return text
    return '\033[0;3' + hex(color.value)[-1] + 'm' + text + '\033[0m'

def pp(text: str, color: Optional[Color] = None, left_padding: int = 53) -> None:
    """Pretty-print text with optional coloring and default left-padding of 53 spaces."""
    print(' ' * left_padding + color_text(text, color))

#Start Menu
pp('-' * 80)
pp('VoteBot v1.5.0')
pp('Copyright 2020.')
pp('Author:')
pp('')
pp('Hit any key and press enter to begin.')
pp('-' * 80)
vote = input(' ' * 53)

#start of main code
while vote == 'start' or '1' or '2' or '3' or '4':
    pp("\n" * 5000)  # this is gross -- maybe use a system("cls") instead?
    # ... etc
    pp('-' * 80)
    pp('Vote here to choose the winning team. '
       'Please choose by entering the number corresponding to your choice.')
    pp('-' * 80)
    pp('1. Team 1 (Candidate 1, Candidate 2)', Color.RED)
    pp('2. Team 2 (Candidate 1, Candidate 2)', Color.YELLOW)
    pp('3. Team 3 (Candidate 1, Candidate 2)', Color.GREEN)
    pp('4. Team 4 (Candidate 1, Candidate 2)', Color.BLUE)
    # ... etc

The signature of pp is designed to narrow your output statements and keep the text aligned for readability; the function name itself is abbreviated, the padding is built into the function so the actual arguments don't need to include it, and the color argument goes at the end so that it doesn't cause the width of the line before the text to vary.

Colors have been defined in an IntEnum because that makes it impossible (with static typechecking) to pass anything that's not a valid color into the color_text function; the alternative would be to use a regular int (or worse yet, the str representation) and then validate at runtime that it falls within the expected range.

|improve this answer|||||
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.