Is there a way to make my code more effiecient

Question:

Hey so I’m a beginner and was just trying out projects to get better so I made a password checker.
Just want to see if there is anyway I can make my code neater or more efficient to tips are nice.

import re
regex = re.compile('[@_!#$%^&*()<>?/|}{~:]')

while True:
    pw = input("Enter a string: ")
    if 5<=len(pw)<=10:
        if (regex.search(pw) == None):
            print("Not a valid password, Needs special character")
            continue
        else:
            if any(x.isupper() for x in pw):
                print("character has an uppercase letter")
                return True
            else:
                print("Character does not have an upper case")
                continue
    else:
        print("password must be between 5 and 10 characters")
        continue

Going to put this into a function and inside main, True returns it’s valid

Asked By: Big_Port

||

Answers:

Yes, define all your conditions (business requirements) in variable in start:

isUpperCaseCriteria = any(char.isupper() for char in text)
isSpecialCharacterCriteria = any(char in string.punctuation for char in text)
isLengthCriteria = len(text) >= 10


if isUpperCaseCriteria:
   -> code 
if isSpecialCharacterCriteria:
   -> code
if isLengthCriteria:
   -> code

and then check everything.

It’s not improve efficiency – but readibility.
Which in the perspective of maintaining this code is almost the same.

Answered By: Piotr Żak

first, I believe this approach is not recommended since it may not be feasible in other languages such as C.

if 5 <= len(pw) <= 10:

Use something like this

if len(pw) < 5 or len(pw) > 10:

I believe that trying to avoid someone else is a better approach. You can achieve this by using only an If statement and a continue like this:

if len(pw) < 5 or len(pw) > 10:
    print("password must be between 5 and 10 characters")
    continue

The less indentation you have, the easier the code is to read and debug.

Instead of creating an infinite loop with while True: try using a boolean variable like isCorrectPassword to make the condition easier to understand.

Finally, I believe that Stack Overflow is not intended for code reviews but rather for debugging purposes. You should try Stack Exchange instead.

Answered By: BlizZ

For something as short-lived as this there’s little to be gained in terms of runtime efficiency.

However, there are changes you could consider making that will improve the code structure.

First of all, you should write a function that performs the validation – and only that. In that way, no matter where the password is acquired from you can always use the same function.

The string of special characters looks clumsy so put it in a global variable (I conventionally use uppercase variable names to indicate global scope and the fact that its use is constant). Something like this:

SPECIALS = '[@_!#$%^&*()<>?/\|}{~:]'

def validate(password):
    if 5 <= len(password) <= 10: # correct length
        if any(sc in password for sc in SPECIALS): # has a special character
            if any(c.isupper() for c in password): # has at least one uppercase letter
                return True
    return False

while True:
    password = input('Enter a password: ')
    if validate(password):
        print('Valid')
        break
    print('Invalid - try again')
Answered By: DarkKnight

Here is one more attempt at making some improvements to your original code:

import re
import getpass

from typing import NamedTuple


class ValidationResponse(NamedTuple):
    is_valid: bool
    message: str


MIN_LENGTH = 5
MAX_LENGTH = 10
SPECIAL_CHARS = "[@_!#$%^&*()<>?/|}{~:]"
SPECIAL_CHARS_REGEX = re.compile(SPECIAL_CHARS)


def validate_password(password: str) -> ValidationResponse:
    """
    Validate password based on predefined rules.

    This function checks a given password for compliance with the following rules:
    - The password should be between MIN_LENGTH and MAX_LENGTH characters long.
    - The password should contain at least one character from SPECIAL_CHARS.
    - The password should contain at least one uppercase letter.

    Args:
        password (str): The password string to be validated.

    Returns:
        ValidationResponse: A named tuple with the following fields:
            - is_valid (bool): True if the password is valid, False otherwise.
            - message (str): The validation message.
    """
    if not MIN_LENGTH <= len(password) <= MAX_LENGTH:
        return ValidationResponse(
            False,
            f"Password must be between {MIN_LENGTH} and {MAX_LENGTH} characters.",
        )
    if SPECIAL_CHARS_REGEX.search(password) is None:
        return ValidationResponse(
            False,
            f"Password needs to contain at least one special character {SPECIAL_CHARS}",
        )
    if not any(char.isupper() for char in password):
        return ValidationResponse(
            False,
            "Password needs to contain at least one uppercase letter.",
        )
    return ValidationResponse(True, "Password is valid.")


def main() -> None:
    while True:
        password = getpass.getpass("Enter a password: ")
        is_valid, message = validate_password(password)
        print(message)
        if is_valid:
            break
    print(f"DEBUG: {password} is valid!")


if __name__ == "__main__":
    main()

Improvements with Explanations:

  1. Separation of Concerns: The user input collection and password validation are now handled in two distinct functions. The main function asks the user for their password, and validate_password checks if the provided password meets the specified conditions. This makes the code modular, easy to understand, and increases reusability.

  2. Use of Constants: The constants MIN_LENGTH, MAX_LENGTH, SPECIAL_CHARS, and SPECIAL_CHARS_REGEX are used to define password requirements. This makes the code more maintainable since these requirements can be changed easily in one place without going through the entire code.

  3. Type Hints: The function validate_password now includes type hints (password: str) for the input and return value (-> ValidationResponse). This makes the code easier to understand and work with, especially in larger codebases or when collaborating with other developers.

  4. Secure Password Input: The password is now captured using the getpass module, which doesn’t echo the password back to the console, providing an additional layer of security.

  5. Clear Communication: Each time validate_password detects an issue with the password, it immediately returns a False flag and a message explaining why the password is invalid. This makes debugging easier and provides clear feedback to the user.

  6. Termination: The main function runs in a loop until a valid password is entered. Once a valid password is detected, the loop breaks, and a success message is displayed. This way, the program provides continuous feedback until it receives valid input.

I hope this helps 🙂

Answered By: Sash Sinha