[英]Assign class name to a class variable in Python
在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 ++背景)
請注意,具有class方法
@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
。
class Foo(object):
def __init__(self):
self.class_name = self.__class__.__name__
x = Foo()
x.class_name
編輯 Waitaminute。 我不認為我會得到你。 靜態變量是什么意思?
在Python 3(從3.3版開始)中,最簡單的方法是使用__qualname__
(由於這個答案 ,我遇到了):
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
的括號,那么您可能要考慮的是創建一個class屬性。 這樣,您可以使其保持只讀和可繼承性,就像使用類方法一樣,但仍保持類變量的外觀。 創建類屬性是此問題的主題。 一個答案建議使用方法裝飾器( 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))
另一個答案建議使用元類。 對我來說這是一個新概念。 盡管它提供了簡潔的代碼,但在有關元類的相當不錯的指南中 ,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))
我認為這些就足夠了。 :)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.