"But according to this logic, neither ps not less should appear in the output of ps."
Yes, so your logic is wrong, because they both appear. When you run a command in a Un*x shell, very few (if any) actually run in the shell. A separate process is forked to run that command.
When you pipe two commands together, both commands are launched in separate processes and stdout of the first linked to stdin of the second.
So, very shortly after you execute ps|less, you have three processes: one running your shell, one running ps, and one running less. As the output is generated by ps, it will be worked on in parallel (timesliced as needed) by less. Both commands run in parallel, not sequentially, with minimal buffering.
As ps works its way through the process list, it finds and displays both itself and less, and the parent shell too, and the parent's parent, and so on up to init. And everything else on the system. That is why your output includes both ps and less.