python内置类型的扩展方法

发布于 2021-01-29 19:35:15

是否可以将扩展方法添加到python内置类型中?我知道我可以通过简单地通过添加新方法来将扩展方法添加到定义的类型。如下:

class myClass:
    pass

myClass.myExtensionMethod = lambda self,x:x * 2
z = myClass()
print z.myExtensionMethod(10)

但是是将扩展方法添加到python内置类型(如列表,字典,…)的任何方法

list.myExtension = lambda self,x:x * 2
list.myExtension(10)
关注者
0
被浏览
102
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    可以使用以下非常聪明的模块在纯Python中完成此操作:

    https://pypi.python.org/pypi/forbiddenfruit

    例如:

    import functools
    import ctypes
    import __builtin__
    import operator
    
    class PyObject(ctypes.Structure):
        pass
    
    Py_ssize_t = hasattr(ctypes.pythonapi, 'Py_InitModule4_64') and ctypes.c_int64 or ctypes.c_int
    
    PyObject._fields_ = [
        ('ob_refcnt', Py_ssize_t),
        ('ob_type', ctypes.POINTER(PyObject)),
    ]
    
    class SlotsPointer(PyObject):
        _fields_ = [('dict', ctypes.POINTER(PyObject))]
    
    def proxy_builtin(klass):
        name = klass.__name__
        slots = getattr(klass, '__dict__', name)
    
        pointer = SlotsPointer.from_address(id(slots))
        namespace = {}
    
        ctypes.pythonapi.PyDict_SetItem(
            ctypes.py_object(namespace),
            ctypes.py_object(name),
            pointer.dict,
        )
    
        return namespace[name]
    
    def die(message, cls=Exception):
        """
            Raise an exception, allows you to use logical shortcut operators to test for object existence succinctly.
    
            User.by_name('username') or die('Failed to find user')
        """
        raise cls(message)
    
    def unguido(self, key):
        """
            Attempt to find methods which should really exist on the object instance.
        """
        return functools.partial((getattr(__builtin__, key, None) if hasattr(__builtin__, key) else getattr(operator, key, None)) or die(key, KeyError), self)
    
    class mapper(object):
        def __init__(self, iterator, key):
            self.iterator = iterator
            self.key = key
            self.fn = lambda o: getattr(o, key)
    
        def __getattribute__(self, key):
            if key in ('iterator', 'fn', 'key'): return object.__getattribute__(self, key)
            return mapper(self, key)
    
        def __call__(self, *args, **kwargs):
            self.fn = lambda o: (getattr(o, self.key, None) or unguido(o, self.key))(*args, **kwargs)
            return self
    
        def __iter__(self):
            for value in self.iterator:
                yield self.fn(value)
    
    class foreach(object):
        """
            Creates an output iterator which will apply any functions called on it to every element
            in the input iterator. A kind of chainable version of filter().
    
            E.g:
    
            foreach([1, 2, 3]).__add__(2).__str__().replace('3', 'a').upper()
    
            is equivalent to:
    
            (str(o + 2).replace('3', 'a').upper() for o in iterator)
    
            Obviously this is not 'Pythonic'.
        """
        def __init__(self, iterator):
            self.iterator = iterator
    
        def __getattribute__(self, key):
            if key in ('iterator',): return object.__getattribute__(self, key)
            return mapper(self.iterator, key)
    
        def __iter__(self):
            for value in self.iterator:
                yield value
    
    proxy_builtin(list)['foreach'] = property(foreach)
    
    import string
    
    print string.join([1, 2, 3].foreach.add(2).str().add(' cookies').upper(), ', ')
    
    >>> 3 COOKIES, 4 COOKIES, 5 COOKIES
    

    在那里,感觉不舒服吗?



知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看