Python 是有名的动态类型语言,本身不支持函数重载。
class Foo:
def add(self, a):
pass
def add(self, a, b):
# 会覆盖上面已经定义类函数
pass
然而使用元编程 (meta-programming) 和 python 3.5+ 的 type hints,可以实现类函数重载。
然后写了一个库:pover - Python OVERload
pip3 install pover
使用一个 metaclass OverloadMeta
实现类函数重载。
#!/usr/bin/env python3
import unittest
import pover
class Foo(metaclass=pover.OverloadMeta):
def add(self, a: int):
return a + 1
def add(self, a: list):
return a + [1]
def add(self, a: set):
a.add(1)
return a
def minus(self, a: int):
return a - 1
def minus(self, a: str):
return a[:-1]
class OverloadTest(unittest.TestCase):
def test_overload(self):
foo = Foo()
self.assertEqual(foo.add(1), 2)
self.assertEqual(foo.add([0]), [0, 1])
self.assertEqual(foo.add({0}), {0, 1})
self.assertEqual(foo.minus(1), 0)
self.assertEqual(foo.minus("hello"), "hell")
具体实现原理在: https://github.com/idf/pover/blob/master/pover/core.py
GitHub 地址,请多指教: https://github.com/idf/pover
1
Kilerd 2018-12-14 16:26:59 +08:00
|
2
deepreader OP @Kilerd 了解过,`singledispatch` 没法 dispatch 类函数吧。singledispatch decorator renames module functions,这个机制并不使用类函数。
|
3
xpresslink 2018-12-14 16:35:43 +08:00
from functools import singledispatch
@singledispatch def add(a:object): pass @add.register(int) def _add(a: int): return a + 1 @add.register(list) def _add(a: list): return a + [1] @add.register(set) def _add(a: set): a.add(1); return a cases=[1, [0], {0}] for case in cases: print(add(case)) |
4
xpresslink 2018-12-14 16:39:50 +08:00
实现上由于 python 是动态语言,传递对象是鸭子类型又可以变长参数,所以用上方法重载的机会不太多。
java 那个有名的 23 种设计模式,大约有 16 种设计模式在动态语言里面根本就不需要了。 |
5
deepreader OP @xpresslink single dispatch 是不错,但是不适合类函数吧?见#2
|
6
xpresslink 2018-12-14 17:13:12 +08:00
@deepreader 当然可以用在类函数了。
|
7
ffffish 2018-12-14 17:32:25 +08:00
蛋总牛逼
|
8
deepreader OP @xpresslink show me the code.
Decorator invocation 是在类函数 invocation 时执行的的,类函数 definition 的时候同函数名已经在 class construction 被覆盖了。 |
9
deepreader OP @ffffish 哟
|
10
xpresslink 2018-12-15 11:11:56 +08:00
@deepreader 当然要静态方法调用啊,直接 类名.方法()
|