[英]Assign class name to a class variable in Python
In Python 3.5, how can the class name be assigned to a class variable? 在Python 3.5中,如何将类名称分配给类变量? The obvious alternative is to hardcode the class name.
显而易见的替代方法是对类名进行硬编码。
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
I tried getting the class from the first argument of a @classmethod
. 我尝试从
@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())
Unfortunately, this function cannot be called when assigning to a class variable. 不幸的是,分配给类变量时不能调用此函数。
class = class_name
produces NameError: name 'class_name' is not defined
. class = class_name
产生NameError: name 'class_name' is not defined
。 my_class = Foo.class_name()
produces NameError: name 'Foo' is not defined
. my_class = Foo.class_name()
产生NameError: name 'Foo' is not defined
。
NOTE: Updated question to use the correct Python term "class variable" and not a static variable (reflecting my C++ background) 注意:已更新问题,以使用正确的Python术语“类变量”而不是静态变量(反映了我的C ++背景)
Note that having the class method 请注意,具有class方法
@classmethod
def class_name(cls):
return cls.__name__
Brings nothing compared to calling x.__class__.__name__
directly. 与直接调用
x.__class__.__name__
相比,什么也没有带来。
If you want to assign the class name, just modify the class itself: 如果要分配类名称,只需修改类本身即可:
class Foo(object):
@classmethod
def class_name(cls):
return cls.__name__
Foo.__name__ = "bar"
a = Foo()
print(a.class_name())
outputs bar
输出
bar
If you wanted different class name only for one instance, you need to create a new class on the fly (inheriting from the old class) and change the name of this class. 如果只想为一个实例使用不同的类名,则需要动态创建一个新类(继承自旧类)并更改该类的名称。
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())
outputs bar
too. 输出
bar
。
class Foo(object):
def __init__(self):
self.class_name = self.__class__.__name__
x = Foo()
x.class_name
EDIT Waitaminute. 编辑 Waitaminute。 I don't think I'm getting you.
我不认为我会得到你。 What do you mean with static variable?
静态变量是什么意思?
In Python 3 (since version 3.3), the most straightforward way to do this is to use __qualname__
(which I came across thanks to this answer ): 在Python 3(从3.3版开始)中,最简单的方法是使用
__qualname__
(由于这个答案 ,我遇到了):
class Foo(object):
name = __qualname__
class Bar(Foo):
name = __qualname__
print((Foo.name, Bar.name))
This produces the desired output: 这将产生所需的输出:
('Foo', 'Bar')
For earlier versions, or if you want to be more explicit, you could always just mention the name of your class (yes, it's not DRY, but it's KISS): 对于较早的版本,或者如果您想更明确一些,可以始终提及类的名称(是的,它不是DRY,而是KISS):
class Foo(object):
name = Foo.__name__
class Bar(Foo):
name = Bar.__name__
print((Foo.name, Bar.name))
However, both suggestions above require you to re-assign the name in derived classes. 但是,以上两个建议都要求您在派生类中重新分配名称。 Obviously, as you implemented one in your question, you are aware that you could just use a class method, but then you'd have to call it each time you wanted the name:
显然,当您在问题中实现一个时,您知道可以只使用类方法,但是每次您想使用该名称时,都必须调用它:
class Foo(object):
@classmethod
def name(cls):
return cls.__name__
class Bar(Foo):
pass
print((Foo.name(), Bar.name()))
If you don't like the parenthesis that cling to name
, what you might want to consider is to create a class property. 如果您不喜欢紧贴
name
的括号,那么您可能要考虑的是创建一个class属性。 That way you can keep it read-only and inheritable, just like the class method approach, but still maintaining the appearance of a class variable. 这样,您可以使其保持只读和可继承性,就像使用类方法一样,但仍保持类变量的外观。 Creating a class property is the topic of this question .
创建类属性是此问题的主题。 One answer suggests using a method decorator (
classproperty
, defined there), albeit with some verbosity (though you can cut the setter method): 一个答案建议使用方法装饰器(
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))
Another answer suggests using a meta-class. 另一个答案建议使用元类。 This is a new concept for me.
对我来说这是一个新概念。 While it provides succinct code, the quote by Tim Peters mentioned in this pretty good guide about meta classes deters me from recommending it:
尽管它提供了简洁的代码,但在有关元类的相当不错的指南中 ,Tim Peters所引用的引文阻止了我推荐它:
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))
I think those are enough. 我认为这些就足够了。 :)
:)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.