Why rectangle is fundamental ?

Rectangles are very important in game development. As we will see later all heroes, players, monster or other thing moving in your games will be just images (or 3D objects in 3D graphic) with some parts transparent. So why not represent their position in game world by squares.
There is another advantage that is very important. Some objects on the screen have really hard shapes to describe. So how we will move them or have we will detect collisions with them ? Yes we can use per pixel detection but it is precious time consuming. And if you have 10 000 of them in game ?!? Rectangles are better because they have easy, simple and fast mathematical methods to detect collisions and sometimes you need only roughly precision.
However if you still need per pixel detection don't worry just do general rect detection and if there is any do for them per pixel detection. So from 10 000 possible collisions (and 10 000 fast operation) you will get 10 possible (and only 10 slow operations). Big optimization don't you think?

pygame.Rect have several attributes:
top, left, bottom, right
topleft, bottomleft, topright, bottomright
midtop, midleft, midbottom, midright
center, centerx, centery
size, width, height
w,h
You can change every of them. But changing size, width or height will change automatically others.

pygame.Rect.move
pygame.Rect.move_ip

Games without motion are boring. But how to update ours rectangles? Simply pygame.Rect.move(x,y) will return new rectangle placed in (x,y) point. pygame.Rect.move_ip(x,y) behaves the same but it will change current Rect.

pygame.Rect.inflate
pygame.Rect.inflate_ip

If wont to produce new Rect with changed height and weight (but centered at the same point as current Rect) use pygame.Rect.inflate(x,y) where x and y are offsets that height and weight will be changed by. Negative values will shrink Rect.
Use pygame.Rect.inflate_ip to change current Rect.

pygame.Rect.clamp
pygame.Rect.clamp_ip

Sometimes we need to move one Rect into another Rect (or get new one moved). Rect have pygame.Rect.clamp(another_rect) function to do that (or corresponding pygame.Rect.clamp_ip)

pygame.Rect.clip

Pygame.Rect.clip(Rect) will return new Rect fitting in gived Rect or 0 if current Rect and given don't overlap.

pygame.Rect.union
pygame.Rect.union_ip
pygame.Rect.unionall
pygame.Rect.unionall_ip

Pygame.Rect.union(Rect) will have opposite effect. It will return Rect that contain current and given Rect and possibly other areas. pygame.Rect.union_ip(Rect) will change current Rect and pygame.Rect.unionall(Sequence_of_rects) will do that for many rects. pygame.rect.unionall_ip(sequence) will change current rect

pygame.Rect.fit

pygame.Rect.fit(Rect) create new rect that is moved and resized to fit into given Rect but aspect ratio (weight/height) is unchanged so new Rect can have weight or height smaller than given Rect.

pygame.Rect.normalize

Using functions that change Rect can sometimes cause that Rect will have negative weight or height. Use pygame.Rect.normalize() to change them to positive values (without moving or scaling).

To test collision PyGame have multiple functions for multiple thing that we wan't to test against:

pygame.Rect.collidepoint

pygame.Rect.collidepoint(x,y) test if given pint is inside current Rect.

pygame.Rect.contain

pygame.Rect.contain(Rect) will return True if current Rect contain inside given Rect.

pygame.Rect.colliderect

pygame.Rect.colliderect(Rect) return true if any part of Rect overlap with current.

pygame.Rect.collidelist
pygame.Rect.collidelistall

pygame.Rect.collidelist(list) will return first rect that collide with current one while collidelistall(list) will return all rects that collide with current.

pygame.Rect.collidedict
pygame.Rect.collidedictall

collidedict(dictionary) and collidedictall(dictionary) behaves the same but operate on dictionary.