Calling `print("Hello World")` saves you from writing the code that sends text to a display. That is the practical value of an application programming interface (API): it lets one piece of software use another piece’s functionality through an understood interface, without taking on its implementation. section 3.1 section 3.1.1
Think of an API as a contract. A caller supplies the expected input; the receiving code performs work, returns information, or both. A function’s name, arguments, and return behavior are therefore part of its API. The implementation can remain a black box as long as callers can rely on the agreed behavior. section 3.1.1 section 3.5
The boundary can be small or large. A function or class method you create is a local API, as is an imported module’s interface. Applications also use APIs to access operating-system services and code running on a server. A remote API adds a network connection between the caller and the functionality. section 3.0 section 3.1.1 section 3.5
print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)
The `print` signature shows how one familiar API accommodates several needs: `*objects` accepts multiple values, while defaulted parameters let callers change separation, line ending, destination, or flushing only when needed. section 3.1.2
Grow a function’s contract deliberately
A `full_name(fname, mname, lname)` function makes its three inputs and their order clear. Giving `mname` and `lname` defaults makes them optional; accepting `*names` instead supports a variable number of name parts. Each choice changes what callers must know, so choose the simplest interface that fits the intended use. section 3.2.2
Design for the next caller—including yourself. Clear module, function, and class names, consistent parameters, and documentation make functionality easier to discover and use. The payoff is code that depends on a predictable interface rather than on the details behind it. section 3.4 section 3.5











































