1

以前にJavaで作成されたライブラリをPythonで作成する必要があります。Javaのバックグラウンドから来たPythonは、私に少し困難な時間を与えています。私は何かをする正しいpythonicの方法を選ぶことに固執しています。

したがって、私のJavaコードは次のようなものです。

import java.util.Collection;

public abstract class MyEnumBaseClass
{
    protected int    value;
    protected String description = null;

    protected MyEnumBaseClass(int iValue, String iDescription)
    {
        value = iValue;
        description = iDescription;
    }

    public int getValue()
    {
        return value;
    }

    public String getDescription()
    {
        return description;
    }

    protected static MyEnumBaseClass getEnum(Collection<MyEnumBaseClass> iter, int value)
    {
        for (MyEnumBaseClass enumObj : iter)
        {
            if (enumObj.getValue() == value)
            {
                return enumObj;
            }
        }
        return null;
    }
}



import java.util.ArrayList;
import java.util.Collection;

public class MyEnumClass extends MyEnumBaseClass
{
    private final static Collection<MyEnumBaseClass> enumList   = new ArrayList<MyEnumBaseClass>();

    public final static int                          ERROR1     = 1;
    public final static int                          ERROR2     = 2;
    public final static int                          ERROR3     = 3;
    public final static int                          ERROR4     = 4;

    public final static MyEnumClass                  ErrorEnum1 = new MyEnumClass(ERROR1, "ERROR1");
    public final static MyEnumClass                  ErrorEnum2 = new MyEnumClass(ERROR2, "ERROR1");
    public final static MyEnumClass                  ErrorEnum3 = new MyEnumClass(ERROR3, "ERROR1");
    public final static MyEnumClass                  ErrorEnum4 = new MyEnumClass(ERROR4, "ERROR1");

    protected MyEnumClass(int iValue, String iDescription)
    {
        super(iValue, iDescription);
    }

    public static int getCount()
    {
        return enumList.size();
    }

    public static Collection<MyEnumBaseClass> getList()
    {
        return enumList;
    }

    public static MyEnumBaseClass getEnum(int value)
    {
        return getEnum(enumList, value);
    }
}

これをPythonで書きたいです。私は両方の言語が完全に異なることを理解しています。正確なコードを複製したくはありませんが、Javaコードが提供する機能を提供するPythonで何かを書きたいと思っています。

だから私は次のようなものを思いついた:

# MODULE MYENUMBASECLASS:::

class MyEnumBaseClass(object):

    def __init__(self, iValue, iDescription, ui = None):
        self._value = iValue
        self._description = iDescription

    def getValue(self):
        return self._value

    def getDescription(self):
        return self._description

    @classmethod
    def getEnum(cls, value, itr):
        for enumObj in itr:
            if enumObj.getValue() == value:
                return enumObj
        return None


# MODULE: ENUMS:::
from MyEnumBaseClass import MyEnumBaseClass

__all__ = ["MyEnumClassConstants", "MyEnumClass", "MyEnums"]
_enumList = []

class MyEnumClassConstants(object):
    ERROR1 = 1
    ERROR2 = 2
    ERROR3 = 3
    ERROR4 = 4

class MyEnumClass(MyEnumBaseClass):
    def __init__(self, v, d, ui):
        global _enumList
        super(MyEnumClass, self).__init__(v, d, ui)
        _enumList.append(self)

    @staticmethod
    def getCount():
        return len(_enumList)

    @staticmethod
    def getList():
        return _enumList

    @classmethod
    def getEmum(cls, value, itr = None):
        return super(MyEnumClass, cls).getEnum(value, _enumList)


class MyEnums(object):
    ErrorEnum1 = MyEnumClass(MyEnumClassConstants.ERROR1, "ERROR1");
    ErrorEnum2 = MyEnumClass(MyEnumClassConstants.ERROR2, "ERROR2");
    ErrorEnum3 = MyEnumClass(MyEnumClassConstants.ERROR3, "ERROR3");
    ErrorEnum4 = MyEnumClass(MyEnumClassConstants.ERROR4, "ERROR4");

私は知りたいです:

  1. それはそれを行う正しいpythonicの方法ですか?

  2. ErrorEnum1,2,3,4と定数をMyEnumsクラスからモジュール変数として移動したかったのです。しかし、そうすれば、すべての変数に長いリストが含まれるようになります。また、他のモジュールにEnumsモジュールをインポートするときに変数名が衝突するリスクがあります(他のいくつかのEnums2モジュールにもErrorEnum1,2,3が含まれる場合があります。しかし、それは大きな問題ではありません。常にEnums.ErrorEnum1とEnums2を使用できます。 .ErrorEnum1)。私は正しいと思いますか?

  3. 私はこれが完璧ではないことを知っています(私の最初のPythonコード)。だから私はあなたたちに私にアイデアを与えてくれて招待します。

ありがとう

4

3 に答える 3

5

さて、あなたはあなたのコードが最適ではなく、確かに進むべき道ではないことを知っていると思います。もう1つの問題は、何をしようとしているのか正確にわからないため、「Javaコードが提供する機能を提供するPythonで何かを書く」方法がわからないことです。とは言うものの、コードには明らかなJavaバイアスがたくさんあり、問題なく削除できます。

  • まず、なぜとを持っているMyEnumBaseClassMyEnumClassですか?あなたは1つだけを持つことができます。クラスの数とモジュールの数が減ります。列挙型を拡張したい場合でも、コードを単純化すると、コードMyEnumClassが非常に単純になり、問題なく拡張できることがわかります。

  • さて、ゲッターやセッターはご遠慮ください。プロパティがあるので、それらを使用する理由はありません。プロパティが値を取得および設定するだけの場合は、とにかくプロパティを使用しないでください。

    class MyEnumClass(object):
        def __init__(self, value, description, ui = None):
            self.value = value
            self.description = description
    
  • MyEnumClassConstantsやなどの定数のような値を保持するためだけにクラスを作成するのは本当に醜いMyEnumsです。モジュールレベルでいくつかの変数を作成するだけです。以下の項目の直後にそれを行う方法を見てみましょう。

  • また、なぜgetEnum()クラスメソッドなのですか?これは単なる関数である可能性があり、モジュール内にあるため、競合について心配する必要はありません。

    def getEnum(value, itr):
        for enumObj in itr:
            if enumObj.value == value:
                return enumObj
        return None
    
  • いくつかの変数を連番で設定する場合は、解凍イディオムを使用することをお勧めします。

    (
        ERROR1,
        ERROR2,
        ERROR3,
        ERROR4
    ) = range(1, 5)
    
  • このイディオムは、列挙型のリストを作成するためにも使用できます。

    _enums = (
        ErrorEnum1,
        ErrorEnum2,
        ErrorEnum3,
        ErrorEnum4
    ) = (
        MyEnumClass(ERROR1, "ERROR1"),
        MyEnumClass(ERROR2, "ERROR2"),
        MyEnumClass(ERROR3, "ERROR3"),
        MyEnumClass(ERROR4, "ERROR4")
    )
    
  • 正直なところ、私は喜ん_enumsでモジュールのパブリックメンバーとして残しますが、Java-itis:Pで簡単にしgetEnum()ましょう。他のクラスメソッドでも同じようにしましょう。モジュール内の関数として宣言します。

    def getCount():
        return len(_enums)
    
    def getList():
        return _enums
    
  • getEnum()デフォルトのパラメータを変更することで、を改善することもできます。

    def getEnum(value, itr=_enums):
        for enumObj in itr:
            if enumObj.value == value:
                return enumObj
        return None
    
  • __all__また、ここでの宣言を喜んで禁止します。インターフェイスの一部ではない唯一のものは_enumsタプルであり、その前にPEP-8_によると、外部で使用してはならないことを意味します。しかし、それはとどまるとしましょう。モジュールには、より多くの定数と関数を備えた新しいインターフェイスがあります。

    __all__ = ["MyEnumClass", "ERROR1", "ERROR2", "ERROR3", "ERROR4",
            "ErrorEnum1", "ErrorEnum2", "ErrorEnum3", "ErrorEnum4",
            "getCount", "getList", "getEnum"]
    

    インターフェイスから削除したほうがいいようMyEnumClassですが、使用したい場合もあるので、そのままにしておきます。__all__この値は、モジュールの別のコンポーネントへのアクセスを回避しないことにも注意してください。ドキュメントを変更するだけです

最終結果は次のようになります。

__all__ = ["MyEnumClass", "ERROR1", "ERROR2", "ERROR3", "ERROR4",
        "ErrorEnum1", "ErrorEnum2", "ErrorEnum3", "ErrorEnum4",
        "getCount", "getList", "getEnum"]

class MyEnumClass(object):
    def __init__(self, value, description, ui = None):
        self.value = value
        self.description = description

(
    ERROR1,
    ERROR2,
    ERROR3,
    ERROR4
) = range(1, 5)


_enums = (
    ErrorEnum1,
    ErrorEnum2,
    ErrorEnum3,
    ErrorEnum4
) = (
    MyEnumClass(ERROR1, "ERROR1"),
    MyEnumClass(ERROR2, "ERROR2"),
    MyEnumClass(ERROR3, "ERROR3"),
    MyEnumClass(ERROR4, "ERROR4")
)

def getCount():
    return len(_enums)

def getList():
    return _enums

def getEnum(value, itr=_enums):
    for enumObj in itr:
        if enumObj.value == value:
            return enumObj
    return None

(編集)これは実際にはそれほど単純ではありません。エラーコードを作成する場合はERROR1ERROR2変数などを作成するだけです。クラスも関数も、変数の値だけを作成します。実際、エラーコードを作成するという考えでさえ不適切に思えます。PythonのZenが述べているように、エラーは決して黙って渡されるべきではないため(または、Eric RaymondのUnix哲学が言うように、失敗しなければならないときは騒々しく失敗するため)、例外を作成することをお勧めします。そしてできるだけ早く)。それでも、私が行った変更により、Pythonの記述をより正確に味わうことができると思います。

この方法で物事を行うことについてかゆみを感じるかもしれませんが、私を信じてください、それは最良の方法です。一部の人は私といくつかの点で同意しないかもしれませんが、アイデアは提示されたものです。私は主にJava開発者ですが、言語の音楽に合わせて踊ることが重要です。外国の概念を無理やり押し込まないでください。

最後に、いくつかの重要な参考資料:

  • PEP-20 -Zen of Python:PythonおよびPythonへの開発におけるコアバリューのやや詩的なリスト。
  • PEP-8 -Pythonのスタイルガイド。今すぐ読んでください。
  • PythonはJavaではありません-Pythonで不適切なJavaの習慣を回避するための最良のガイドの1つです。
于 2012-06-26T22:06:53.197 に答える
0
  • 一般に、Pythonクラスのプロパティは、公開されない正当な理由がない限り、公開されたままになります。

  • プロパティをプライベートにする必要@propertyがある場合は、getPropertyメソッドよりもデコレータを使用する方がPythonicです。

class MyEnumBaseClass(object):
    def __init__(self, value, description, ui=None):
        self.value = value
        self._description = description
        self.ui = [] if ui is None else ui

    @property
    def description(self):
        return self._description

    @classmethod
    def get_enum(cls, value, itr):
        for enumObj in itr:
            if enumObj.value == value:
                return enumObj
        return None
于 2012-06-26T20:56:15.497 に答える
0

よりPython的なアプローチ:

class EnumValue(object):
    def __init__(self, value, description):
        self.value = value
        self.description = description

class EnumType(object):
    @classmethod
    def lookup(cls, value):
        for error in cls.VALUES:
            if error.value == value:
                return value
        raise ValueError(value)    

class MyErrors(EnumType):
    ERROR1 = EnumValue(1, "Simple Errors")
    ERROR2 = EnumValue(2, "Bigger Errors")
    ERROR3 = EnumValue(3, "Really Big Errors")

    VALUES = [ERROR1, ERROR2, ERROR3]
于 2012-06-26T21:29:51.023 に答える