Trying to set a variable from a value in a dictionary
Question: I'm learning python and am creating a rock paper scissors game.

I'm stuck on one part.

I have 4 variables currently (Although I would like to get it down to 2)

  * pKey
  * pChoice
  * comKey
  * comChoice

They look up the the Key and Value respectively in a dictionary.

    
    
    choice = {1:'rock',  2:'paper',  3:'scissors'}
    

The problem I'm having is getting the keys from the dictionary using the
variables.

Here's the code snippet that's giving me trouble

    
    
        print('--- 1 = Rock    2 = Paper     3 = Scissors --- ')
        pKey = input() # this is sets the key to the dictionary called choice
        while turn == 1: # this is the loop to make sure the player makes a valid choice
            if pKey == 1 or 2 or 3:
                pChoice = choice.values(pKey)  # this calls the value from choice dict and pKey variable
                break
            else:
                print('Please only user the numbers 1, 2 or 3 to choose')
    
        comKey = random.randint(1, 3)  # this sets the computer choices
        comChoice = choice.values(comKey)
    

Specifically the troublesome part is

    
    
     pChoice = choice.values(pKey)
    

and

    
    
     comChoice = choice.values(comKey)
    

I've tried everything I know from using brackets, trying different methods,
and using different formats.

Would love to learn this! Thanks!


Answer: Sounds like you're just trying to do a dictionary lookup

    
    
    pKey = 1
    pChoice = choices[pKey]  # rock
    

`dict.values` is used to create a list (actually a `dict_values` object) with
all the values of the dictionary. It's not used as a lookup.

* * *

As far as your code structure goes, it could use some work. The
rock/paper/scissors choice is perfect for an `Enum`, but that might be a bit
beyond you right now. Let's just try as a toplevel module constant.

    
    
    ROCK = "rock"
    PAPER = "paper"
    SCISSORS = "scissors"
    
    def get_choice():
        """get_choice asks the user to choose rock, paper, or scissors and
        returns their selection (or None if the input is wrong).
        """
        selection = input("1. Rock\n2. Paper\n3. Scissors\n>> ")
        return {"1": ROCK, "2": PAPER, "3": SCISSORS}.get(selection)
    

Addressing them as constants makes sure they're the same everywhere in your
code, or else you get a very clear NameError (instead of an if branch not
executing because you did `if comChoice == "scisors"`)

* * *

A minimal example with an enum looks like:

    
    
    from enum import Enum
    
    Choices = Enum("Choices", "rock paper scissors")
    
    def get_choice():
        selection = input(...)  # as above
        try:
            return Choices(int(selection))
        except ValueError:
            # user entered the wrong value
            return None
    

You could extend this by using the more verbose definition of the Enum and
teach each Choice instance how to calculate the winner:

    
    
    class Choices(Enum):
        rock = ("paper", "scissors")
        paper = ("scissors", "rock")
        scissors = ("rock", "paper")
    
        def __init__(self, loses, beats):
            self._loses = loses
            self._beats = beats
    
        @property
        def loses(self):
            return self.__class__[self._loses]
    
        @property
        def beats(self):
            return self.__class__[self._beats]
    
        def wins_against(self, other):
            return {self: 0, self.beats: 1, self.loses: -1}[other]
    
    s, p, r = Choices["scissors"], Choices["paper"], Choices["rock"]
    s.wins_against(p)  # 1
    s.wins_against(s)  # 0
    s.wins_against(r)  # -1
    

Unfortunately there's no great way to lose the abstraction in that
(abstracting out "paper" to Choices.paper every time it's called) since you
don't know what `Choices["paper"]` is when `Choices.rock` gets instantiated.

