The other review is kind of OK but is focusing on the little things instead of the things that would make you a "real" programmer.
It all depends on the perspective you take on that program :
- Since you program in Python you probably have an implicit sense that it should be a small, self-contained script. That's OK but I'm guessing that's not how you're trying to improve.
- However, if you imagine for a second that this is just a "practice run" for a "real" program -- a program which would, let's say, be accepted in the corporate world -- then it's missing two serious things :
1) Break it down
By doing so, you are doing two different things:
- For the READER: it makes the flow easy to follow. I'm not just saying that the program is easier to "understand". I'm saying that the FLOW is more straightforward, as the reader knows at all times what exactly comes in and out of subparts.
- For the PROGRAM : avoid side effects, which means you literally FORBID unwanted parts of the program to mess with other wanted parts and with the global state (which you're aiming at removing entirely, ideally).
It's not just about separating bits of code. It's to stay in control of the flow. Right now, as one big function, everything has access to everything.
You need to break it down into smaller functions that can change only what they need to change, nothing more. That's what we call leaving no room for side effects.
The most obvious break down is to move the entire code inside of the while
to its own separate function, which you could for example name update
. Then your challenge is to decide how that function notifies the loop
that it needs to exit, as variable done
is now inside the function. That's for you to solve.
Another bit of code that you can move to a separate function is the loop asking "are you sure you want to exit".
etc.
2) Separate the infrastructure from the business logic
I used big words to make you think ;-)
You need to imagine that you can't know in advance what underlying subsystem will render the output. Maybe it will be text in a console, maybe it will have graphics, etc.
Even when you're 100% sure that the output goes to the terminal, in effect you still don't know anything. Maybe it will be handled by a third-party library. Maybe there is some hidden mechanism to log stuff to a log file. Etc.
Therefore, you need to separate the input/output from the rest. To achieve that, maybe you need to have a tiny library that contains : a wrapper around input
, a wrapper around print
, a wrapper around isnumeric
and isalpha
. Then you need to throw in the parsing of the input : A function isQuit
, isY
, isN
. All of that is good practice because maybe in the future another dev will revisit those methods and make them handle upper case and lower case (that's just an example).
On the other hand, the "business logic" is everything that handles the state of the game in a "perfect world" where you don't have to worry about I/O or that kind of things. In your game the business logic is at least a function "has_won". And its siblings: is_bigger
, is_smaller
. Yes, as overkill as it sounds, if int_num == realno:
is the core of your business logic and must be put on some kind of pedestal, isolated from the rest, so that any reader can tell :"Aha, that's the important part that should never be broken by my changes".
3) Exit the application cleanly!
Remember what I said about staying in control of the flow? Well right now there are two entirely separate flows for exiting the application :
- by setting "done" to true, which exits the loop
- by calling "exit()" right in the middle of the loop.
That's not very good for the reader.
Plus, if you want to add a goodbye message then you'll have to add it in both places.
A single flow!
Instead I would add quit
to the exit condition of the loop :
while not done and not quit:
realno = random.randint(1, 10)
\$\endgroup\$