Python 在类变量中存储类名而不键入类名?

Python 在类变量中存储类名而不键入类名?,python,class,classname,Python,Class,Classname,在python类的一个实例方法中,我知道我们可以通过self.\uuuuu class\uuuuuu.\uuuuu name\uuuuuu 但是,我希望将类名存储在类变量中,而不编码类名 我知道我可以这样做,将类名放入类变量中: class MyClass(object): pass MyClass._myname = MyClass.__name__ 但是,我必须在类定义之外对字符串MyClass进行两次编码,以便将类名放入类变量中。在本例中,这将是“MyClass”,我可以简单地按如下

在python类的一个实例方法中,我知道我们可以通过
self.\uuuuu class\uuuuuu.\uuuuu name\uuuuuu

但是,我希望将类名存储在类变量中,而不编码类名

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

class MyClass(object):
  pass
MyClass._myname = MyClass.__name__
但是,我必须在类定义之外对字符串
MyClass
进行两次编码,以便将类名放入类变量中。在本例中,这将是
“MyClass”
,我可以简单地按如下方式进行编码:

class MyClass(object):
  _myname = "MyClass"
class MyClass(object):
  _myname = ???? # where ???? is a statement which returns the class
                 # name, in which the string "MyClass" does not appear
但即使是这样,考虑到我必须在
MyClass
类中硬编码
“MyClass”
,这也是多余的

我希望以某种方式将类名输入到类变量中,而无需对类名进行编码,如下所示:

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

这可能吗?

你可以用一个装饰师

>>> 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'
>>>

关于decorator vs元类的一个注意事项:元类是非常酷的,尽管如此,如果一个人不严格地需要它们,那么最好避免它们,因为它们臭名昭著。

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

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"

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

事实上,我过度简化了问题。我真正想要的是类变量包含一些依赖于类名的数据。。。换句话说,它将是类名函数的结果。PS:一个问题可以标记两个答案吗?Bickkngt的答案和Paul Panzer的答案都给了我想要的信息。如果可能的话,我想把你们的两个答案都标出来。@Hippman你们可以把两个都投上一票。但我相信你只能接受一个。我同样喜欢这两个答案,现在我已经任意地接受了第一个。再次感谢你们两位。