Python 3 用元编程和 typehints 实现类函数重载 - Pover

2018-12-14 15:25:32 +08:00
 deepreader

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

1527 次点击
所在节点    Python
10 条回复
Kilerd
2018-12-14 16:26:59 +08:00
deepreader
2018-12-14 16:33:14 +08:00
@Kilerd 了解过,`singledispatch` 没法 dispatch 类函数吧。singledispatch decorator renames module functions,这个机制并不使用类函数。
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))
xpresslink
2018-12-14 16:39:50 +08:00
实现上由于 python 是动态语言,传递对象是鸭子类型又可以变长参数,所以用上方法重载的机会不太多。
java 那个有名的 23 种设计模式,大约有 16 种设计模式在动态语言里面根本就不需要了。
deepreader
2018-12-14 16:54:04 +08:00
@xpresslink single dispatch 是不错,但是不适合类函数吧?见#2
xpresslink
2018-12-14 17:13:12 +08:00
@deepreader 当然可以用在类函数了。
ffffish
2018-12-14 17:32:25 +08:00
蛋总牛逼
deepreader
2018-12-15 01:03:31 +08:00
@xpresslink show me the code.

Decorator invocation 是在类函数 invocation 时执行的的,类函数 definition 的时候同函数名已经在 class construction 被覆盖了。
deepreader
2018-12-15 01:04:24 +08:00
@ffffish
xpresslink
2018-12-15 11:11:56 +08:00
@deepreader 当然要静态方法调用啊,直接 类名.方法()

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/517580

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX