Two ways. Rejection: map two uniforms to x and y in [−1, 1], keep the point if x² + y² ≤ 1 and draw again if not; about π/4, or 78.5%, of draws are kept. Polar: take the angle as 2π times one uniform and the radius as the square root of another, because area grows with r², so a plain uniform radius crowds points into the centre. Check either by confirming that about a quarter of the points fall within radius 0.5.
import math, random
def in_circle_rejection():
while True:
x, y = 2 * random.random() - 1, 2 * random.random() - 1
if x * x + y * y <= 1: return x, y
def in_circle_polar():
theta, r = 2 * math.pi * random.random(), math.sqrt(random.random())
return r * math.cos(theta), r * math.sin(theta)
pts = [in_circle_polar() for _ in range(100_000)]
print(sum(math.hypot(x, y) <= 0.5 for x, y in pts) / len(pts)) # about 0.25
Expect a follow-up on cost: rejection throws away about 21% of draws here, and the share wasted grows quickly in more dimensions.
Wolfram MathWorld: Disk Point PickingPython docs: random
Practise it with Prism