python - 如何将一个方法定义为实例方法和类方法(共享相同名称),每个方法都有不同的参数?
问题描述
从本质上讲,我正在尝试完成以下操作,但在 wherebar
和baz
具有相同的句柄(例如 just bar
)而不是两个不同命名的函数。
定义
import numpy as np
foo = np.add # For example; real function will be different in every instance
class MyClass(object):
def __init__(self, arg1, arg2):
self.arg1 = arg1
self.arg2 = arg2
def bar(self):
return foo(self.arg1, self.arg2)
@classmethod
def baz(cls, arg1, arg2):
return foo(arg1, arg2)
示例用法
a, b = 1, 2
mine = MyClass(a, b)
print(mine.bar())
>>> 3
x, y = 3, 4
print(MyClass.baz(x, y))
>>> 7
为了便于理解,我正在尝试这样做。_
真正的函数名称很长,带有许多下划线,并且为我想要执行的每个函数创建两个名称略有不同的函数(例如,在一个函数名称前加上 a )只会混淆已经很复杂的情况。
该函数将主要在内部使用,但我希望能够在静态上下文中使用可能不一定与给定对象的实例变量匹配的临时参数调用该函数MyClass
(事实上,我只会称它为如果他们不匹配的方式)。我使用@classmethod
而不是@staticmethod
因为真正的函数使用一些内部类变量。
我已经尝试简单地bar
为两个函数名称实现上述内容,但正如预期的那样,实例方法已被类方法覆盖。
我想一个尴尬的解决方案是定义
bar
为:def bar(self, arg1=None, arg2=None): if arg1 is None: arg1 = self.arg1 if arg2 is None: arg2 = self.arg2 return foo(arg1, arg2)
然后,如果我想在其他地方静态调用它,我需要使用:
# Assuming that a specific object of MyClass does not exist yet useless = "not", "used" mine = MyClass(*useless) x, y = 6, 9 print(mine.bar(x, y))
我不太喜欢这样,因为它需要我
bar
从MyClass
. 如果我已经有某个地方的实例,这在技术上不是问题MyClass
,但我想要一个类方法是有原因的:bar
在这种情况下,它不依赖于任何实例变量(尽管它依赖于类变量)。另一个可能的解决方案是为这个函数(和其他函数)创建一个单独的类:
class Functions(object): @classmethod def bar(cls, arg1, arg2): return foo(arg1, arg2)
并在内部和外部
MyClass
称为Functions.bar(self.arg1, self.arg2)
Functions.bar(arg1, arg2)
我也不是很热衷于此,因为我将
bar
类似的功能放入其中MyClass
是有原因的:它们在MyClass
概念上是相关的。
我看到了一些使用描述符的类似 SO 帖子的答案,但我希望可能有一个更优雅的解决方案。
这里有任何明智的 Python 向导有建议吗?
解决方案
您也可以 letself
采用默认参数,以便区分mine.bar()
和MyClass.bar()
。代价是其他两个参数必须是关键字参数。
class MyClass:
_sentinel = object()
def bar(self=None, *, arg1=_sentinel, arg2=_sentinel):
if self is not None:
if arg1 is _sentinel:
arg1 = self.arg1
if arg2 is _sentinel:
arg2 = self.arg2
else:
if arg1 is _sentinel:
raise ValueError("Missing required arg1")
if arg2 is _sentinel:
raise ValueError("Missing required arg2")
return foo(arg1, arg2)
mine.bar() # self is mine, arg1 is _sentinel, arg2 is _sentinel
MyClass.bar(arg1=3, arg2=4)
推荐阅读
- flutter - 如何更改文本和瓷砖之间的距离
- javascript - 在 mongoose 模式中更改 date.now 以显示这种格式的日期“MMMM Do YYYY”
- amazon-web-services - 使用启动模板时,如何使用该 Spot 队列独有的 AWS boto3“request_spot_fleet”设置标签?
- c# - iText7 - 无法设置 SquareAnnotation 内部颜色的不透明度
- traveling-salesman - 多参数任务分配的最佳算法
- reactivesearch - Reactivesearch, ReactiveList - 添加页面大小选择器
- django - 在 Django 模板中设置变量的自定义标签。将值从上下文中清空?
- ssl - 我的一个 haproxy 后端返回“没有服务器可用于处理此请求”
- sharepoint - 无法删除 SharePoint 库中既未签出也未打开进行编辑的文档?
- c# - ADOMD 与 SSAS 的连接