How do I get more efficient?

Hi guys, I’m now 11 days into the 100 days of codding challenge.
My code works , but i wonder how you guys got more efficient?
whats considered a good code lay-out, …

if you learn at home, who checked your code ?
what could be better?

Thanks in advance!

Please don’t post code in screenshots. Paste the code and wrap it in triple backticks to preserve the formatting:

```
if True:
    print('Hello world!')
```

Even better, add ‘python’ tag to get some syntax coloring.

normal_code
if True:
    print('colored builtin')  # comment in italics
else:
    print('lightly colored keyword')

This better?


def generate_number():
    r_number = random.randint(1, 100)
    return r_number


def easy_or_hard_game(tries):
    for trie in range(tries):
        print(f"you have {tries -trie} attempts remaining to gues the number.\n")
        gues = int(input("Make a gues: "))
        if gues == number:
            return guesed_number + 1
        if gues < number:
            print("Too low")
        else:
            print("Too high")

print(logo)
print("Welcome to the Number Guessing Game!\n")
print("I'm thinking of a number between 1 and 100.")
difficulty = input("Choose a difficulty. Type 'easy' or 'hard':")
number = generate_number()
guesed_number = 1
if difficulty == "easy":
    chances = 10
    guesed_number = easy_or_hard_game(chances)
else:
    chances = 5
    guesed_number = easy_or_hard_game(chances)
if guesed_number == 2:
    print("You won")
else:
    print("you lost")

I recommend you to go through this topic. You will se a lot of useful information there:


My suggestions for your code:

def generate_number():
    r_number = random.randint(1, 100)
    return r_number
  • Missing docstring — What about """Generate a random number to be guessed."""?
  • Shortening of variable names could lower readability. — why not random_number?
  • Do you need the variable at all? — If you understand what random.randint() does, return the result directly without storing it into a variable.
def easy_or_hard_game(tries):
    for trie in range(tries):
        print(f"you have {tries -trie} attempts remaining to gues the number.\n")
        gues = int(input("Make a gues: "))
        if gues == number:
            return guesed_number + 1
        if gues < number:
            print("Too low")
        else:
            print("Too high")
  • Missing docstring again.
  • Function name — there is just a single implementation in the program so why having easy_or_hard in the name? Maybe you would like to make multiple games in the program then it could be number_guessing_game but part of the logic is in your main program so it would need some restructuring.
  • Spelling — In your screenshot I noticed that you use a spell checker. Why do not you check its suggenstions? “trie” is correctly “try” or “attempt”, “gues” is correctly “guess”.
  • Global variable number — Normally it is best to avoid global variables. Doing so is an extremely useful practice before writing more complex programs! Pass the number as a parameter of the function instead.
  • Why do you use the global variable guesed_number? In your program it could contain only value 1 and nothing else when this function is executing. It looks like you use it just as an indication of whether the number was guessed correctly or not. You should do just: return True
guesed_number = 1
  • What does that number mean? See above that this variable not needed at all. (Unless you want to later extend the program in a way I do no understand.)
guesed_number = easy_or_hard_game(chances)
  • You duplicate the same code in both the branches of the if statement. Put it just once after if/else.
  • After that simplification you can maybe skip storing the result in a variable and use it directly in the the following if statement.

Wow, thanks for the detailed suggestions ! i will loook trough the topic you send .

  • Missing docstring — What about """Generate a random number to be guessed."""?
    thanks for the reminder, i will try to use it ! if i understood right, docstrings are used to define what the function does right? so anyone (including myself) know what it supposed to do.
  • Shortening of variable names could lower readability. — why not random_number?
    i wanted to avoid using random, thought it would be ‘dangerous’ to use a variable as almost the same name as a function
  • Do you need the variable at all? — If you understand what random.randint() does, return the result directly without storing it into a variable.
    I see what you mean, the random generated is going anyway be returned. so this code was unnecessary. return randomint(1,100) would be better and less potential for error.

Function name
i think i did easy_or_hard because i knew there were only two ‘modes’ . but i know what you mean, something i will keep in mind for my future projects.

Spelling
i needed to count the attempts left, so tries = 10 for easy and 5 = hard
needed to count down, could have used maybe :
while try > 0
try -= 1

Global variable
yeah , i know that global variable is not the way to go. but i was getting frustrated or something. coudnt figure out why my code wasnt working. so then this solution came up.

guesed number was indeed to check if the number was guessed correctly.

i will work on these subjects, really helpful to bring my mistakes under the ‘microscope’ with you !
i really appreciate it

I am glad that I could help you.

Yes, of course they are important for others to be able to understand the code in reasonable time. You will see their usefulness after you check your own code few weeks or months later.

Docstring are even more important in libraries. Where you do not usually want to study the implementation, you just want to know how to use them.

Python has useful recommendations about how should docstrings look like:

In short:

  • One-line docstring should be a sentence in imperative mode that fits a single line.
  • Longer docstring starts as a one-line docstring, after a blank line it contains more details.

I personally use Google-style docstrings - they define more details how they should look like:

https://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_google.html

Editors like VS Code, PyCharm, JupyterLab will show you the docstring as a pop-up helping you while writing the code.


It is normal that you decide only later that you should rename a variable, function or a class. If it improves readability of the code you should certainly do the renaming. In VS Code it is easy (in PyCharm probably too) - just move cursor to the variable and press F2. The symbol will be renamed in all the places it is used. (Different symbols of the same name will not be touched.)

1 Like

made a new programm, is this somewhat better?

py
import data


def report_resources():
    """print the resources left"""
    print(data.resources)


def operate_coffee_machine(choice):
    """Checks the choice made bij the user, returns the dictionary to have the value's"""
    for each in data.menu:
        if choice == each:
            return data.menu[each]


def check_resources(user, available):
    """ To check if there are resources available to make the coffee"""
    for item in user:
        if user[item] > available[item]:
            print(f"Sorry there is not enough {item}.")
            return False
    return True


def insert_coins():
    """Ask the user to enter the total amount of coins, convert them in to total coins."""
    print("Insert Coins")
    quarters = float(input("How many quarters ??: ")) * 0.1
    dimes = float(input("How many dimes??: ")) * 0.10
    nickles = float(input("How many nickles ??: ")) * 0.5
    pennies = float(input("How many pennies ??: ")) * 0.25
    return quarters + dimes + nickles + pennies


def make_coffee(drink_name, order_ingredients):
    """Make the coffee, subtract resources"""
    for item in order_ingredients:
        data.resources[item] -= order_ingredients[item]
    print(f"Here is your {drink_name} ☕️. Enjoy!")


def reboot():
    machine_continue = True
    while machine_continue:
        user_input = input("What would you like? (espresso/latte/cappuccino):").lower()
        if user_input == "off":
            machine_continue = False
        elif user_input == "report":
            report_resources()
            reboot()
        else:
            coffee = operate_coffee_machine(user_input)
            resources_available = check_resources(coffee["ingredients"], data.resources)
            if resources_available is True:
                total_coins = insert_coins()
                if total_coins > coffee['cost']:
                    drink = data.menu[user_input]
                    make_coffee(user_input, drink["ingredients"])
                    reboot()
                else:
                    print("not enough money.")
                    machine_continue = False
                    reboot()


reboot() ```

In operate_coffee_machine, why are you searching data.menu for choice? Why not just look it up? Incidentally, if the choice isn’t found, operate_coffee_machine will return None. A dict’s .get method is useful for the lookup.

In check_resources’, using the dict’s .items method would be better.

In reboot, there’s no need for reboot to call itself. Also, you really want to say is True; it would be better to have if resources_available:.