I have created this repo on GitHub and I have shown how this software works through a video.

If you have time, please visit the repo and read the files. I'll post some relevant snippets below, but if you can quickly skim over the whole thing, that would be great.

I'm new to Python so I'm sure there are some things in the code below that may not be best code practice. If you spot anything off, please let me know.

file yousecret.py:

I don't see many people writing Tkinter .grid() calls in this fashion so I'm thinking there may be some more practical way to do this. Also, the outcome looks like something from 1995, so I also wish I could give it a modern look.


file ysdecode.py:

What follows below feels like C code, I believe there must be a shorter and faster way to write this function in Python.

def getsum(addrlist):
    alladdr = []
    sumlists = []
    for addr in addrlist:
        final = []
        temp = []
        switch = True
        for url in addr:
            if switch:
                switch = False
            elif not switch:
                switch = True
                temp = []
    for addr in alladdr:
        temp = []
        for pair in addr:
            for bitpair in BITARRAY:
                if pair == bitpair:
    return sumlists

The addrlist parameter is a list of tuples, like this:

addrlist = [ ('wDzN2SQ8dCs', 'NLQf-Q8zlG0'), ('EhFPMTWSsso', 'wf1laG5Jp34') ] 

BITARRAY is a global variable that is also a list of tuples.

for i in '-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz':
    for j in '048AEIMQUYcgkosw':
  • \$\begingroup\$ The look and feel from 1995 comes from Tkinter. If you want a more modern one, you’ll have to switch to something else like PyQT or pygi… \$\endgroup\$ Aug 17, 2017 at 7:51

1 Answer 1



In any significant project, especially one that you are sharing through GitHub, it is important to write docstrings for each function. You haven't written any.

It is implied by the PEP 8 official style guide that functions should be named using lower_case_with_underscores and constants should be named using UPPER_CASE_WITH_UNDERSCORES. I would recommend renaming BITARRAYBIT_ARRAY and getsum()get_sum(), because pythonisnotgermanorfinnish.


Whenever you build a list by starting with an empty list and appending to it in a loop, you'll almost certainly want to write a list comprehension or a generator expression instead. That way, you describe the result "all at once" using a single statement.

from string import digits, ascii_uppercase, ascii_lowercase

INIT_CHARS = '-' + digits + ascii_uppercase + '_' + ascii_lowercase
BIT_ARRAY = sum(([tuple((a, b)) for a in INIT_CHARS] for b in FINAL_CHARS), [])

The sum() function above is used to concatenate lists. That expression is a bit nasty. You can write it better using itertools.product(), which is exactly what we need:

from itertools import product
from string import digits, ascii_uppercase, ascii_lowercase

INIT_CHARS = '-' + digits + ascii_uppercase + '_' + ascii_lowercase

Note, however, that it would be better not to define your BITARRAY at all, if your only goal is to find the index of a particular pair of characters. Instead of BITARRAY.index(…), it would be more efficient to do a little arithmetic:

def numeric_value(init_char, final_char):
    Given character init_char (one of the characters [-0-9A-Z_a-z]) and
    character final_char (one of the characters [048AEIMQUYcgkosw]),
    deterministically produce a numeric value from 0 to 1023, inclusive.
    return INIT_CHARS.index(init_char) * len(FINAL_CHARS) + \

Based on similar principles, I would write this function:

def get_sum(video_ids):
    Compute a tuple of numbers for the given YouTube video IDs.

    The videos IDs are taken two at a time.  From each pair, the initial
    character of the first ID and the final character of the second ID are
    taken.  Those two characters are mapped a numeric value between 0 and 1023.

    If there are an odd number of video IDs, the last one is ignored.
    return tuple(
        numeric_value(a[0], b[-1]) for a, b in zip(*[iter(video_ids)] * 2)

The zip(*[iter(video_ids)] * 2) expression above is a slick way to split the video_ids into pairs. It comes from the grouper() example in the itertools recipes.

Note that your original getsum(addrlist) function is actually equivalent1 to

def getsum(addrlist):
    return [get_sum(playlist) for playlist in addrlist]

I recommend splitting the work this way instead, so that you don't end up with an excessively nested list comprehension.

1 Well, it's not exactly equivalent, in that your BITARRAY lookup silently ignores pairs of characters that do not conform to the ([-0-9A-Z_a-z], [048AEIMQUYcgkosw]) scheme, whereas numeric_value(…) would raise a ValueError.

  • \$\begingroup\$ Regarding PEP8 and the distinction between variables and constants. Shouldnt BIT_ARRAY be seen as a variable, since it is being mutated in the code? BITARRAY.append((i,j)) \$\endgroup\$
    – JAD
    Aug 17, 2017 at 8:34
  • \$\begingroup\$ @JarkoDubbeldam I would say that it is notionally a constant, for all practical purposes. It was just clumsily initialized. \$\endgroup\$ Aug 17, 2017 at 8:37
  • \$\begingroup\$ My bad actually, I misread the OP, thinking the BITARRAY.append((i,j)) was happening at a later point in the script. \$\endgroup\$
    – JAD
    Aug 17, 2017 at 8:39
  • \$\begingroup\$ I'm surprised you jumped straight to using itertools.product, would showing how to flatten a list using comprehensions be good? For example using BIT_ARRAY = [(a, b) for b in FINAL_CHARS for a in INIT_CHARS]. That way the OP knows that there is never a need for using sum in such a horrible way. \$\endgroup\$
    – Peilonrayz
    Aug 17, 2017 at 10:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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