Script variable can be referenced in Start but not in update.

Hello, I have a two part question.
First, I can print a gameObjects speed fine in the method where it was initialized, but when I follow the exact same process inside update it prints 0. Why would this be?

Secondly I was told that it’s a bad idea to be calling getObjects() for the stats script every frame because it was an expensive operation and that I should instead look into making a global variable for the scripts. The problem I have with this is that I sort the gameobjects by speed every single turn, so the scripts location might not be easy to access. I thought about storing the script with the gameObject in a “pair” but I don’t think that that is the right solution either.

public PlayerStats playerStats;
List<GameObject> players = new List<GameObject>();

void Start()
		//create players
		GameObject player1 = GameObject.CreatePrimitive(PrimitiveType.Capsule);
		player1.transform.position = new Vector3(4,1,0);
		PlayerStats player1Stats = player1.AddComponent<PlayerStats>();
		player1.tag = "Player";
		player1Stats.setSpeed (15.0f);
                //This line prints 15, as expected
		GameObject player2 = GameObject.CreatePrimitive(PrimitiveType.Capsule);
		player2.transform.position = new Vector3(0,1,4);
		PlayerStats player2Stats = player2.AddComponent<PlayerStats>();
		player2.tag = "Player";
		player2Stats.setSpeed (10.0f);
                //this line prints 10, as expected
		PlayerStats ps;
		ps = players[0].GetComponent<PlayerStats>();
                //this line prints 15, as expected

	// Update is called once per frame
	void Update () {		
		int playerSize = players.Count;
		int index = 0;
		PlayerStats ps;
		while(index < playerSize)
			ps = players[index].GetComponent<PlayerStats>();
                        //this line ALWAYS prints 0, when it should print either 10 or                  

Is playerstats initializing itself or doing any logic of its own?