J'ai créé une classe de cordes mutable en Python, basée sur la classe intégrée Je peux changer le premier caractère, mais lorsque j'appelle str code> STR. capitaliser () Code> , il utilise la valeur ancienne à la place p>
hello world
Cello world
3 Réponses :
Votre implémentation hérite de De plus, les types intégrés Python Ne rangez pas leur état dans un Vous devrez ombrager toutes les méthodes qui peut être beaucoup de travail, des méthodes d'écriture Comme ceux-ci pour chaque méthode possible démo avec le un côté REMARQUE: le également, prenez en compte la plupart des API Python codées dans C et prennent une valeur str code>, de sorte qu'il apporte toutes les méthodes str code>. Cependant, la mise en œuvre de la méthode str.capitalize () code> n'est pas conçue pour le prendre en compte. Méthodes telles que str.capitalize () code> renvoyer un nouvel em> STR code> objet avec le changement requis appliqué. __ dict __ dict __ code> cartographie des attributs, mais utilisez interne structure code> structures de données ) uniquement accessible sur le niveau C; Votre attribut auto-self.string code> n'est pas l'endroit où le (équivalent C de) str .__ nouveau __ () code> stocke les données de chaîne. Le str.capitalize () code> La méthode basse sa valeur de retour sur la valeur stockée dans la structure de données interne lorsque l'instance a été créée, qui ne peut pas être modifiée à partir du code Python. P> str cod> qui renvoient une nouvelle valeur, y compris str.capitalize () code> pour se comporter différemment. Si vous souhaitez que ces méthodes de renvoient une nouvelle instance pour modifier la valeur en place, vous devez le faire vous-même: p> str code> qui renvoie une valeur mise à jour. Au lieu de cela, vous pouvez utiliser un __ getattribute __ code> crochet à des méthodes de redirection: p> __ getattribute __ code> méthode ci-dessus ajoutée à votre Classe: p> __ RECR __ code> doit utiliser REC () code> pour renvoyer une représentation appropriée, non juste la valeur: p> str code> comme entrée, sont probables. Pour utiliser le API C pour Strings Unicode et ainsi Non seulement ignorer complètement vos implémentations personnalisées, mais comme l'original str.capitalize () code> Ignorera également l'attribut auto-self.string code>. Au lieu de cela, ils interagiront également avec les données internes str code>. P> p>
Compte tenu de tout cela, y a-t-il des avantages gagnés par cette classe héritante de str code>?
@Khelwood: Ça va tester comme une chaîne n'importe où isinstance (objet, str) code> est utilisé. Étant donné qu'il n'y a pas de type collections.abc code> que vous pouvez utiliser à la place, c'est une raison décente de continuer à le faire.
Cela ne sera-t-il pas plutôt trompeur?
@khelwood: Cela dépend de ce que la puissance espère utiliser cette classe.
@khelwood: Et en programmation, il n'y a pas de «trompeur», c'est ce que l'héritage est tout à propos de! Étendre et modifier le comportement mais être toujours compatible avec l'interface de la classe mère.
"Compatible" dans le sens d'avoir un tas de méthodes qui ressemblent aux méthodes que vous attendez, mais faites quelque chose de très différent ...
Y a-t-il un moyen d'obtenir toutes les méthodes de str code>? De cette façon, je peux en faire la boucle et les redéfinir à l'aide d'une lambda ou autre chose
@khelwood: oui, alors? C'est comme ça que beaucoup d'objets fonctionnent. Liste code>, tuple code>, octets code> et str code> sont toutes des séquences, de même que de nombreuses méthodes communes. Cependant, leurs implémentations sont très différentes pour tout ce que les noms de méthode et les signatures sont les mêmes.
@Michaelfish: utilisez vars (str) code> pour obtenir un dictionnaire de tous les attributs que le type définit. Les méthodes ne sont que des attributs qui se produisent sont appelables (et d'habitude, mettre en œuvre le protocole descripteur). Prendre en compte il y a au moins une méthode statique sur le type, str.maketrans () code>.
@Michaelfish: Il existe également des méthodes qui renvoient autre chose qu'un str code>, tel que des tests qui renvoient un booléen ( __ contient __ () code>, ispper () code >, isdigit () code>, startswith () code>, etc.) ou renvoyer une liste ou un tuple ( divisé () code>, partition () code>, rsplit () code>, rPartition () code>, etc.). Il n'y a pas d'approche à une taille unique - toutes les approches ici, je crains.
Je suppose que votre "qui dépend de ce que la puissance espère utiliser cette classe pour" couvre ce motif, mais mon objection est que si j'ai une fonction qui accepte une chaîne comme argument (et je confirme qu'il s'agit d'un str code> avec isinstance code>), alors je m'attends à pouvoir appeler y = x.capitaliser () code> etc. et obtenir les résultats prescrits par l'habituel < code> str code> méthodes. Avoir quelque chose déguisé en tant que STR CODE> comportant un comportement totalement différent semble être un excellent moyen d'introduire des comportements étranges et de déranger les bugs dans votre programme.
Et si l'utilisation prévue de l'OP est pas i> incluent la transmission de leurs chaînes mutables dans des fonctions qui attendent des chaînes normales, alors pourquoi devrait-il être souhaitable d'avoir isinstance (objet, str) code> retourner vrai?
@khelwood: Concaténation avec d'autres STR code> Les valeurs où string () code> est la valeur de droite. Pour a + b code>, où b code> est une sous-classe de type (a) code>, b .__ radd __ () code> est appelé avant a .__ ajouter __ () code> a>. Ceci est spécifiquement afin que vous puissiez remplacer de telles surcharges de l'opérateur dans une sous-classe.
vous hérité hériter d'un type intégré comme celui-ci nécessite efficacement de réimplément chaque méthode em> ou de faire des métaprogramming avec str code> de code> Capitalize code>, qui ignore les comportements de votre classe et utilise simplement les données sous-jacentes du "vrai" str code> . p>
__ getattribute __ code>; Sinon, les comportements de type sous-jacent seront hérités non modifiés. P>
Cette approche est inférieure aux réponses déjà suggérées. Il y a plus de frais généraux car vous ne pouvez pas simplement suivre les choses comme une liste, et Une autre façon d'accomplir cela est de Sous-classe , puis vous obtiendrez isinstance (s, str) code> ne fonctionnera pas, par exemple. Collections.Userstring Code> . C'est une enveloppe autour du type de chaîne intégré qui le stocke en tant que membre nommé données code>. Donc, vous pouvez faire quelque chose comme p> capitaliser code> et les autres méthodes de chaîne gratuites. P> P>