Using "and" in return
The and
operator evaluates whether both of its arguments are tru-ish, but in a slightly surprising way: First it examines its left argument. If it is truish, then it returns its right argument. If the left argument is falsish, then it returns the left argument.
So the last line in your code:
return username and USER_RE.match(username)
is the same as:
if username:
return USER_RE.match(username)
else:
return username
Strings like username
are truish if they are not empty. The regex match
function returns a truish match object if the pattern matches, and returns None
, a falsish value, if it doesn't match.
The net result is that valid_username
will return a truish value if username is not an empty string, and the username matches the given pattern.
Note the "and" here has nothing to do with returning two values, it's computing one value.
When you use a logical operator, it continues according to the rules, so with and, it evaluates the truthiness of the first statement and if it isn't truthy, it returns a non-truthy value (in the first case, '').
print repr("" and "THIS IS POST AND")
""
print "" or "THIS IS POST AND"
THIS IS POST AND
print None or "Something else"
Something else
Where this comes in handy is when you don't want to call a non-existent method on something like None
(e.g. the length trait):
r = None
s = [1,2,3,4]
print r and len(r)
None
print s and len(s)
4
In the case you posted, the point is that you only want to check the username against the regular expression if the username is truthy.
It's important to note here that and
, and or
both short-circuit. So if you get something non-truthy, the function won't even evaluate the regular expression.