【问题标题】:How to get the class name of a staticmethod如何获取静态方法的类名
【发布时间】:2014-10-22 17:50:18
【问题描述】:

所以基类中有一个静态方法,子类应该使用它。

但是,我需要知道哪个子类调用了静态方法。

代码是这样的:

class BaseClass():
    @staticmethod
    def getname():
        #some magic

class SubClassA(BaseClass): 
    pass

class SubClassB(BaseClass):
    pass

SubClassA.getname()   #hope to see 'SubClassA'
SubClassB.getname()   #hope to see 'SubClassB'

或者,这可能吗?

【问题讨论】:

标签: python static-methods


【解决方案1】:

staticmethod 不可能。但是,classmethod

是可能的
class A(object):
    @classmethod
    def f(cls):
        print cls

【讨论】:

  • staticmethodis 是可能的(请参阅我的回答中的元类示例)——但要么只是要求 cls.__name__ 或将其设为 classmethod 肯定是更好的解决方案。
【解决方案2】:

根据定义,staticmethod 不提供对调用类或实例的引用——这就是 Python 中“静态”的含义。

您可以通过元类或装饰器做一些 hacky 的事情来实现这一点。

请注意,我使用的示例思想是从您的帖子中获取类的名称,但是,您可以修改此示例以使用您希望作为静态函数的任何类型的函数。您只需在下面的getnameable 中定义该函数,就像我定义了getname 并使用下面的some_class 参数(并且您将使用与我在这里使用的所有“getname”内容不同的名称)。

使用装饰器,您可以这样做:

def getnameable(some_class):

    # Note, this could be any kind of static method that you want, not
    # just for getting the name. And it can use `some_class` in whatever
    # way is needed.
    def getname():
        return some_class.__name__
    some_class.getname = staticmethod(getname)
    return some_class

然后这个工作:

In [334]: @getnameable
class SubClassA(BaseClass):
    pass
   .....: 

In [335]: SubClassA.getname()
Out[335]: 'SubClassA'

但请注意,如果您直接在BaseClass 中实现此功能,则绑定的类名将是BaseClass,即使在子类中也是如此。因此,在这种情况下,您需要将装饰器放在您想要的每个类上。

元类通过表明您希望装饰类的业务成为类创建的一部分(而不是实例创建,请注意),从而解决了这个问题。

class GetNameableMeta(type):
    def __new__(cls, name, bases, attrs):
        temp_class = super(GetNameableMeta, cls).__new__(cls, name, bases, attrs)
        return getnameable(temp_class)

class BaseClass(object):
    __metaclass__ = GetNameableMeta

class SubClassA(BaseClass):
    pass

测试一下:

In [337]: %cpaste
Pasting code; enter '--' alone on the line to stop or use Ctrl-D.
:class GetNameableMeta(type):
:    def __new__(cls, name, bases, attrs):
:        temp_class = super(GetNameableMeta, cls).__new__(cls, name, bases, attrs)
:        return getnameable(temp_class)
:
:class BaseClass(object):
:    __metaclass__ = GetNameableMeta
:
:class SubClassA(BaseClass):
:    pass
:--

In [338]: SubClassA.getname()
Out[338]: 'SubClassA'

In [339]: BaseClass.getname()
Out[339]: 'BaseClass'

当我们有几个合理的替代方案时,请注意我们需要编写多少高级代码才能做到这一点:

  1. 直接询问__name__ 属性即可。
  2. 首先将其设为classmethod。
  3. 在我们需要的地方使用装饰器并放弃继承部分。

我怀疑“Python 的精髓”中的任何一个都比我上面描述的机制更好,因为它使代码更简单、更容易理解。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-13
    • 1970-01-01
    相关资源
    最近更新 更多