Getters and setters are confusing because there are no reasons to use them for small projects, like what you would build in a college course. Software becomes exponentially confusing the larger it becomes. In addition, one piece of software may be built by multiple teams, such as using third party libraries. The best way to handle the additional complexity is to split each section into two: the interface (public) and the implementation (private). Here are the reasons why:
First, change. Changes to code happen all of the time. If someone wants to build a library so that many other users can interact with it, they have to realize that one day changes to that library will need to happen. If code is separated into public and private properly, then any private functions and fields can be rewired, and as long as the rewiring makes the public functions and fields perform the same, then the change will not break anything. How important is not breaking things? Well anyone familiar with Python's 2 and 3 schism knows the pain of changes that break compatibility.
Second, visibility. When you are interacting with a large codebase, you need to know what functions and fields to interact with. IDEs have very useful tools that can list these for you, but if everything is public then they will list everything. If 90% of your codebase is private data, that is a lot of useless functions and fields to sort through!
Third, hackery. When you are building a large codebase, there may be some things you don't want you programmers interacting with it to do. Users might take advantage of quirks in your code that were never meant to be used that way. XKCD's Spacebar Heating comic illustrates this nicely. Another reason may be security, as you might not want someone to have full access to functions and fields to poke around and understand your code better.
So these are the reasons why public and private are important concepts. The problem is then if something starts out as public, it won't have any of these advantages. If you want to change it to private later on, then you are screwed. So the Java solution is to make everything private from the beginning. Vanilla getters and setters are really just making private data appear public. Then if the data needs to be changed from "public" to private, the getters and setters can be modified accordingly.
Python's property approach is a similar concept, but infinitely better, as instead of relying on a programmer to build getters and setters, the language itself invisibly builds them under the hood. Then if you want to change something from public to private, instead of being screwed, you just add a property tag with the getter and setter code to change the getter and setter from an invisible default to a visible modification.