The pipe introduces a subshell in which variable changes are masked from the parent; this is similar to `while` loops involving pipes where variable changes inside that loop do not affect the parent. The PID change can be observed with the `zsh/system` module:
zmodload zsh/system
local testa=("a")
local testb=("b")
function test {
testb=(${(P)1})
echo "INSIDE testb=$testb $sysparams[pid]"
}
test "testa" | cat
echo "OUTSIDE testb=$testb $sysparams[pid]"
Which should show something like
% zsh foo.zsh
INSIDE testb=a 61488
OUTSIDE testb=b 61487
%
different subshell, different variables.