Comment savez-vous si vous tenez une vue ou une copie ?

Questions d’entrevue Python et Pandas

Seniorpandas

Ce que les deux mots veulent dire

Une vue est une fenêtre sur le même bloc mémoire. Modifier la vue modifie l’original. Une copie a son propre bloc : les deux objets divergent dès la première écriture.

En NumPy, a[1:4] est en général une vue, et a[[0, 2, 5]] une copie. En Pandas, la même syntaxe n’a jamais eu ce contrat. Une sélection de colonnes contiguës pouvait renvoyer une vue ; un masque booléen, une copie ; un ordre de colonnes différent, encore autre chose. D’où SettingWithCopyWarning : l’outil refuse de garantir le résultat.

Comment vous tranchez en pratique

Vous ne « détectez » pas la vue pour ensuite parier. Vous décidez l’intention.

  • Vous voulez muter l’original. Une seule affectation : df.loc[masque, colonnes] = valeurs. Pas de variable intermédiaire, pas de chaîne de crochets.
  • Vous voulez un objet indépendant. .copy() tout de suite, puis vous travaillez sur la copie. Le coût mémoire est le prix de la clarté.
  • Vous ne mutuez rien. Vous enchaînez des méthodes qui renvoient un nouvel objet (assign, query, filtres réassignés à df). Plus de question vue contre copie.
python
extrait = df.loc[df["pays"] == "CA", ["client_id", "montant"]].copy()
extrait["montant"] = extrait["montant"].clip(lower=0)

Sans .copy(), « ça marche sur ma machine » n’est pas une spécification.

df.values / to_numpy() : le tableau sous-jacent peut être une vue. Écrire df.to_numpy()[:, 0] = 0 peut corrompre df, ou non. Pour un tableau que vous allez modifier, to_numpy(copy=True).

Copy-on-write : ce qui a changé

Pandas 2 permettait d’activer le copy-on-write ; les versions 3 en font le comportement par défaut. Les méthodes se comportent comme si elles renvoyaient une copie, et la mémoire n’est dupliquée qu’à la première écriture. L’intention devient : tout est isolé, sauf si vous écrivez via loc sur l’objet que vous avez choisi de modifier.

En entretien senior, vous ne racontez pas l’historique pour briller. Vous dites : l’ambiguïté historique justifie une disciplineloc pour muter, .copy() pour isoler — et CoW aligne enfin le runtime sur cette discipline.

La relance

« Comment vérifier qu’on partage la mémoire ? »

np.shares_memory(a.to_numpy(), b.to_numpy()) donne un indice, pas une preuve métier : le bloc des valeurs peut être partagé alors que l’index est copié, ou l’inverse. Ne construisez pas un nettoyage sur ce test. Construisez-le sur une intention écrite dans le code.

Toutes les questions Python et Pandas