簡體   English   中英

將類名稱分配給Python中的類變量

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM