开发者

How to override ord behaivour in Python for str childs?

开发者 https://www.devze.com 2022-12-14 01:01 出处:网络
I have this class: class STR(str): def __int__(self): return 42 If i use it in the promt like this: >>> a=STR(\'8\')

I have this class:

class STR(str):

    def __int__(self):
        return 42 

If i use it in the promt like this:

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

that's the behaivour. I'd like to ord(a) be 42. How can 开发者_如何学PythonI do it? Which method should I override in the str class? Is all this documented anywhere?

Thanks!


Here's the C source for Python's builtin ord from the current SVN revision of bltinmodule.c:

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;
}

As you can see, it doesn't make any method calls on the instance you pass in. As far as I can tell, if you don't pass it an explicit string, there's no way to override the functionality of ord.

In fact, it's essentially verifying that the PyObject is either a string, byte array, or Unicode -- that's what the PyString_Check, etc. functions do. If it's none of those, you get the TypeError exception.

One workaround that doesn't scale very well would be to write your own ord in the global namespace:

>>> 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

Of course, this scales horribly because another module using your class may be directly calling __builtins__.ord, or they might even be overwriting ord themselves! But, if you only need this to work on a single, standalone module, this is one way to go about it.


Somebody already posted the builtin ord code, and there is no method call you may intercept.

One solution could be override the ord function, for example:

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

Then you define your class with the __ord__ method and do something like:

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

For tests:

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

Outputs:

53
LOL


ord is not overloadable, it doesn't call any method on string objects (at least in CPython - Python/bltinmodule.c, builtin_ord function).

The best way is probably to create STR.ord method and call that instead of the built-in.


You can't override ord but you can overwrite as variable for example

backup original ord

origord= ord

def ord(x):
    return 42


ord(a)
42

origord(a)
56

But I think its not good a idea to overwrite it.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号