Turns out nditer actually can do what I wanted in a more elegant way (which also avoids crazy indexing):-
nvalues = -np.arange(-50, 50, 10)
pvalues = np.arange(-50, 50, 10)
for x in np.nditer(pvalues): # top
square.append(PVector(x, -50))
for y in np.nditer(pvalues): # right side
square.append(PVector(50, y))
for x in np.nditer(nvalues): # bottom
square.append(PVector(x, 50))
for y in np.nditer(nvalues): # left side
square.append(PVector(-50, y))
But unfortunately I cannot use py5.vertices as suggested, however that might be a consideration when creating a vector class (for my ruby processing Vec2D and Vec3D classes I have created to vertex methods for PShape and and custom renderer).