在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
这甚至可能吗?
答案 0 :(得分:5)
您可以使用装饰器
>>> 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。
答案 1 :(得分:3)
你可以用元类来做到这一点:
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__
。