2009-12-12 10 views
2

J'ai cette classe:Comment substituer ord behaivour en Python pour str childs?

class STR(str): 

    def __int__(self): 
     return 42 

Si je l'utilise dans le PROMT comme ceci:

>>> a=STR('8') 
>>> ord(a) 
56 
>>> int(a) 
42 
>>> chr(a) 
'*' 

qui est le behaivour. Je voudrais ord (a) avoir 42 ans. Comment puis-je le faire? Quelle méthode devrais-je remplacer dans la classe str? Est-ce que tout ceci est documenté n'importe où?

Merci!

Répondre

3

est ici la source de C pour builtin de Python ord du current SVN revision of bltinmodule.c. En ce qui concerne

static PyObject * 
builtin_ord(PyObject *self, PyObject* obj) 
{ 
    long ord; 
    Py_ssize_t size; 

    if (PyString_Check(obj)) { 
     size = PyString_GET_SIZE(obj); 
     if (size == 1) { 
      ord = (long)((unsigned char)*PyString_AS_STRING(obj)); 
      return PyInt_FromLong(ord); 
     } 
    } else if (PyByteArray_Check(obj)) { 
     size = PyByteArray_GET_SIZE(obj); 
     if (size == 1) { 
      ord = (long)((unsigned char)*PyByteArray_AS_STRING(obj)); 
      return PyInt_FromLong(ord); 
     } 

#ifdef Py_USING_UNICODE 
    } else if (PyUnicode_Check(obj)) { 
     size = PyUnicode_GET_SIZE(obj); 
     if (size == 1) { 
      ord = (long)*PyUnicode_AS_UNICODE(obj); 
      return PyInt_FromLong(ord); 
     } 
#endif 
    } else { 
     PyErr_Format(PyExc_TypeError, 
       "ord() expected string of length 1, but " \ 
       "%.200s found", obj->ob_type->tp_name); 
     return NULL; 
    } 

    PyErr_Format(PyExc_TypeError, 
      "ord() expected a character, " 
      "but string of length %zd found", 
      size); 
    return NULL; 
} 

Comme vous pouvez le voir, il ne fait pas de méthode fait appel à l'instance que vous passez que je peux dire, Si vous ne lui passez pas une chaîne explicite, il n'y a aucun moyen de remplacer la fonctionnalité de ord. En fait, il vérifie essentiellement que PyObject est soit une chaîne, un tableau d'octets, soit un Unicode - c'est ce que font les fonctions PyString_Check, etc. Si ce n'est pas le cas, vous obtenez l'exception TypeError.

Une solution qui ne serait pas à l'échelle très bien d'écrire votre propre ord dans l'espace de noms global:

>>> class STR(str): 
...  def __int__(self): 
...    return 42 
... 
>>> 
>>> def ord(s): 
...  if isinstance(s, STR): 
...    return int(s) 
...  else: 
...    return __builtins__.ord(s) 
... 
>>> 
>>> ord(STR('fdsafds')) 
42 
>>> ord("!") 
33 

Bien sûr, cette échelles horriblement parce qu'un autre module en utilisant votre classe peut être appeler directement __builtins__.ord, ou ils pourraient même écraser ord eux-mêmes! Mais, si vous avez seulement besoin de cela pour travailler sur un seul module autonome, c'est une façon de s'y prendre.

+0

J'aime cette réponse. Quel est le problème d'échelle? Je ne peux pas le voir très bien. –

0

ord n'est pas surchargeable, il n'appelle aucune méthode sur les objets string (au moins dans la fonction CPython - Python/bltinmodule.c, builtin_ord).

Le meilleur moyen est probablement de créer la méthode STR.ord et de l'appeler à la place du built-in.

0

Vous ne pouvez pas remplacer ord mais vous pouvez remplacer comme variables par exemple

originale sauvegarde ord

origord= ord 

def ord(x): 
    return 42 


ord(a) 
42 

origord(a) 
56 

Mais je pense que ce ne est pas bonne idée de le remplacer.

+0

mmmmmm cela m'a donné une idée. –

+0

: D mais vous savez, cela va vous confondre et d'autres personnes qui liront ces codes plus tard. – YOU

2

Quelqu'un a déjà publié le code ordin intégré et aucun appel de méthode ne peut être intercepté.

Une solution pourrait être remplacer la fonction ord, par exemple:

backup_ord = ord 
def ord(obj): 
    if hasattr(obj, '__ord__'): 
     return obj.__ord__() 
    else: 
     return backup_ord(obj) 

Ensuite, vous définissez votre classe avec la méthode __ord__ et faire quelque chose comme:

class MyStr(str): 
    def __ord__(self): 
     return 'LOL' 

Pour les tests:

normal_five = '5' 
strange_five = MyStr('5') 
print ord(normal_five) 
print ord(strange_five) 

Sorties:

53 
LOL