2010-06-23 10 views
0

C'est plus une question de curiosité qu'autre chose. Je suis nouveau avec Python et je joue avec. Je viens de regarder le module base64. Et si au lieu de faire:Comment ajouter des capacités à des chaînes en Python

import base64 
string = 'Foo Bar' 
encoded = base664.b64encode 

que je voulais faire quelque chose comme:

>>> class b64string(): 
>>> <something> 
>>> 
>>> string = b64string('Foo Bar') 
>>> string 
'Foo Bar' 
>>> string.encode64() 
'Rm9vIEJhcg==' 
>>> string 
'Rm9vIEJhcg==' 
>>> string.assign('QmFyIEZvbw==') 
>>> string 
'QmFyIEZvbw==' 
>>> string.b64decode() 
'Bar Foo' 
>>> string 
'Bar Foo' 

est-il un moyen simple, pythonique pour créer cette classe?

J'ai commencé avec ceci:

>>> class b64string(base64): 
... def __init__(self, v): 
...  self.value=v 

Et déjà je reçois:

Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: Error when calling the metaclass bases 
    module.__init__() takes at most 2 arguments (3 given) 

et ne vous a commencé à me (juste pour voir ce qui se passerait) pas:

>>> class b64string(str, base64): pass 
... 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: Error when calling the metaclass bases 
    metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases 

Je sais comment le faire manuellement en listant tous les attributs de base64 dans une nouvelle classe et en les appelant avec la valeur stockée sous argu. ment. Mais y a-t-il une manière propre et pythonique de faire cela? Est-ce une mauvaise idée de le faire? L'idée serait, si nécessaire, de le faire avec beaucoup de ces modules et d'avoir des "super strings" qui auraient comme modules tout ce que je devrais faire avec eux. Est-ce mauvais? Est-ce un-pythonic? Si c'est pythonique, comment ça se fait?

+6

Un problème avec '' Foo Bar'.encode ("base64") '? – YOU

+0

Je ne suis pas encore assez sage dans la manière de Python de répondre à votre question principale, mais votre message d'erreur au moins est d'essayer de sous-classer 'base64', qui est un module et non une classe. – shambulator

Répondre

1

Je ne pense pas que la création de classes aussi complexes ressemble à une chaîne, mais si vous le souhaitez vraiment, voici un extrait simple qui exécute vos exemples.

D'abord, nous définissons une classe qui est un encapsuleur de chaînes générique. Son cœur est une fonction __getattr__ qui transmet chaque appel de méthode à un self.module donné, en ajoutant self.string comme premier paramètre et en mémorisant le résultat sur self.string.

import base64 

class ModuledString(object): 
    def __init__(self, string): 
     self.string = string 

    def __getattr__(self, attrname): 
     def func(*args, **kwargs): 
      result = getattr(self.module, attrname)(self.string, *args, **kwargs) 
      self.string = result 
      return result 
     return func 

    def __str__(self): 
     return str(self.string) 

Création d'une chaîne wrapper avec des capacités de base64 est alors facile:

class B64String(ModuledString): 
    module = base64 

if __name__ == '__main__': 
    string = B64String('Foo Bar') 
    print string 
    # 'Foo Bar' 
    print string.b64encode() 
    # 'Rm9vIEJhcg==' 
    print string 
    # 'Rm9vIEJhcg==' 
    string.string = 'QmFyIEZvbw==' 
    print string 
    # 'QmFyIEZvbw==' 
    print string.b64decode() 
    # 'Bar Foo' 

Notez que les exemples ci-dessus ne fonctionnent que parce b64encode et b64decode prennent une chaîne comme premier argument et renvoie une chaîne comme résultat (il n'y a pas de validation dans ma fonction __getattr__). Une fonction aléatoire d'un module aléatoire déclencherait probablement une sorte d'exception. Donc, après tout, il serait préférable de limiter l'utilisation à un ensemble prédéfini de fonctions d'un module donné, mais cela devrait être facile maintenant.

Je répète, je ne recommande pas d'utiliser un tel code dans un projet sérieux, seulement pour le plaisir.

+0

Merci! (Et désolé pour la réponse tardive.) Ceci est très utile, pas pour un code réel, bien sûr, pour comprendre comment fonctionne Python et comment il devrait être utilisé au mieux. J'aurais pensé qu'un emballage générique aurait été trop lourd, et il y aurait beaucoup d'autres choses que j'aurais envisagées sous un angle très différent. C'était juste la chose dont j'avais besoin. Brillant! – eje211

Questions connexes