When do I use an underscore versus using a decimal?

Is there an simplified way to explain how I would know when to use an underscore versus a decimal? Take this piece of code for example.

class Player:
    def __init__(self):
        self.inventory = [items.Rock(),
                          items.Dagger(),
                          'Gold(5)',
                          'Crusty Bread']
        
    def print_inventory(self):
        print("Inventory:")
        for item in self.inventory:
            print('* ' + str(item))
        best_weapon = self.most_powerful_weapon()
        print("Your best weapon is your {}".format(best_weapon))
        
    def most_powerful_weapon(self):
        max_damage = 0
        best_weapon = None
        for item in self.inventory:
            try:
                if item.damage > max_damage:
                    best_weapon = item
                    max_damage = item.damage
            except AttributeError:
                pass
            
        return best_weapon

For example, I have max_damage = item.damage
I used an underscore for the first half but a decimal for the second half but I am not clear on when to use one over the other.

I also am unclear on how do determine if I should use a double underscore versus a single underscore.

I hope this question makes sense. I am just following along in a tutorial but I need to understand why I am doing something and not just copying what the book told me to do.

Thank you

It may be helpful to look at the material in Python: Classes, which covers topics related to those issues. If the material there seems too advanced or abstract, then be sure to review some of the more basic concepts concerning Python, especially those related to using objects and methods.

1 Like

Thank you.
At first glance this does seem a bit advanced for my current level but it does give me direction. My brain does not process new concepts like it did 30 years ago but I will make time to study this more in-depth and see what I can retain and understand. I will revisit this link frequently to review.

1 Like

Is there an simplified way to explain how I would know when to use
an underscore versus a decimal?

This is probably the wrong way of approaching understanding.
Underscore and full stop (a.k.a. period punctuation, decimal mark)
aren’t really comparable. The underscore character is treated like
any other alphanumeric character in Python. Full stop, on the other
hand, is used as an object attribute (method, class variable)
separator.

In your max_damage = item.damage example, max_damage is
simply the name of a variable. The _ in it is no different than
the x preceding it nor the d following. On the other hand
item.damage refers (presumably) to a damage attribute of
your item object. This item likely has a number of
attributes defined, for which damage is but one.

Attempting to understand Python purely by reading found code will
quite probably result in a number of leaps of conjecture leading to
misconceptions about the language itself. There is no substitute for
reading up on the basics of its syntax.

1 Like

Hi Myron,

The TL;DR is that:

  • you use underscores in variable names instead of a space;

  • and decimal points are used for numbers like 2.5 (duh!) but also for accessing methods and attributes of objects.

Underscores are just considered to be a letter of the alphabet for naming purposes. You can’t use two words for variable names:

best weapon = "axe"  # doesn't work

so we use an underscore instead:

best_weapon = "axe"

Underscores at the beginning, or at the begining and end, or a variable are treated as special by convention. As a beginner, the rule you should follow is:

  • never name a variable with a leading underscore, like _inventory, until you are more experienced and know why you would want to do this;

  • if you are using code written by somebody else, never use their variables starting with a leading underscore;

  • variables and methods with two leading and two trailing underscores are called dunders (from “Double UNDERscore”); they are reserved for the interpreter.

In general, you should not use dunders, but you can write dunder methods inside classes, e.g. your class has an __init__ method.

Dotted names look like “self.inventory” or “items.Rock”. That is a two part name. The first part up to the dot is the variable, and the second part after the dot is something belonging to the variable.

For example, “self.inventory” means you have a variable called “self”, and has an attribute called “inventory” belong to it.

(Other names for “attribute” used in other programming languages include “member”, “property” or even just “variable”.)

The attributes can be things like an inventory, or methods that you call to do something:

self.inventory  # the inventory belonging to self, the current Player

self.inventory = items.Rock()  
# Rock is a function, method or class belonging to the variable items;
# we call that function to produce a new rock object, that goes into the inventory.

If we were writing a program about animals, we might say:

cat.tail  # the cat's tail
parrot.speak()  # might print "Polly wants a cracker!"

If we were writing a program about cars, we might say:

car.model  # might be "Toyota Landcruiser"
car.fuel  # might be gasoline, LPG, diesel, electric or hybrid
car.engine  # the car's engine
car.drive()  # make the car go forward

Thank you Steven! This is a great explanation and provides me with clarity in terms I can follow along with.