我想做这样的事情:
class X:
@classmethod
def id(cls):
return cls.__name__
def id(self):
return self.__class__.__name__
现在调用id()
类或它的实例:
>>> X.id()
'X'
>>> X().id()
'X'
显然,此确切的代码不起作用,但是是否有类似的方法可以使它起作用?还是任何其他解决方法都可以在没有太多“怪异”内容的情况下获得这种行为?
类和实例方法位于同一个命名空间中,并且您不能像这样重用名称。id
在这种情况下,最后的定义将获胜。
类方法将继续在实例上运行,但是, 无需 创建单独的实例方法。只需使用:
class X:
@classmethod
def id(cls):
return cls.__name__
因为方法继续绑定到该类:
>>> class X:
... @classmethod
... def id(cls):
... return cls.__name__
...
>>> X.id()
'X'
>>> X().id()
'X'
明确记录了以下内容:
可以在类(如
C.f()
)或实例(如C().f()
)上调用它。该实例除其类外均被忽略。
如果您需要一种方法,使其根据使用的位置而有所不同;在类上访问时绑定到一个类,在实例上访问时绑定到该实例,您需要创建一个自定义 描述符对象 。
该描述符的API是Python的如何导致功能被绑定为方法,并结合classmethod
对象的类;
请参阅描述符说明。
您可以通过创建具有__get__
方法的对象来为方法提供自己的描述符。这是一个简单的方法,可根据上下文切换方法所绑定的对象,如果to的第一个参数__get__
是None
,则描述符将绑定到一个类,否则它将绑定到一个实例:
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
并且仅重新定义其处理绑定的方式,将的原始实现委派给instance is None
,__get__
否则将其委派给标准函数实现。
请注意,在方法本身中,您可能随后必须测试其绑定的对象。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 html" target="_blank">object at 0x10ac7d580>'
一种替代实现可以使用 两个 函数,一个函数绑定到类时,另一个函数绑定到实例时:
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值之间的区分,其中模型中的列对象会切换这样的行为。请参阅其_混合属性_文档。其实现遵循与我hybridmethod
上面的类完全相同的模式。
问题内容: H2似乎在带引号的名称和不带引号的名称之间有所不同。有没有办法让他们以相同的方式对待他们? 这是我已经完成的测试: 这是查询: 我该怎么做才能使这些查询与H2一起使用? 问题答案: 根据SQL规范的要求,H2中的引号名称区分大小写。这意味着它将起作用: 但这不会: 在H2中,不带引号的名称不区分大小写。它们通常会转换为大写字母(例如在Oracle和其他数据库中)。这意味着声明 与…相同
问题内容: 在我的Java应用程序中,我使用第三方库。 但是,我发现有些奇怪,有一些嵌套的程序包,有些类的名称可能与程序包的名称相同。 恐怕我不清楚。这是一个例子: 包 在“ com.xx.a”内部有一个名为“ a”的类。 因此,如果我想将此类称为“ a” … 我写: 然后,IDE将认为我的意思是软件包“ com.xx.a.a”。 那我就不能打电话了。 我想知道为什么? 顺便说一句,图书馆提供者似
在Spring IOC中,bean的两个定义(具有相同的名称和类)是否有效? 我有两个bean定义文件包含在web中。xml。参见下面的示例。 应用Context-beans1.xml applicationContext-beans2。xml 到目前为止,我还没有遇到任何问题。但是,这可能会影响到多线程和集群的现实环境吗? 注意:这两个XMLs都被加载,因为我可以使用在这两个XMLs中定义的其他
问题内容: 我的问题是为什么我不能再次调用该函数?或者,如何做到这一点? 假设我有这个功能: 我称之为: 我得到4。 但是,假设我声明了一个与该函数同名的变量(错误): 现在,如果我尝试这样做: 要么: 我将收到此错误:“ TypeError:’int’对象不可调用” 无法将变量“ a”分配给函数? 问题答案: 完成此操作后: 不再是一个 函数 ,而只是一个 整数 (您已将其重新分配!)。因此,很
我不太清楚kotlin是如何管理属性名和主构造函数参数名的。如果我写了相同的属性名和参数名,那么kotlin编译器会给出一个错误。 它给出了这个错误。 但是,当我更改属性的名称或更改主构造函数的参数名称时,代码将工作并编译。 这将工作或编译罚款。 这背后的原因是什么?为什么主构造函数的参数名和属性名不能相同?
假设您有2个包,并且有名为-Test的公共类。 第一个包。测试 第二包测试 它们中的每一个都有实例变量-x。 在第一种情况下-int x=2; 在第二种情况下-int x=3; 我想导入FirstPackage。在第二个包内测试。测试并打印值为2的x。 我的代码: 但是输出是3。如何打印?