Lorsque je recherchais les collections
de python, il n'y avait presque pas d'article sur collections.UserList
, alors j'ai essayé de résumer comment l'utiliser.
collections.UserList
?Le Document officiel dit:
Cette classe agit comme un wrapper pour les objets de liste. Ceci est utile comme classe de base pour votre propre classe de type liste, où vous pouvez remplacer des méthodes existantes ou en ajouter de nouvelles. De cette façon, vous pouvez ajouter un nouveau comportement à la liste.
Comme mentionné ci-dessus, ʻUserList est la classe de base pour créer votre propre classe de type liste. Une classe de type liste est une classe qui peut créer ʻappend
et remove
, et a un indexeur.
collections.UserList
À titre d'exemple, implémentons une liste ResettableList
avec une méthode reset
qui renvoie la liste à son état initial au moment du constructeur.
python
from collections import UserList
# collections.Hériter de UserList
class ResettableList(UserList):
def __init__(self, initlist=None):
super().__init__(initlist)
self._initlist = initlist.copy() #Gardez une copie de la liste d'initiation
def reset(self):
self.data = self._initlist.copy() # self.data est la liste encapsulée
mylist = ResettableList([1, 2, 3]) #Passer la liste initiale au constructeur
print(f'mylist = {mylist}')
print(f'mylist.data = {mylist.data}') # [non recommandé]Vous pouvez accéder à la liste interne avec des données
#Vous pouvez fonctionner comme une liste normale
print(f'mylist[1] = {mylist[1]}')
mylist.append(4)
print(f'mylist = {mylist}')
mylist.remove(1)
print(f'mylist = {mylist}')
mylist.reset() #Revenir à l'état initial
print(f'mylist = {mylist}')
résultat
mylist = [1, 2, 3]
mylist.data = [1, 2, 3]
mylist[1] = 2
mylist = [1, 2, 3, 4]
mylist = [2, 3, 4]
mylist = [1, 2, 3]
ResettableList
est un wrapper et stocke la liste dans la variable membre data
. La méthode reset
, qui a son propre comportement, est implémentée en manipulant ce self.data
.
De plus, dans l'exemple, la variable membre «data» est accessible de l'extérieur, mais ce comportement doit être évité car il peut provoquer des problèmes inattendus.
Pour illustrer cela, nous avons implémenté une liste ʻUnremovableList` qui ne peut pas supprimer des éléments.
python
from collections import UserList
#Exception lorsqu'une méthode qui supprime un élément est utilisée
class RemoveError(Exception):
pass
class UnremovableList(UserList):
#Remplacer la méthode qui supprime l'élément et déclencher une exception
#Pour plus de simplicité, seule la suppression est remplacée ici
def remove(self, item):
raise RemoveError('Cannot remove')
mylist = UnremovableList([1, 2, 3])
print(f'mylist = {mylist}')
#Ne peut pas être supprimé
try:
mylist.remove(1)
except RemoveError as e:
print(f'RemoveError: {e}')
print(f'mylist = {mylist}')
# mylist.Je peux le supprimer lorsque j'accède aux données
mylist.data.remove(1)
print(f'mylist = {mylist}')
résultat
mylist = [1, 2, 3]
RemoveError: Cannot remove
mylist = [1, 2, 3]
mylist = [2, 3]
En accédant ainsi aux «données» de l'extérieur, vous pouvez supprimer les éléments qui auraient dû être interdits.
list
Si vous voulez créer une classe de type liste, vous devriez pouvoir hériter de list
. Y a-t-il un mérite d'hériter de collections.UserList
au lieu de list
?
Dans le Document officiel, il est écrit comme suit.
Le besoin de cette classe a été partiellement remplacé par la possibilité de sous-classer directement à partir de la liste; cependant, il est plus facile d'utiliser cette classe car elle vous donne accès à la liste sous-jacente en tant qu'attribut. Il y a aussi.
"Cette classe" est ʻUserList. En résumé, "Vous pouvez hériter de
liste, mais il est plus facile d'hériter de ʻUserList
."
Voyons à quoi ressemblerait l'implémentation si nous héritions de list
. Implémentez la ResettableList
de l'exemple précédent de cette façon.
python
class ResettableList(list):
def __init__(self, initlist=None):
super().__init__(initlist)
self._initlist = initlist.copy()
def reset(self):
self.clear()
self.extend(self._initlist)
Vous devez travailler avec votre propre instance, contrairement à ce que vous avez hérité de ʻUserList`. Par conséquent, je l'ai implémenté en vidant la liste une fois et en ajoutant la liste initiale.
Une comparaison des deux est la suivante. (Seule la méthode reset
est décrite)
python
#Version héritée de UserList
class ResettableList(UserList):
def reset(self):
self.data = self._initlist.copy()
#liste des versions héritées
class ResettableList(list):
def reset(self):
self.clear()
self.extend(self._initlist)
Il est plus simple d'hériter de ʻUserList`.
Jusqu'à présent, j'ai résumé comment utiliser collections.UserList
à ma manière.
ʻUserList` a une structure qui contient une liste, mais qui ressemble à la liste elle-même lorsqu'elle est vue de l'extérieur. Je pense que cela sera également utile lors de l'extension des classes communes.
A propos, collections
a aussi ʻUserDict et ʻUserString
, qui sont similaires à ʻUserList`. C'est une classe de base pour créer respectivement des classes de type "dict" et "str".
Je ne pense pas utiliser ces classes très souvent, mais j'aimerais les utiliser de manière appropriée dans ces situations.
Recommended Posts