A very basic question about DAC conversion in a sound card
For example, below discrete sinusoid stem plot is composed of 48 points per period of a sine:  


No, it's not!


  Would we hear f = 1/[48 * 1/(48000)] = 1kHz vibration?


For the particular waveform you've plotted, you would hear f = 1/[47 * 1/(48000)] = 1021Hz vibration.

If you were intending to represent a 1kHz waveform, you've made the classic off by one fencepost error mistake of thinking the number of points was equal to the number of intervals. You need 48 intervals in the waveform, which means as the curve starts and finishes at zero, you need one extra point, for 49 points to make 48 intervals.

With Python, include the PyAudio library, which is a python binding for PortAudio v19, which will drive most cards on most operating systems. Generate the waveform as a Numpy array, and follow the documentation with the library. IIRC, if you use floats, then +/- 1 corresponds to full scale on the DAC, but if you use integers, then +127/-128 or +32767/-32768 correspond to full scale depending on the 8/16 bit mode. RTFM and all will be revealed.

You might prefer to use Audacity to build, play and store waveforms. Obviously not a programmable solution, but has a nice GUI and gets you experimenting faster.