Python Forum
How to compare two parameters in a function that has *args? - Printable Version

+- Python Forum (https://python-forum.io)
+-- Forum: Python Coding (https://python-forum.io/forum-7.html)
+--- Forum: General Coding Help (https://python-forum.io/forum-8.html)
+--- Thread: How to compare two parameters in a function that has *args? (/thread-39687.html)



How to compare two parameters in a function that has *args? - Milan - Mar-26-2023

Hello team,

I have the following function

import string
import random

def check_input(*args):
    length = args[0]
    while length <= 0:
        length = int(input("[!] Please insert a positive integer: "))
    number = args[1]
    while length < number:
        number = int(input("[!] Please insert a positive integer: "))


check_input(-1)
check_input(5)
I would like to compare the first argument, in the above example it would ask to input another value instead of -1, and the second argument, in the above example 5.

I am getting the following error:

Error:
IndexError: tuple index out of range
I see *args prints the following when I
print(args)

(-1,)
(5,)
Could you please help me with how can I access the second and the following tuples to come for that function?

Thanks in advance.


RE: How to compare two parameters in a function that has *args? - Gribouillis - Mar-26-2023

Could you explain the problem that you are trying to solve? It is very difficult to understand it through this function that does nothing useful.


RE: How to compare two parameters in a function that has *args? - Milan - Mar-26-2023

(Mar-26-2023, 05:11 PM)Gribouillis Wrote: Could you explain the problem that you are trying to solve? It is very difficult to understand it through this function that does nothing useful.

Sure, I am glad you asked, so I am finishing my password generator, the main file looks like that

import random
import string
from logo import logo

print(logo)

# Generate string with all letters, numbers and symbols

def generate_password(n_letters, n_numbers, n_symbols):
    letters = "".join(random.sample(string.ascii_letters, n_letters))
    numbers = "".join(random.sample(string.digits, n_numbers))
    symbols = "".join(random.sample(string.punctuation, n_symbols))
    password = letters + numbers + symbols
    return "".join(random.sample(password, len(password)))


# Variable type verification
while True:
    try:
        length = int(input("[-] Choose the length of the password (Only integer): "))
        while length <= 0:
            length = int(input("[!] Please insert a positive integer: "))
        letters = int(input("[-] How many letters: "))
        while letters >= length:
            letters = int(input(f"[!] Amount of letters cannot be bigger than the password lenght, please insert a number lesser than {length}: "))
        numbers = int(input("[-] How many numbers: "))
        while numbers + letters > length:
            numbers = int(input(f"[!] Amount of numbers plus letter cannot be bigger than the password lenght, please insert a number lesser than {length - letters}: "))
        symbols = int(input("[-] How many symbols: "))
        while numbers + letters + symbols > length:
            symbols = int(input(f"[!] Amount of symbols plus letters and numbers cannot be bigger than the password lenght, please insert a number lesser than {length - letters - numbers}: "))
    except ValueError:
        print("[!] Invalid input, please enter an integer number")
        continue
    else:
        break
        
# Creates password based on user's input
password = generate_password(letters, numbers, symbols)
print(f"[+] Your password: {password}")
I would like to add a function to replace the many while loops between lines 21 and 31.

To my mind a function with *args would solve it, all I need is to know how to access the four arguments in it, they being 'length', 'letters', 'numbers' and 'symbols'.


RE: How to compare two parameters in a function that has *args? - deanhystad - Mar-26-2023

You are checking at the wrong time. Tell the user what they can enter and force them to enter values that are correct.
def get_number(prompt, range=None):
    """Force user to input number.  If range provided, input must be in range."""
    while True:
        try:
            value = int(input(prompt))
            if not range or range[0] <= value <= range[1]:
                return value
            print("Invalid input.  Try again")
        except ValueError:
            print("Invalid input.  Try again")


MAX_LENGTH = 30
MIN_LENGTH = 8
remaining = MAX_LENGTH - 2  # at least 1 lettter, number and special character

special = get_number(f"How many special characters (1-{remaining}): ", (1, remaining))
remaining = remaining - special + 1

if remaining > 2:
    numbers = get_number(f"How many numbers (1-{remaining}): ", (1, remaining))
else:
    numbers = 1

remaining = remaining - numbers + 1
if remaining > 1:
    min_letters = max(1, MIN_LENGTH - (special + numbers))
    letters = get_number(f"How many letters ({min_letters}-{remaining}): ", (min_letters, remaining))
else:
    letters = 1

print(letters, numbers, special)
To answer your question, you could do something like this:
def check(*args):
    """Force all args to be at least 1"""
    return [max(1, arg) for arg in args]



RE: How to compare two parameters in a function that has *args? - Milan - Mar-26-2023

(Mar-26-2023, 07:20 PM)deanhystad Wrote: You are checking at the wrong time. Tell the user what they can enter and force them to enter values that are correct.
def get_number(prompt, range=None):
    """Force user to input number.  If range provided, input must be in range."""
    while True:
        try:
            value = int(input(prompt))
            if not range or range[0] <= value <= range[1]:
                return value
            print("Invalid input.  Try again")
        except ValueError:
            print("Invalid input.  Try again")


MAX_LENGTH = 30
MIN_LENGTH = 8
remaining = MAX_LENGTH - 2  # at least 1 lettter, number and special character

special = get_number(f"How many special characters (1-{remaining}): ", (1, remaining))
remaining = remaining - special + 1

if remaining > 2:
    numbers = get_number(f"How many numbers (1-{remaining}): ", (1, remaining))
else:
    numbers = 1

remaining = remaining - numbers + 1
if remaining > 1:
    min_letters = max(1, MIN_LENGTH - (special + numbers))
    letters = get_number(f"How many letters ({min_letters}-{remaining}): ", (min_letters, remaining))
else:
    letters = 1

print(letters, numbers, special)
To answer your question, you could do something like this:
def check(*args):
    """Force all args to be at least 1"""
    return [max(1, arg) for arg in args]

Thank you very much.