You've misunderstood how backreferences work. For a backreference to match anything, the original reference must have matched too.
In your second example, the (?P<f>first) group didn't match anything, so the (?P=f) back reference cannot match anything either.
Back references are the wrong tool here; you'll have to repeat at least one of your groups, literally:
r'(?:(?P<f>first )?(?P<s>second)(?(f)| first))'
would use a conditional pattern that only matches first after second if there was no f match before second:
>>> import re
>>> pattern = re.compile(r'(?:(?P<f>first )?(?P<s>second)(?(f)$| first))')
>>> pattern.match('first second').group()
'first second'
>>> pattern.match('second first').group()
'second first'