获取某些ducktype类的变量名

2024-09-28 01:26:42 发布

您现在位置:Python中文网/ 问答频道 /正文

我有这样一个Language类:

class _Language:
    def __init__(self, name, bRightToLeft=False):
        self.name = name
        self.bRightToLeft = bRightToLeft

    def isRightToLeft(self):
        return self.bRightToLeft

    def getName(self):
        return self.name

class Language:
    EN = _Language("English")
    AF = _Language("Afrikaans")
    SQ = _Language("Albanian")  

我创建了一个这样的语言对象:

l1 = Language.EN

在处理english对象之后,我想检索它的“子类型”,即EN。例如:

print l1

[输出]:

EN

我尝试过在语言类中添加__repr____str__,但当我print l1时,我没有得到EN

class Language:
    EN = _Language("English")

    AF = _Language("Afrikaans")
    SQ = _Language("Albanian")   

    def __str__(self):
        return self.__name__

[输出]:

Language

如何访问变量名,以便在print l1时获得EN


Tags: nameselfl1returnenglishdefsqlanguage
3条回答

重写,__str__是正确的方法,但是self.__name__是类名而不是成员名,这就是为什么总是看到“Language”。你知道吗

为了做你想做的,你需要做一些元编程。你知道吗

一种方法是将“短”名称作为参数传递给构造函数。一种更黑客的方法是使用Language类对象的内部dict。你知道吗

任何一个_Language实例都不知道您在Language名称空间(或者其他任何地方)中给它起了什么两个字母的名字。所以你有两种可能:

(1)让每个实例存储这些信息,避免重复自己的工作:

class _Language:

    def __init__(self, name, code, rtl=False):
        self.name = name
        self.code = code.upper()
        self.rtl  = rtl

    def __str__(self):
        return self.code

# ...

class Language:
    EN = _Language("English", "EN")

当然,您可以通过在Language上提供类方法来创建和注册_Language实例,而不是在类定义时创建它们,从而减少重复:

class Language:
    @classmethod
    def add(cls, name, code, rtl=False):
        settatr(cls, code, _Language(name, code, rtl))

Language.add("English", "EN")
Language.add("Afrikaans", "AF")
Language.add("Albanian", "SQ")

这可能是我个人喜欢的解决方案。你知道吗

(2)让您的_Language.__str__方法搜索Language名称空间,找出它在那里知道的名称:

def __str__(self):
    for k, v in Language.__dict__.iteritems():
        if v is self:
           return k

在这种情况下,您可以存储结果,以便只需查找一次:

class _Language:

# ...

    code = None
    def __str__(self):
        if self.code:
            return self.code
        for k, v in Language.__dict__.iteritems():
            if v is self:
               self.code = k
               return k

正如b4hand指出的,__name__类型的名称,这显然不是您想要的。对象不知道分配给它们的变量的名称。如果你想一想,他们怎么可能?同一个对象可以分配给20个不同的变量,或者没有(可能它唯一存在的地方是作为一个集合的成员)。你知道吗

将代码传递到_Language构造函数(如kindall's answer)显然是最干净的解决方案……但它需要一些重复。除了单调乏味之外,它还带来了出错的机会,以及最难调试的愚蠢的打字错误。你知道吗

那么,我们有办法解决这个问题吗?当然。施工后只需添加代码:

class _Language:
    def __init__(self, name, bRightToLeft=False):
        self.name = name
        self.bRightToLeft = bRightToLeft

    def isRightToLeft(self):
        return self.bRightToLeft

    def getName(self):
        return self.name

    def __str__(self):
        return self.code

class Language:
    EN = _Language("English")
    AF = _Language("Afrikaans")
    SQ = _Language("Albanian")

for code, language in inspect.getmembers(Language):
    if code.isalpha() and code.isupper():
        language.code = code

但是,当我们这样做的时候,我们也可以省去所有重复的_Language

class Language:
    EN = "English"
    AF = "Afrikaans"
    SQ = "Albanian"

for code, language in inspect.getmembers(Language):
    if code.isalpha() and code.isupper():
        _language = _Language(language)
        _language.code = code
        setattr(Language, code, _language)

尽管我认为如果使用dict或enum.Enum而不是只包含类属性的类,这可能会更好。你知道吗

或者,如果您想喜欢的话,这里有各种各样的Enum方法,它们展示了如何创建一个自定义枚举元类,该元类将使用现有的魔法,让Enum值知道它们的名称,还可以像在_Language类中那样将其他属性填充到它们中。你知道吗

相关问题 更多 >

    热门问题