我有一个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")
我创建了一个Language对象:
l1 = Language.EN
使用english
对象进行一些处理后,我想检索其“子类型”,即EN
。例如:
print l1
[OUT]:
EN
我尝试在语言课程中添加__repr__
或__str__
,但在我EN
时我没有print l1
:
class Language:
EN = _Language("English")
AF = _Language("Afrikaans")
SQ = _Language("Albanian")
def __str__(self):
return self.__name__
[OUT]:
Language
我如何访问变量名称,以便{I} print l1
时EN
答案 0 :(得分:5)
任何单个_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
答案 1 :(得分:1)
正如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
类中一样将其他属性填充到其中。
答案 2 :(得分:0)
覆盖,__str__
是正确的方法,但self.__name__
是类名而不是成员名,这就是为什么你总是看到"语言"。
为了做你想做的事,你需要做一些元编程。
一种方法是通过"短"作为构造函数的参数的名称。更hacky的方法是使用Language
类对象的内部字典。