Python Forum
Tuple comprehension to for loop help
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Tuple comprehension to for loop help
#1
Hello, I am currently taking a python course online. My class recently went over making a password checker api. If you take a look below, there is def get_password_leaks_count(hashes, hash_to_check).
How would I turn that tuple comprehension/generator expression into a for loop instead? I've been trying to figure out for the past 2 days and it just seems that I cannot get it right. I have rewatched the videos from the course, but I still cannot figure it out. Can someone show me what the answer would look like?

import requests
import hashlib
import sys

password_input = input("Please type in a password you would like to check ").split()

def request_api_data(query_char):
    url = "https://api.pwnedpasswords.com/range/" + query_char
    res = requests.get(url)
    if res.status_code != 200:
        raise RuntimeError(f'Error fetching: {res.status_code}, '
                           f'check the API and try again.')
    return res

def read_res(response):
    print(response.text)

def get_password_leaks_count(hashes, hash_to_check):
     hashes = (line.split(':') for line in hashes.text.splitlines())
     print(hashes)
     for h, count in hashes:
         if h == hash_to_check:
             return count
     return 0
     print(h, count)

def pwned_api_check(password):
    sha1password = hashlib.sha1(password.encode('utf-8')).hexdigest().upper()
    # Check password if it exists in API response
    first5_char, tail = sha1password[:5], sha1password[5:]
    response = request_api_data(first5_char)
    print(first5_char, tail)
    # print(response)
    # return read_res(response)
    return get_password_leaks_count(response, tail)


def main(args):
    for password in args:
        count = pwned_api_check(password)
        if count:
            print(f'{password} was found {count} times.'
                  f' Consider changing your password.')
        else:
            print(f'{password} was NOT found.')
    return "complete"
if __name__ == '__main__':
    sys.exit(main(password_file))
    # sys.exit(main(sys.argv[1:])
    # sys.exit(main(password_input))
Yes, I know there should not be same variable names, but this is just to show what I was trying to do.
My attempt:
def get_password_leaks_count(hashes, hash_to_check):
    for line in hashes.text.splitlines():
        hashes = line.split(':')
        # for h, count in hashes:
        #     if h == hash_to_check:
        #         return count
        # return 0
Reply
#2
In the generator comprehension, hashes holds the iterator returned by the generator. In your attempt, hashes holds only one element from the iteration (one by one as you loop).

It's slightly easier to show the translation for a list comprehension since you're not having to yield.

For a list comprehension of the form
mylist = [x*2 for x in iter]
Then an unroll of it might look like:
temp_list = []
for x in iter:
    temp_list.append(x*2)
mylist = temp_list
Reply
#3
Thank you for your reply.
I was finally able to get some meaningful help from the class.
def get_password_leaks_count(hashes, hash_to_check):
    splithashes = hashes.text.splitlines()
    newlist = []
    for line in splithashes:
        newlist.append(line.split(':'))
        for h, count in newlist:
            if h == hash_to_check:
                return count
        return 0
        print(h, count)
However, there is a weird problem now. Last night, this functioned well just like the original, but today, it is just letting any password pass by as being safe.
Reply
#4
In your original (comprehension) code, hashes was built up from all the lines in passed in hashes. After it was built, you iterated through the contents.

In your new one you're doing both at the same time (incorrectly).

The loop starting at line 4 and the append on line 5 are building up the list. But then during the build-up, the loop on line 6 is trying to iterate through it. The first time it runs, there will be only one item, and it thinks that's the end of the list. In reality, the list wasn't complete.

These loops shouldn't be nested. They should either be separated as earlier (build up the list, then loop through it), or combined into one (check each hash rather than create the temporary list).
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
Question mypy unable to analyse types of tuple elements in a list comprehension tomciodev 1 494 Oct-17-2023, 09:46 AM
Last Post: tomciodev
  For Loop with List Comprehension muzikman 25 6,707 Dec-18-2020, 10:45 PM
Last Post: muzikman
  code with no tuple gets : IndexError: tuple index out of range Aggam 4 2,847 Nov-04-2020, 11:26 AM
Last Post: Aggam
  Help: list comprehension for loop with double if statement mart79 3 2,444 May-04-2020, 06:34 AM
Last Post: buran
  List comprehension. Shor for loop version dervast 1 1,605 Dec-11-2019, 12:34 PM
Last Post: perfringo
  Arrange list of tuple using loop batchenr 7 3,497 Jun-16-2019, 03:24 PM
Last Post: Abdullah
  How to get first line of a tuple and the third item in its tuple. Need Help, Anybody? SukhmeetSingh 5 3,219 May-21-2019, 11:39 AM
Last Post: avorane

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020