0

私はその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__Language クラスにorを追加しようとしましたが、 i のときに__str__取得できません:ENprint l1

class Language:
    EN = _Language("English")

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

    def __str__(self):
        return self.__name__

[アウト]:

Language

print l1取得したときに変数名にアクセスするにはどうすればよいENですか?

4

3 に答える 3

5

個々の_Languageインスタンスは、Language名前空間 (または他の場所) で指定した 2 文字の名前を認識しません。したがって、次の 2 つの可能性があります。

(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

この場合、結果を保存して、1 回検索するだけで済みます。

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
于 2014-11-27T00:38:22.867 に答える
1

b4handが指摘しているように、はtype__name__の名前ですが、これは明らかにあなたが望むものではありません。オブジェクトは、割り当てられた変数の名前を知りません。考えてみれば、どうして彼らは?同じオブジェクトが 20 の異なる変数に割り当てられるか、まったく割り当てられない可能性があります (おそらく、それが存在する唯一の場所はセットのメンバーとしてです)。

kindall's answer のように、コードを_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

    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)

enum.Enumクラス属性だけでいっぱいのクラスの代わりに dict または を使用した場合、これはより良いと思いますが。

または、凝りたい場合は、値に名前を知らせ、他の属性を値Enumに詰め込むことができる既存の魔法を使用するカスタム列挙型メタクラスを作成する方法を示すあらゆる種類のレシピがあります。クラスEnum_Language

于 2014-11-27T01:03:51.353 に答える
0

オーバーライド__str__は正しいアプローチですがself.__name__、メンバー名ではなくクラス名であるため、常に「言語」が表示されます。

必要なことを行うには、メタプログラミングを行う必要があります。

1 つのアプローチは、「短い」名前を引数としてコンストラクターに渡すことです。よりハックなアプローチは、Languageクラス オブジェクトの内部辞書を使用することです。

于 2014-11-27T00:38:15.587 に答える