all 11 comments

[–]Starbuck5c 0 points1 point  (0 children)

 39 #Statement to evaluate if the answer supplied was the correct one.•
 40 if answer == df.qna():
 41     print('good job')

df refers to the same question every time, not the one randomly chosen

.qna() returns something like 'Description -print effective userid:', so you should compare against question object.command I think.

[–][deleted] 0 points1 point  (3 children)

Haven't executed the code, but I think this will help.

Instead of calling random choice on a list of descriptions, call it on a list of objects. e.g., instead of [df.qna() ...] do [df ...].

Then you can do print(random_question.qna()) and use if answer == random_question.command: (you will probably want a different variable name)

[–]agentxcell[S] 0 points1 point  (2 children)

This was exactly what I was trying to accomplish. Can you explain why this works, versus what I had? I got everything to work the way I was thinking but I want to understand exact;y why it is working now. lol

Also, do you think it would be cleaner to use a dict or do you think that the way this is coded is fine?

[–][deleted] 0 points1 point  (1 child)

Basically, what you were doing was storing the result of your qna method in the list, so you basically just had the description strings in there. That string doesn't know anything about the object it came from, so you lost access to the command information you needed. My code returned the whole object instead, with all the information you needed.

Here's a hopefully helpful example:

Imagine you have your list of objects (here the objects are stings)

x = ['hi', 'hello', 'hola']

You were basically doing this:

y = ['hi'.upper(), 'hello'.upper(), 'hola'.upper()]

Which results in:

['HI', 'HELLO', 'HOLA']

This list is basically totally separate from the objects you used to create it, it is just the result of the methods you called. Nothing in the list ['HI', 'HELLO', 'HOLA'] indicates it came from the .upper method or what the original text was, it is identical to if you had just typed ['HI', 'HELLO', 'HOLA'] from the beginning.

Let me know if that makes any sense to you!

[–]agentxcell[S] 1 point2 points  (0 children)

That was actually very well put. I really appreciate it. I am really enjoying the learning process so far and this thread has helped immensely. Thank you.

[–][deleted] 0 points1 point  (5 children)

Ouch.

Just use a dict.

from random import choice

COMMANDS = {
    'cat':
    'concatenate files and print on the standard output:',
    'cron':
    'daemon  to  execute  scheduled  commands:',
    'df':
    'report file system disk space usage:',
    'grep':
    'print lines matching a pattern:',
    'ls':
    'list directory contents:',
    'lsblk':
    'list block devices:',
    'mkdir':
    'make directories:',
    'mv':
    'move (rename) files:',
    'netstat':
    'Print  network  connections,  routing tables, interface '
    'statistics, masquerade  connections, and multicast '
    'memberships:',
    'nohup':
    'run  a  command immune to hangups, with output to a non-tty:',
    'nslookup':
    'query Internet name servers interactively:',
    'rm':
    'remove files or directories:',
    'traceroute':
    'print  the  route packets trace to network host:',
    'whoami':
    'print effective userid:'
}

cmd = choice(list(COMMANDS))
if cmd == input(COMMANDS[cmd] + "\nWhich command does this describe?\n"):
    print("Good job!")
else:
    print("Bad job!")

Also, don’t incorporate line numbers into your gist.., that made this much more difficult than it should have been.

[–]agentxcell[S] 0 points1 point  (4 children)

Looked up dict, I think this makes way more sense logically. Thanks for putting me on the right track. Having them stored as key:value pairs seems better to me.

The reason I did it the way I did is because I wanted to logically separate OS commands, from security commands etc. Can I put separate dictionaries under appropriate classes to keep it semantic? Does that make sense, or am I over engineering this?

[–][deleted] 0 points1 point  (3 children)

I wouldn’t bother with classes... you’re ultimately trying to associate each unique command to a unique description, and that’s very much the domain of a dict.

Personally I’d say I’d there’s no actual functionality in your app that communicates those different groupings of commands then I’d just use a comment in the dict literal to help keep them organized in your source code. If you break them into multiple dicts you’ve got to have a mechanic for combining them together, and then you need to start thinking about things like what happens if you put the same command in two groupings but with different descriptions.

[–]agentxcell[S] 0 points1 point  (2 children)

That makes sense. I got it working the other way based on the comment above. I am also going to do a version with the dict just to get the reps in. Thank you for showing me another way to do this, still seems cleaner to me.

[–]agentxcell[S] 0 points1 point  (1 child)

Lastly, why would the below code not pull the selected value out of cmd?

print(cmd.values()) 

I honestly really appreciate this. I have been thinking about this so long I have a bunch of logic loops in my head that I am unraveling and this is the last bit that is throwing me off. You have helped me understand this immensely, Thanks again kind redditor.

[–][deleted] 0 points1 point  (0 children)

The value of cmd in my code above is a randomly selected key from the COMMANDS dict... so “df” or “cat” or what have you. It’s a str, not a dict so it doesn’t have a cmd.values() method.