gpt4 book ai didi

Python函数重载

转载 作者:IT老高 更新时间:2023-10-28 12:22:44 26 4
gpt4 key购买 nike

我知道 Python 不支持方法重载,但我遇到了一个问题,我似乎无法以一种好的 Python 方式解决。

我正在制作一个角色需要发射各种子弹的游戏,但我如何编写不同的函数来创建这些子弹?例如,假设我有一个函数可以创建一个以给定速度从 A 点行进到 B 点的子弹。我会写一个这样的函数:

def add_bullet(sprite, start, headto, speed):
# Code ...

但我想编写其他函数来创建项目符号,例如:

def add_bullet(sprite, start, direction, speed):
def add_bullet(sprite, start, headto, spead, acceleration):
def add_bullet(sprite, script): # For bullets that are controlled by a script
def add_bullet(sprite, curve, speed): # for bullets with curved paths
# And so on ...

等等,有很多变化。有没有更好的方法可以在不使用这么多关键字参数的情况下做到这一点,导致它变得有点难看。重命名每个函数也很糟糕,因为您会得到 add_bullet1add_bullet2add_bullet_with_really_long_name

解决一些问题:

  1. 不,我不能创建 Bullet 类层次结构,因为那太慢了。管理子弹的实际代码是 C 语言,我的函数是 C API 的包装器。

  2. 我知道关键字参数,但检查各种参数组合变得很烦人,但默认参数有助于分配像 acceleration=0

最佳答案

您所要求的称为多次调度。见 Julia演示不同类型调度的语言示例。

但是,在讨论之前,我们将首先解决为什么 重载 在 Python 中并不是您真正想要的。

为什么不重载?

首先,需要了解重载的概念以及为什么它不适用于 Python。

When working with languages that can discriminate data types atcompile-time, selecting among the alternatives can occur atcompile-time. The act of creating such alternative functions forcompile-time selection is usually referred to as overloading afunction. (Wikipedia)

Python 是 dynamically类型语言,因此重载的概念根本不适用于它。然而,一切都没有丢失,因为我们可以在运行时创建这样的替代函数:

In programming languages that defer data type identification untilrun-time the selection among alternativefunctions must occur at run-time, based on the dynamically determinedtypes of function arguments. Functions whose alternativeimplementations are selected in this manner are referred to mostgenerally as multimethods. (Wikipedia)

所以我们应该能够在 Python 中执行 multimethods,或者,也可以称为:multiple dispatch

多次调度

多重方法也称为多重调度:

Multiple dispatch or multimethods is the feature of someobject-oriented programming languages in which a function or methodcan be dynamically dispatched based on the run time (dynamic) type ofmore than one of its arguments. (Wikipedia)

Python 不支持此功能1,但碰巧有一个出色的 Python 包,名为 multipledispatch正是这样做的。

解决方案

我们可以这样使用 multipledispatch 2 包来实现你的方法:

>>> from multipledispatch import dispatch
>>> from collections import namedtuple
>>> from types import * # we can test for lambda type, e.g.:
>>> type(lambda a: 1) == LambdaType
True

>>> Sprite = namedtuple('Sprite', ['name'])
>>> Point = namedtuple('Point', ['x', 'y'])
>>> Curve = namedtuple('Curve', ['x', 'y', 'z'])
>>> Vector = namedtuple('Vector', ['x','y','z'])

>>> @dispatch(Sprite, Point, Vector, int)
... def add_bullet(sprite, start, direction, speed):
... print("Called Version 1")
...
>>> @dispatch(Sprite, Point, Point, int, float)
... def add_bullet(sprite, start, headto, speed, acceleration):
... print("Called version 2")
...
>>> @dispatch(Sprite, LambdaType)
... def add_bullet(sprite, script):
... print("Called version 3")
...
>>> @dispatch(Sprite, Curve, int)
... def add_bullet(sprite, curve, speed):
... print("Called version 4")
...

>>> sprite = Sprite('Turtle')
>>> start = Point(1,2)
>>> direction = Vector(1,1,1)
>>> speed = 100 #km/h
>>> acceleration = 5.0 #m/s**2
>>> script = lambda sprite: sprite.x * 2
>>> curve = Curve(3, 1, 4)
>>> headto = Point(100, 100) # somewhere far away

>>> add_bullet(sprite, start, direction, speed)
Called Version 1

>>> add_bullet(sprite, start, headto, speed, acceleration)
Called version 2

>>> add_bullet(sprite, script)
Called version 3

>>> add_bullet(sprite, curve, speed)
Called version 4

<子>1。 Python 3 当前支持 single dispatch <子> 2。注意不要使用multipledispatch在多线程环境中,否则你会得到奇怪的行为。

关于Python函数重载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6434482/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com