You probably didn’t make a copy at all, but instead sorted the original and used the return value of that of which there is None. What you would need instead is a way of copying the list and then sorting that, or some different way of sorting which created a copy in the process.
The main reason for making a copy is so that the original remains unchanged, the caller may not want (or expect) the original to be altered (the purpose of your function is to compute median, not to sort, why would it do that?)
The cost of making that copy is low or outweighed by the sorting, in nearly all cases you can consider it free.
I don’t hugely object to using a variable by the same name as the function itself. But the variable isn’t needed at all, may as well return the result directly rather than assigning a variable to it first. Which ever way you do it, including yours, is fine, there are some arguments to be made for all these options.
Rather than sorting in both branches of the if-statement, sort before the if-statement, no need for that duplicated code.
A size-1 list isn’t a special case, no need to test for that. That’s three lines doing absolutely nothing.
Also note that the length of a list isn’t computed every time you call len(list), it’s a stored value that gets updated when the list adds/removes values. Creating your own variable might still be desirable to avoid the clutter of extra parentheses when calling it, or maybe if you want a slightly different name for it for whatever reason. It’s also slightly faster to use local variables, but that is insignificant here (not doing it millions of times)