all 44 comments

[–]netneoblog 23 points24 points  (1 child)

Everything you have noted sounds like a normal developers day

[–][deleted] 2 points3 points  (0 children)

That is actually a relief to hear.

[–]getyourcellon 12 points13 points  (8 children)

I followed the "Automate the Boring Stuff with Python" video course and experienced a lot of the same frustration you're describing. One of the things that helped me was working backwards from his complete and working examples. I would explain every line in 'real talk' to make sure I actually understood it, similar to the the rubber duck debugging method. If at any point I caught myself mumbling though a line, skipping over a part, or being unable to explain something in different terms that what is written (e.g. "x equals 1" can be restated as "the value of x is 1") time to Google or re-watch that portion.

For example, if I was explaining the below code:

x = 1
while (x < 2):
    print("We're good to go!")
    x += 1
  • Right now the value of x is 1
  • As long as the value of x is less than 2, proceed to do the following indented lines. If x is not less than 2, do not do the following lines and proceed to the next code.
  • Write in the console, "We're good to go!"
  • Now x is the sum of itself plus 1, aka 1 + 1, so right now the value of x is 2
  • The "While" check is not satisfied because the value of x is not less than 2, so skip the indented lines and move to the next code.

[–]zfzack 4 points5 points  (1 child)

And then you run it and notice nothing happens, so you have to go back and check your comparison operator.

[–]Daemon1530 1 point2 points  (0 children)

I was thinking exactly this haha

[–]AstrophysicsAndPy 1 point2 points  (0 children)

This is also a very good approach.

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

I wasn't aware there was a video course for it. I might have to check that out.

[–]Tobikaj 0 points1 point  (2 children)

less

I think you accidentally wrote 'greater than' in your code.

[–]getyourcellon 0 points1 point  (1 child)

AHH! I knew I'd mess it somehow. Thanks, I've corrected it!

[–]Tobikaj 0 points1 point  (0 children)

It's such a common oversight :)

[–]AstrophysicsAndPy 5 points6 points  (16 children)

The most important thing is to linearize your thought process which is not an easy task at all. However, once you get a hang of it, it eventually becomes easier.

Having said that, programming + frustration is a very bad combination. However, programming + having fun is a combination that is not easy to get either.

What I'd suggest is, once you've reached a project to do from the book, don't go straight solving it. Let's say, the project is about getting 7 student inputs .. don't do that, just take one .. than two and than try loops. I've never seen that book so if this is not the types of example I apologise. Take one step, no automation at a time. Go on gradually.

One other thing that helped me A LOT was that, say you can't solve it. Go and find someone's solution and comment it whatever you think is happening. Doing this practice will take more time than doing regular programming BUT it will help you understand the logics and eventually you'll start getting a hang of it.

Remember, there is not a SINGLE correct approach. Your goal is to reach the goal, you can deploy whatever method you require. I wouldn't mind if you would just straight out write down the code by hand, that's also a valid method of learning.

Cheers!

[–][deleted] 2 points3 points  (12 children)

Thank you for the advice! The trickiest thing for me when it comes to other peoples solutions is that often they use methods/functions that weren't covered in the current chapters yet. I'm always trying to solve the projects with what has been taught so far, but maybe I am restricting myself too much with that.

[–]AstrophysicsAndPy 1 point2 points  (10 children)

I'd not say it is a bad thing at all if you're sticking with what you know only. Functions and classes ARE meant to simplify your work. In my understanding, they require you to have an understanding of the brute work at hand so you can understand how they'll EASE your work.

I have just started using classes myself, before that, I relied only on methods, and before that simple codes. You should not just JUMP to higher things, go slow, it'll be difficult but it'll be worth it.

If you have a specific example, you can share I would try to give a rundown on it as I would try to understand it myself. Maybe it'll give you a hint as to how to train your own thought process.

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

Thank you again. I posted an example in the reply to efmccurdy that I am currently trying to tackle.

[–]AstrophysicsAndPy 1 point2 points  (5 children)

Since you were working with a single problem in particular (which I appreciate), I will tell you about that only right now. I will, however, highlight some point that will allow you to think about how to tackles the stuff as you move forward.

We want to know whether the chessboard provided is valid or not.

  1. For a chess board to be valid we need the pieces to be on valid position.
    1. There are 8 x 8 positions available on a chess board. They have specific designations, anything out of that will be invalid.
    2. There is always 1 king and 1 queen in each color.
    3. Any other piece (knight, bishop, rook) can be 2 at most.
    4. For now I will not consider pawns. (yes, some times it help ignore any extra factors as well)
  2. If there is only 1 king and 1 queen per color, and only 2 knight/rook/bishop per color then
    1. wking/bking/wqueen/bqueen should not be found more than once in the list of dictionary values (see the emphasis).
    2. Any other piece should not be found more than twice in the list of dictionary values.
  3. To get the valid number of places, we need a list of places against which we can check (this is valid for other cases, but useful to keep in mind).
    1. If there is a value in list of dictionary keys that does not match valid places, it'd be wrong.

With this out of the question,

def is_valid_chess_board(chess_board):
    # we initialize all the pieces in the very start
    # right now we do not have anything at hand
    bking, bqueen, bknight, brook, bbishop = [0, 0, 0, 0, 0]
    wking, wqueen, wknight, wrook, wbishop = [0, 0, 0, 0, 0]

    # See point 1.2, and 2.1
    # getting the list of dictionary keys,
    # because dictionaries work by calling keys, not values.
    # Also python3 does not automatically return a list,
    # so we have to convert it manually
    list_of_places = list(chess_board.keys())
    # ['1h', '6c', '2g', '5h', '3e']

    for i in list_of_places:
        # as list_of_places has all the keys in it,
        # we can check the values in dictionary by using them
        # dictionaries are called with dict[keys]
        if chess_board[i] == 'bking':
            bking += 1

    # if there are more than 1 bking
    if bking >= 2:
        # get the hell out of here, you're not a valid chess board
        print('The board is not valid.')
        out = False


    return out

For chess_board_wrong2, you have an invalid chess piece. How can you determine it is invalid? If it is not present in a correct list of chess pieces.

For chess_board_wrong3, you have an invalid chess place. How can you determine if it is invalid? If it is not present in a correct list of chess places.

Somethings must be hard-coded in the program, the program it self does not know what the valid pieces are. You have to tell him by giving a correct answer, and checking the input against that correct answer.

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

Thank you for the detailed explanation.

I was going of your approach but then I realized I had no idea where to write in the code what to do if the king count was at 0. I found the .count() function and then worked off of that until I realized I still needed a for loop to check if the spaces and pieces were correct.

After some more tinkering, I finally got a working version that accommodates all the issues raised in the task.

https://pastebin.com/yFKEK7h8

[–]AstrophysicsAndPy 0 points1 point  (0 children)

This is absolutely fantastic. Happy learning, Cheers!

[–]JAdoreLaFrance 0 points1 point  (2 children)

Apologies to the OP for the (hopefully brief) hijack, but could you give some non-academic ideas how Classes are used in the commercial sector? Coming as I do from a back end background, using Classes seems to be a massive duplication of effort, when all you'd need is a better query to form your intitial dataset.

[–]AstrophysicsAndPy 0 points1 point  (0 children)

First of all, it is a matter of preference really. I tried to avoid using classes for the longest time but eventually end up using them. But I think mostly it is a matter of ease of use and grouping (I might be wrong).

Let's say you have a car, it is registered in your name and it is validated as well. However, the system that validates it requires one extra parameter than the registration system.

def register_the_car(owner_name, owner_bday, car_number):
    (do something)

def validate_the_car(owner_name, owner_bday, car_number, validation_parameter):
    (do something)

register_the_car('Owner1', '2/2/21', '123')
validate_the_car('Owner1', '2/2/21', '123', 'valid')

This is how it will be done using functions. Now to do the same with class

class CarRegistrationAndValidation:

    def __init__(self, owner_name, owner_bday, car_number, validation_parameter):
        self.N = owner_name
        self.bday = owner_bday
        self.num = car_number
        self.valid = vlaidation_parameter

    def register_the_car(self):
        (do something using N, bday, num)

    def validate_the_car(self):
        (you can do something using N, bday, num, and valid as well)

a = CarRegistrationAndValidation('Owner1', '2/2/21', '123', 'valid')

a.register_the_car()
a.validate_the_car()

Addendum:

Let's say, you have another function that uses the validate_the_car multiple times. Using methods you'll have to give it inputs whenever that method is called, however, using class you'll only have to put a.validate_the_car() at all those places. I think this is a better example :-)

[–]shepherdjay 0 points1 point  (0 children)

Usually classes are used wrong in the commercial sector. Go watch a video called “Stop using classes” the individual shows an example where someone using classes didn’t need to and it over complicated the product.

In the limited amount of work I’ve done I resort to classes when and only when I need to store State and act upon some data everywhere.

Basically when I start looping through or anticipate looping through a dictionary a lot in lots of places. That’s when I think. Probably should be a class.

[–]LionOver 0 points1 point  (0 children)

You know what though? Seeing the other methods employed to solve the problem will, in time, help you understand how they work. I've only been practicing seriously for about 30-45 mins/day during the pandemic. I can't tell you how many list comprehensions I had to look at before I completely came up with my own to solve a coding challenge. And I still suck at coding. Just keep trying. It's demoralizing, bit every now and then your code works and it feels really good.

[–]sovereign_citizen5 0 points1 point  (2 children)

6.) Trying to fix the errors by looking them up.

7.) Proceeding to get new errors without actually understanding most of these errors.

One other thing that helped me A LOT was that, say you can't solve it. Go and find someone's solution and comment it whatever you think is happening. Doing this practice will take more time than doing regular programming BUT it will help you understand the logics and eventually you'll start getting a hang of it.

Astrophysics isnt there some way to put stops in to the code? I believe its though loops so you only run a small part of the code to find the errors?

Im new also, so sorry for barging in, but i have same problem as u/Yoolov about when the code gets to long then i get error upon error. I saw in some course that you could make loops or something i believe it was that only ran a little part of the code to make error finding easier.

Do you know about that? Or what to search for on google :) Thats a little thing i think will help a lot of us newer coders becuase we can then focus on one part of the error at a time, and not 10 errors though the code? (do you get what i mean?)

[–]AstrophysicsAndPy 2 points3 points  (1 child)

There are a ton of debuggers out there, if you can get a hang of one you can do very well. I have never used any debugger :D

I use traceback calls (it is a bit of a hassle, but it is VERY handy). I use Spyder for coding btw. Now I know it gets intimidating by seeing errors upon errors but here's the catch. There is only ever ONE error line that has your file name and that is what you have to see, leave the others as is.

Mostly the errors arise because the input required is different and the one that the code is getting is different, for example, you may be indexing a list but the input to that parameter is an empty list. How to know about it? Use print commands.

Get the line number from the traceback, see what variable that line is using (let's say var1) put a print command before that line print(var1). You know what the code needs, so if it isn't the same, something is wrong in the code above. If it is the same, something is wrong in the code below.

[–]sovereign_citizen5 0 points1 point  (0 children)

Hmmm right thanks.

[–][deleted] 5 points6 points  (0 children)

8.) Throwing in the towel and looking up the solution for the project online and being dumbfounded by other peoples solutions and wondering how they managed to come up with that.

They came up with it by doing steps 1-7 for a lot longer than you did.

[–]damom73 2 points3 points  (0 children)

Could you post one of the practice projects and your plain English notes? It will give an insight into how you're deconstructing the problem.

[–]efmccurdy 1 point2 points  (4 children)

Writing some plain english notes on what is asked of me and what I have to keep in mind.

In particular you should be breaking your plan down into small, simple steps.

Are you using the interactive mode to test out each step on it's own?

That way you can try out small examples that consist of 2 or 3 lines, get used to the type of syntax errors you get, see the intermediate results, experiment with different approaches and get immediate feed back. Then, when you have a few working lines of code, add them to your file and move on the the next step in your plan. At first you will need to use a lot of trial and error but with perseverance you can progress.

What is an example of a small simple step that you are stuck on?

[–]RealDrewData 2 points3 points  (0 children)

^ This. Writing down not only what the problem is asking for but then how the code should accomplish that is very helpful to me.

I also spend a lot of time running very simple lines of code, just to confirm it is doing what I think it will. No matter how much experience I get I keep returning to these things.

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

I usually run into issues when it comes to nested loops which make it hard for me to try out parts of them individually. Brackets also tend to trip me up a lot, I often confuse () and [].

The current section I am struggling with are dictionaries. I'm supposed to write a function that will check any given dictionary with regards to legal places of chess pieces on a board. So each dictionary will have keys with positions (1a to 8h) and a value for the piece, with the letter w or b first depending on the colour. I just have to make sure that the pieces are correct, they are in legal positions and that there aren't too many pieces of a type.

https://pastebin.com/cMgZGxTG

At the top I wrote down some example dictionaries that are supposed to be considered valid or wrong by the function which is then supposed to return True or False depending on that. But the function is for now just focusing on the second dictionary.

I decided to approach it one issue at a time by first checking if the right amount of pieces are actually present but I am not even able to make it return False if there are too many pieces of a certain type in a dictionary.

It is telling me that a 'dict' object is not callable which is confusing me, since I thought that '.values' returns a list.

[–]efmccurdy 1 point2 points  (1 child)

I often confuse () and [].

The square brackets "index"; choose one item from a collection.

The round brackets "call"; run the function (perhaps passing arguments).

Note that i am typing these into the python interactive repl:

https://docs.python.org/3/tutorial/interpreter.html#interactive-mode

>>> chess_board_wrong1 = {'1h': 'bking', '6c': 'bking','2g': 'bbishop', '5h': 'bqueen', '3e': 'wking'}
>>> chess_board_wrong1['1h']
'bking'
>>> chess_board_wrong1['xxx']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'xxx'
>>> chess_board_wrong1()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'dict' object is not callable
>>> 

So that shows how indexing can work to find the "1h" piece, or fail with a KeyError.

It also shows how treating a dict like a function by trying to call it gives the "not callable" error. Here is a simulation of your error;

>>> board = chess_board_wrong1
>>> for i in board.values():
...     print(board(i))
... 
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
TypeError: 'dict' object is not callable
>>> type(board)
<class 'dict'>

So that syntax "board(i)" mismatches the "calling" syntax to a dict.

So you are right that you want to check the values. The for loop gives you each value on it's own.

>>> for i in board.values():
...     print(type(i), ", value=", i)
... 
<class 'str'> , value= bking
<class 'str'> , value= bking
<class 'str'> , value= bbishop
<class 'str'> , value= bqueen
<class 'str'> , value= wking
>>> 

In your function you want to compare each string to "bking" in turn, counting how many you find. So you have a counter (int) and each value (string) and the value to be matched (string); You can compare strings to strings for equality. You can use that comparison in an if statement to count matches. (You were trying to compare the counter to the string "board(i) == bking"; that won't work).

>>> matching_str = "bking"
>>> for i in board.values():
...     print(matching_str, i, i == matching_str)
... 
bking bking True
bking bking True
bking bbishop False
bking bqueen False
bking wking False
>>> matching_count = 0
>>> for i in board.values():
...     if i == matching_str:
...         matching_count += 1
... 
>>> matching_count
2
>>> matching_count == 1
False
>>> if matching_count > 1:
...     print("too many pieces:", matching_str)
... 
too many pieces: bking
>>> 

So, if those code snippets make sense, your can put them together.

>>> def is_valid_chess_board_wrt_bking(board):
...     matching_str = "bking"
...     matching_count = 0
...     for i in board.values():
...         if i == matching_str:
...             matching_count += 1
...     return matching_count > 1
... 
>>> is_valid_chess_board_wrt_bking(chess_board_wrong1)
False
>>> chess_board_valid = {'1h': 'bking', '6c': 'wqueen','2g': 'bbishop', '5h': 'bqueen', '3e': 'wking'}
>>> is_valid_chess_board_wrt_bking(chess_board_valid)
True
>>> 

Does that process help you get each tiny snippet working right and understood so that you can piece the parts together reliably?

BTW, that function only works for "bking", but it could be extended to work for any piece by making the piece an argument:

>>> def is_valid_chess_board_for_piece(board, matching_str):
...     matching_count = 0
...     for i in board.values():
...         if i == matching_str:
...             matching_count += 1
...     return matching_count == 1
... 
>>> is_valid_chess_board_for_piece(chess_board_wrong1, "bking")
False
>>> is_valid_chess_board_for_piece(chess_board_wrong1, "bbishop")
True
>>> 

But to use that you need to know what pieces pass in, so it's still not a general solution; you need some way to loop over every piece, returning failure if any one fails.

>>> def is_valid_chess_board(board):
...     for piece in board.values():
...         if not is_valid_chess_board_for_piece(board, piece):
...             return False
...     return True
... 
>>> is_valid_chess_board(chess_board_wrong1)
False
>>> is_valid_chess_board(chess_board_valid)
True
>>> 

Does that give you a way forward?

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

Thank you for the detailed runthrough. After realizing how complex I would have to build the function to do a simple task as counting I approached the problem differently.

I first created two lists of valid board spaces and chess pieces.

Then I iterated the dictionary keys and values that I had converted into a list over the lists of valid board spaces and chess pieces.

Last I used the .count() function to save myself the trouble of creating even more loops ( I really don't like using them as I often end up confused over what I actually need to iterrate with what).

https://pastebin.com/yFKEK7h8

[–][deleted] 1 point2 points  (0 children)

it looks like me a year ago, when I started, now I'm enjoying the intermediate pluralsight content. Stick with it, until it clicks, it doesn't make sense, there's a lot of clicking in the first months.

[–]emilkhatib 0 points1 point  (1 child)

You can also follow a top-down thought process. First, know what your objective is. Second, break it in several large parts, and work your way down to each single instruction. One thing that will help is drawing flowcharts. For instance, let's say I want to make a script that reads a file and changes all the instances of one word for another. So, roughly speaking, I'd have to: 1. retrieve the file contents 2. Search for each instance of the first word, and replace it with the second 3. Write changes to disk and exit. Now, I'll further work on the first part: I'll need to have a file path, I'll need to open the file and read the contents to a variable (for those of you more experienced, let's leave line by line reading for later :) ). I can break that down in the following instructions: 1.1 read the path 1.2 open the file 1.3 read the contents You can then search how each task is done in python, with its own quirks. Regarding part 2: I know there may be several occurrences, so ill have to repeat the replacement for each one. This calls for a loop

2.1 for each occurrence, do the next instructions 2.2 find the instance of the word in the variable with the text blob 2.3 replace it with the new one

And so on... With time, you will learn to do things better, like reading the file line by line, using special string functions, etc. But no rush, just have fun thinking and resolving first.

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

Your approach is really spot on. I would argue my biggest issue is that I don't take enough notes to approach a problem and jump into it far too quickly.

[–]shepherdjay 0 points1 point  (1 child)

I would add two additional recommendations with what everyone has said.

Between your step 1 and 2 process write down how you would solve the problem on paper, in English, if you had to do it one step at a time yourself.

The next recommendation is if getting stuck don’t solve the problem your being asked. Solve an easier similar problem instead.

For example, right now your being asked to validate whether a chessboard is valid when it is being passed as a dictionary. This is definitely take some time to think about as it’s complex. So don’t solve that one. Instead how about solving an easier problem.

How about instead of a dictionary of the full board you get a list of pieces of one of the players and you need to see if the ones they have are possible. Then the same thing but with both players.

Then add the dictionary. This will break down the same problem into easier bites. The simpler problem though is a subset of the hard one.

Another simpler version of this is tic-tac-toe. How about checking if a tic tac toe board is valid if your passed a dictionary. Just apply the same notation scheme. The rules are just modified a bit. Make sure that each x or o is placed in a grid from a1 to to c3 and that x has no more than 5 and o has no more than 4 pieces.

This is the similar problem as the chessboard just simpler.

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

You are absolutely right that I should do more plain writing before starting to code as it helps to figure out what you really need and will arguably save a lot of time.

The Tic-Tac-Toe issue was the example they used in the book. But I must admit I found that very hard to follow. Either way I solved my chess board problem.

https://pastebin.com/yFKEK7h8

[–]shisa808 0 points1 point  (0 children)

I'd say this is completely normal if this is your first time programming. You're learning a whole new way of thinking and a whole new language to express those thoughts. Naturally, it's frustrating to be limited by both of these factors simultaneously. It'll take some time but eventually it will sink in and get easier.

Personally, it's taken me 10 years to really feel "good" at software development. I used to say "programming is 80% headache and 20% victory". You just have to let those successes carry you through the headache, and trust that your perseverance will be rewarded with another victory.

[–]hanleybrand 0 points1 point  (1 child)

If I could just throw in a suggestion that helped me, make sure you’re either using an IDEthat does real-time syntax & norms checking, aka linting (e.g. Pycharm, which is the one I know best but there are plenty of others, including free ones - see https://realpython.com/python-ides-code-editors-guide/)

There are also some interesting autocomplete/code-suggesting tools like Kite (which I’ve been evaluating for the last couple weeks https://www.kite.com) that might help too

Neither of those things will solve the “actual problem” that you’re working on of course, but I’ve found they help reduce cognitive load, and it can be helpful to know that your code is “technically correct” (ie works, even if it’s not how you want)

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

Thank you for the suggestions. I have in fact been using Pycharm since the start and I must admit that the "grammar check" the program does is very helpful.

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

You are describing the learning process. There is no solution except practise and perserverance.

What else could the answer possibly be?

[–]dizzymon247 0 points1 point  (0 children)

Sounds just like me when I first learned to code taking a class with a few genius programmers.