在Python 3.5中,如何将类名分配给类变量?显而易见的替代方法是对类名进行硬编码。
class Foo(object):
the_module = __name__
also_the_module = __module__
def name_of_module(self):
return __name__
def name_of_class(self):
return __class__.__name__
print("Foo.the_module= ", Foo.the_module)
print("Foo.also_the_module= ", Foo.also_the_module)
print("Foo.__name__= ", Foo.__name__) # what is desired but outside of class def
print("Foo().name_of_module=", Foo().name_of_module())
print("Foo().name_of_class= ", Foo().name_of_class()) # what is desired but inside a method
我尝试从@classmethod
的第一个参数中获取该类。
class Foo(object):
@classmethod
def class_name(cls):
return cls.__name__
# Both of these produce the correct response but neither
# can be used assign to a class variable
print("Foo.class_name()= ", Foo.class_name())
print("Foo().class_name()= ", Foo().class_name())
不幸的是,在分配给类变量时无法调用此函数。 class = class_name
生成NameError: name 'class_name' is not defined
。 my_class = Foo.class_name()
生成NameError: name 'Foo' is not defined
。
注意:更新了问题以使用正确的Python术语“类变量”而不是静态变量(反映我的C ++背景)
答案 0 :(得分:1)
请注意具有类方法
@classmethod
def class_name(cls):
return cls.__name__
与直接致电x.__class__.__name__
相比,什么也没有带来。
如果要分配类名,只需修改类本身:
class Foo(object):
@classmethod
def class_name(cls):
return cls.__name__
Foo.__name__ = "bar"
a = Foo()
print(a.class_name())
输出bar
如果只想为一个实例使用不同的类名,则需要动态创建一个新类(从旧类继承)并更改该类的名称。
def set_class_name(instance, new_class_name):
orig_class = instance.__class__
class _new_class(orig_class):
pass
_new_class.__name__ = new_class_name
a.__class__ = _new_class
a = Foo()
set_class_name(a, 'bar')
print(a.class_name())
也输出bar
。
答案 1 :(得分:0)
class Foo(object):
def __init__(self):
self.class_name = self.__class__.__name__
x = Foo()
x.class_name
编辑 Waitaminute。我不认为我能得到你。静态变量是什么意思?
答案 2 :(得分:0)
在Python 3(从3.3版开始)中,最简单的方法是使用__qualname__
(感谢这个answer的帮助):
class Foo(object):
name = __qualname__
class Bar(Foo):
name = __qualname__
print((Foo.name, Bar.name))
这将产生所需的输出:
('Foo', 'Bar')
对于较早的版本,或者如果您想更明确一些,您总是可以提及您的类的名称(是的,它不是DRY,而是KISS):
class Foo(object):
name = Foo.__name__
class Bar(Foo):
name = Bar.__name__
print((Foo.name, Bar.name))
但是,以上两个建议都要求您在派生类中重新分配名称。显然,当您在问题中实现一个时,您意识到可以只使用类方法,但是每次您想使用该名称时,都必须调用它:
class Foo(object):
@classmethod
def name(cls):
return cls.__name__
class Bar(Foo):
pass
print((Foo.name(), Bar.name()))
如果您不喜欢紧跟name
的括号,则可能要考虑的是创建一个类属性。这样,您可以使其保持只读和可继承性,就像使用类方法一样,但仍保持类变量的外观。创建类属性是this question的主题。一个answer建议使用一种方法修饰符(在那里定义的classproperty
,尽管有些冗长(尽管您可以削减setter方法):
# classproperty is defined in the aforementioned answer
class Foo(object):
@classproperty
def name(cls):
return cls.__name__
class Bar(Foo):
pass
print((Foo.name, Bar.name))
另一个answer建议使用元类。对我来说这是一个新概念。尽管提供了简洁的代码,但Tim Peters mentioned in this pretty good guide about meta classes的引用阻止了我推荐它:
class FooMetaclass(type):
@property
def name(cls):
return cls.__name__
class Foo(metaclass=FooMetaclass):
# for Python 2, remove the metaclass assignment above, and add:
# __metaclass__ = FeatureMetaclass
pass
class Bar(Foo):
pass
print((Foo.name, Bar.name))
我认为这些就足够了。 :)