59

Python 有没有像 C# 这样的扩展方法?是否可以调用如下方法:

MyRandomMethod()

在现有类型上,例如int

myInt.MyRandomMethod()
4

6 回答 6

68

您可以在 Python 代码中定义的类对象上添加您喜欢的任何方法(AKA 猴子补丁):

>>> class A(object):
>>>     pass


>>> def stuff(self):
>>>     print self

>>> A.test = stuff
>>> A().test()

这不适用于内置类型,因为它们__dict__不可写(它是 a dictproxy)。

所以不,Python 中没有“真正的”扩展方法机制。

于 2009-02-05T00:59:31.207 回答
9

不确定这是否是您所要求的,但您可以扩展现有类型,然后在新事物上调用您喜欢的任何内容:

class  int(int):
     def random_method(self):
           return 4                     # guaranteed to be random
v = int(5)                              # you'll have to instantiate all you variables like this
v.random_method()

class int(int):
    def xkcd(self):
        import antigravity
        print(42)

>>>v.xkcd()
Traceback (most recent call last):
  File "<pyshell#81>", line 1, in <module>
    v.xkcd()
AttributeError: 'int' object has no attribute 'xkcd'
c = int(1)
>>> c.random_method()
4
>>> c.xkcd()
42

希望能澄清你的问题

于 2009-02-05T00:53:57.117 回答
8

可以用禁果来完成(https://pypi.python.org/pypi/forbiddenfruit

安装禁果:

pip install forbiddenfruit

然后你可以扩展内置类型:

>>> from forbiddenfruit import curse

>>> def percent(self, delta):
...     return self * (1 + delta / 100)

>>> curse(float, 'percent', percent)
>>> 1.0.percent(5)
1.05

Forbidden Fruit 从根本上依赖于 C API,它只适用于 cpython 实现,不适用于其他 python 实现,例如 Jython、pypy 等。

于 2018-05-07T09:28:32.073 回答
4

下面的上下文管理器添加了像禁果一样的方法,没有它的限制。除此之外,它还具有在之后删除扩展方法的额外好处:

class extension_method:

    def __init__(self, obj, method):
        method_name = method.__name__
        setattr(obj, method_name, method)
        self.obj = obj
        self.method_name = method_name

    def __enter__(self):
        return self.obj

    def __exit__(self, type, value, traceback):
        # remove this if you want to keep the extension method after context exit
        delattr(self.obj, self.method_name)

用法如下:

class C:
    pass

def get_class_name(self):
    return self.__class__.__name__

with extension_method(C, get_class_name):
    assert hasattr(C, 'get_class_name') # the method is added to C
    c = C()
    print(c.get_class_name()) # prints 'C'

assert not hasattr(C, 'get_class_name') # the method is gone from C
于 2019-11-04T09:34:59.757 回答
2

我对这里描述的方法很幸运:

http://mail.python.org/pipermail/python-dev/2008-January/076194.html

我不知道它是否适用于内置函数。

于 2009-02-05T17:59:17.217 回答
-1

另一种选择是覆盖元类。这使您可以指定所有类中应该存在的函数。

本文开始讨论它:

http://www.onlamp.com/pub/a/python/2003/04/17/metaclasses.html

于 2009-02-05T01:14:45.763 回答