- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我想做这样的事情:
class X:
@classmethod
def id(cls):
return cls.__name__
def id(self):
return self.__class__.__name__
现在为类或其实例调用 id()
:
>>> X.id()
'X'
>>> X().id()
'X'
显然,这个确切的代码不起作用,但是否有类似的方法让它起作用?
或者在没有太多“hacky”东西的情况下获得这种行为的任何其他解决方法?
最佳答案
类和实例方法存在于同一个命名空间中,你不能重复使用这样的名称; id
的最后一个定义在这种情况下会赢。
类方法将继续在实例上工作,但是,不需要创建一个单独的实例方法;只需使用:
class X:
@classmethod
def id(cls):
return cls.__name__
因为方法继续绑定(bind)到类:
>>> class X:
... @classmethod
... def id(cls):
... return cls.__name__
...
>>> X.id()
'X'
>>> X().id()
'X'
这是明确记录的:
It can be called either on the class (such as
C.f()
) or on an instance (such asC().f()
). The instance is ignored except for its class.
如果您需要一种方法根据其使用位置不同来工作;在类上访问时绑定(bind)到类,在实例上访问时绑定(bind)到实例,您需要创建一个自定义的描述符对象。
descriptor API是 Python 如何将函数绑定(bind)为方法,并绑定(bind) classmethod
类的对象;查看descriptor howto .
您可以通过创建一个具有 __get__
的对象来为方法提供您自己的描述符方法。这是一个简单的方法,如果第一个参数为 __get__
,则根据上下文切换方法绑定(bind)的内容。是None
,则描述符被绑定(bind)到一个类,否则它被绑定(bind)到一个实例:
class class_or_instancemethod(classmethod):
def __get__(self, instance, type_):
descr_get = super().__get__ if instance is None else self.__func__.__get__
return descr_get(instance, type_)
这重新使用了 classmethod
并且只重新定义它如何处理绑定(bind),将原始实现委托(delegate)给 instance is None
, 和标准函数 __get__
否则实现。
请注意,在方法本身中,您可能需要测试它绑定(bind)的内容。 isinstance(firstargument, type)
是一个很好的测试:
>>> class X:
... @class_or_instancemethod
... def foo(self_or_cls):
... if isinstance(self_or_cls, type):
... return f"bound to the class, {self_or_cls}"
... else:
... return f"bound to the instance, {self_or_cls"
...
>>> X.foo()
"bound to the class, <class '__main__.X'>"
>>> X().foo()
'bound to the instance, <__main__.X object at 0x10ac7d580>'
另一种实现可以使用两个函数,一个用于绑定(bind)到一个类,另一个用于绑定(bind)到一个实例:
class hybridmethod:
def __init__(self, fclass, finstance=None, doc=None):
self.fclass = fclass
self.finstance = finstance
self.__doc__ = doc or fclass.__doc__
# support use on abstract base classes
self.__isabstractmethod__ = bool(
getattr(fclass, '__isabstractmethod__', False)
)
def classmethod(self, fclass):
return type(self)(fclass, self.finstance, None)
def instancemethod(self, finstance):
return type(self)(self.fclass, finstance, self.__doc__)
def __get__(self, instance, cls):
if instance is None or self.finstance is None:
# either bound to the class, or no instance method available
return self.fclass.__get__(cls, None)
return self.finstance.__get__(instance, cls)
这是一个带有可选实例方法的类方法。像使用 property
一样使用它目的;用 @<name>.instancemethod
装饰实例方法:
>>> class X:
... @hybridmethod
... def bar(cls):
... return f"bound to the class, {cls}"
... @bar.instancemethod
... def bar(self):
... return f"bound to the instance, {self}"
...
>>> X.bar()
"bound to the class, <class '__main__.X'>"
>>> X().bar()
'bound to the instance, <__main__.X object at 0x10a010f70>'
就我个人而言,我的建议是谨慎使用它;基于上下文改变行为的完全相同的方法使用起来可能会造成混淆。但是,有一些用例,例如 SQLAlchemy 对 SQL 对象和 SQL 值的区分,其中模型中的列对象会像这样切换行为;查看他们的 Hybrid Attributes documentation .此实现遵循与我的 hybridmethod
完全相同的模式。上面的类。
关于python - classmethod 和 instancemethod 同名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28237955/
我有两个文件: x.py class BF(object) def __init__(): . . def add(self,z): . . y.py from y
我正在尝试通过类变量调用外部函数。以下是我的真实代码的简化: def func(arg): print(arg) class MyClass(object): func_ref = N
我试图在另一个实例方法的事件处理程序中调用实例方法,但我得到函数未定义,我认为这是因为在事件处理程序中“this”指的是 DOM 元素而不是实例: function MyObject(somethin
html 中的多个复选框,如果选择了 None,我希望我的用户重定向到同一页面。 我应该通过 Javascript 执行此操作吗?或者 if request.method == 'POST':
我不断收到此错误: TypeError: 'instancemethod' object has no attribute '__getitem__' 根据我对 django 网站的特殊看法,我正在玩
我遇到了pickle的问题,代码是: import cPickle class A(object): def __init__(self): self.a = 1 de
我正在尝试创建一个 python 类来使用我的 Raspberry Pi 控制步进电机。它主要有效,但是每当我将列表定义为类变量时,我都会收到“'instancemethod' object has
我正在向 sequelize 模型添加一个实例方法。根据the documentation我应该能够引用 this.name,但我能看到的唯一值是 this.dataValues.name。我没有理由
我爱ActiveSupport::Concern . 它使向您的类添加功能变得容易,而且语法很好。 无论如何,在 Rails 3.2 中,InstanceMethods 模块已被弃用。如果我理解正确,
我正在使用sequelize 连接到mysql 数据库进行开发。我有一个名为 Dealer 的模型: 'use strict'; module.exports = function(sequelize
在我们的代码库中,SWIG 结合了 Python 和 C++。 C++ 类有时会像这样被赋予 Python 扩展: %pythoncode %{ def DiscreteKey_baseData(se
我有一个如下所示的数据框: id ttp var cap_util wip 0 ADLL 3.333333 6.003725e-
我正在模拟循环算法,下面列出的代码给我错误 RR.Przesuniecie[Oczekujace_procesy] TypeError: 'instancemethod' object is unsu
我对 python 和线程还很陌生。我正在尝试编写一个使用线程和队列的程序,以便使用凯撒密码加密 txt 文件。当我单独使用加密函数时,它本身运行良好,但在我的程序中使用它时出现错误。错误从这一行开始
在调试来自 https://github.com/haydnw/AirPi/blob/master/outputs/ubidots.py 的 AirPi 代码时,我遇到了输出期间出现异常:“insta
HTML java c network python list_categories = reques
我想做这样的事情: class X: @classmethod def id(cls): return cls.__name__ def id(self):
所以开始我对 Node.js 的所有事物的冒险。我正在尝试学习的工具之一是 Sequelize。所以我将开始我想做的事情: 'use strict'; var crypto = require('cr
我在文件中创建了一个函数并使用 export function foo(params...) { // do something } 在模型的初始化中,我以这种方式导入函数: import { fo
我有一个类 (Bar),它实际上有自己的状态和回调,并被另一个类 (Foo) 使用: class Foo(object): def __init__(self): sel
我是一名优秀的程序员,十分优秀!