将类名存储在类变量中而不输入类名?

Posted

技术标签:

【中文标题】将类名存储在类变量中而不输入类名?【英文标题】:Storing the class name in class variable without typing the name of the class? 【发布时间】:2017-07-11 22:15:28 【问题描述】:

在一个python类的实例方法中,我知道我们可以通过self.__class__.__name__获取类名

但是,我想将类的名称存储在类变量中,而不用编码类的名称。

我知道我可以这样做来将类名放入类变量中:

class MyClass(object):
  pass
MyClass._myname = MyClass.__name__

但是,我必须在类定义之外对字符串 MyClass 编码两次,只是为了将类名放入类变量中。在这种情况下,就是"MyClass",我可以简单地编写如下代码:

class MyClass(object):
  _myname = "MyClass"

但即使这样也是多余的,因为我必须在 MyClass 类中硬编码 "MyClass"

我想要以某种方式将类名放入类变量中,而不用对类名进行编码,如下所示:

class MyClass(object):
  _myname = ???? # where ???? is a statement which returns the class
                 # name, in which the string "MyClass" does not appear

这可能吗?

【问题讨论】:

【参考方案1】:

你可以使用装饰器

>>> def autoname(cls):
...    cls._MyName=cls.__name__
...    return cls
... 
>>> @autoname
... class check:
...    pass
... 
>>> check._MyName
'check'
>>> 

或者,如果您不想硬编码属性名称:

>>> def autoname2(name):
...     def autoname(cls):
...         setattr(cls, name, cls.__name__)
...         return cls
...     return autoname
...
>>> @autoname2('_StoreHere')
... class check2:
...     pass
... 
>>> check2._StoreHere
'check2'
>>> 

当然,第二种形式可以带更多参数,例如:

>>> def autoname3(name, f=lambda x: x):
...     def autoname(cls):
...         setattr(cls, name, f(cls.__name__))
...         return cls
...     return autoname
...
>>> @autoname3('_MyNameIs', lambda x: x.upper() + '_The_Bold')
... class check3:
...     pass
... 
>>> check3._MyNameIs
'CHECK3_The_Bold'
>>>

关于装饰器与元类的说明:元类非常酷,但如果不是严格需要它们,最好避免使用它们,因为臭名昭著的metaclass conflicts。

【讨论】:

【参考方案2】:

您可以使用元类来做到这一点:

class NameMeta(type):
    def __new__(meta, name, bases, dct):
        dct['_name'] = name
        return super().__new__(meta, name, bases, dct)

class Foo(metaclass=NameMeta):
    pass

print(Foo._name)     # prints "Foo"

请注意,将名称设置为类的新属性有点愚蠢,因为__name__ 已经存在。可能您应该更改正在编写的任何查看 _name 属性的代码,并改为查找 __name__

【讨论】:

嗯,实际上,我过度简化了问题。我真正想要的是类变量包含一些依赖于类名的数据......换句话说,它将是类名函数的结果。 PS:一个问题可以标记两个答案吗? Bickkngt 的回答和 Paul Panzer 的回答都为我提供了我正在寻找的信息。如果可能的话,我想标记你的两个答案。 @HippoMan 你可以对两者都投赞成票。但请接受,我很确定你只能选择一个。 好的。我同样喜欢这两个答案,而我现在只是武断地接受了第一个。再次感谢你们。

以上是关于将类名存储在类变量中而不输入类名?的主要内容,如果未能解决你的问题,请参考以下文章

static关键字

static关键字作用总结

static关键字

day24继承

PHP 静态变量和静态方法

类和对象