1

主に言語をよりよく学ぶための演習として、PHP で書いたものを Python に移植しようとしています。問題のコードは SWF パーサーです。PHP では、すべてのデータ構造をクラスとして宣言しています。私はPythonで同じことをしようとしていますが、クラス変数を宣言する明示的な方法はないようです. したがって、次のような多くのクラスになります。

class SWFRGBA(object):
    red = 0
    green = 0
    blue = 0
    alpha = 0

Pythoners は実際にこのようなことを書きますか?

[編集]

問題を説明するために、実際のコードを投稿させてください。以下の関数は、SWF ファイル内のベクトル形状を読み取ります。readUB()、readSB() は、特定の数のビットを読み取り、符号なしまたは符号付きと解釈します。場合によっては、特定のフィールドに必要なビット数自体がビットストリームから読み取られます。3 つのタイプのレコードが表示される可能性があります: 直線エッジ、二次曲線、またはスタイルの変更。スタイル変更レコードは、ペン位置の移動、線スタイル インデックスの変更、2 つの塗りつぶしスタイル インデックスのいずれかの変更、またはスタイル配列の置換を行う可能性があります。

protected function readShapeRecords($numFillBits, $numLineBits, $version, &$bytesAvailable) {
    $records = array();
    while($bytesAvailable) {
        if($this->readUB(1, $bytesAvailable)) {
            // edge
            if($this->readUB(1, $bytesAvailable)) {
                // straight
                $line = new SWFStraightEdge;
                $line->numBits = $this->readUB(4, $bytesAvailable) + 2;
                if($this->readUB(1, $bytesAvailable)) {
                    // general line
                    $line->deltaX = $this->readSB($line->numBits, $bytesAvailable);
                    $line->deltaY = $this->readSB($line->numBits, $bytesAvailable);
                } else {
                    if($this->readUB(1, $bytesAvailable)) {
                        // vertical
                        $line->deltaX = 0;
                        $line->deltaY = $this->readSB($line->numBits, $bytesAvailable);
                    } else {
                        // horizontal 
                        $line->deltaX = $this->readSB($line->numBits, $bytesAvailable);
                        $line->deltaY = 0;
                    }
                }
                $records[] = $line;
            } else {
                // curve
                $curve = new SWFQuadraticCurve;
                $curve->numBits = $this->readUB(4, $bytesAvailable) + 2;
                $curve->controlDeltaX = $this->readSB($curve->numBits, $bytesAvailable);
                $curve->controlDeltaY = $this->readSB($curve->numBits, $bytesAvailable);
                $curve->anchorDeltaX = $this->readSB($curve->numBits, $bytesAvailable);
                $curve->anchorDeltaY = $this->readSB($curve->numBits, $bytesAvailable);
                $records[] = $curve;
            }
        } else {
            $flags = $this->readUB(5, $bytesAvailable);
            if(!$flags) {
                break;
            } else {
                // style change
                $change = new SWFStyleChange;
                if($flags & 0x01) {
                    $change->numMoveBits = $this->readSB(5, $bytesAvailable);
                    $change->moveDeltaX = $this->readSB($change->numMoveBits, $bytesAvailable);
                    $change->moveDeltaY = $this->readSB($change->numMoveBits, $bytesAvailable);
                }
                if($flags & 0x02) {
                    $change->fillStyle0 = $this->readUB($numFillBits, $bytesAvailable);
                }
                if($flags & 0x04) {
                    $change->fillStyle1 = $this->readUB($numFillBits, $bytesAvailable);
                }
                if($flags & 0x08) {
                    $change->lineStyle = $this->readUB($numLineBits, $bytesAvailable);
                }
                if($flags & 0x10) {
                    $change->newFillStyles = $this->readFillStyles($version, $bytesAvailable);
                    $change->newLineStyles = $this->readLineStyles($version, $bytesAvailable);
                    $change->numFillBits = $numFillBits = $this->readUB(4, $bytesAvailable);
                    $change->numLineBits = $numLineBits = $this->readUB(4, $bytesAvailable);
                }
                $records[] = $change;
            }
        }
    }
    $this->alignToByte();
    return $records;
}
4

4 に答える 4

8

一連の属性を保持するインスタンスだけが必要な場合は、namedtupleを使用する必要があります

于 2012-08-11T20:48:08.793 に答える
3

次のように言っている意味がわかりません。

しかし、クラス変数を宣言する明示的な方法はないようです

コード スニペットは、4 つのクラス変数を持つクラスを定義します。

はい、Python プログラマーがそのようなクラスを作成する場合があります。しかし、これは、少なくとも私の見解では、オブジェクトを生成するクラスというよりは、関連するデータのグループ化に似ています。

ケースに関する限り、伝統的に変数は小文字、定数は大文字です (技術的には Python には定数はありませんが、それは別の議論です)。例えば:

attempts = 5
attempts_on_target = 2
MAX_ATTEMPTS = 10
于 2012-08-11T20:49:05.587 に答える
2

はい、私はそのようなクラスがPythonをよく知っている人にはちょっとばかげているように見えるのではないかと心配しています。

実際のPythonistaは、メタクラスを使用して、必要な種類のクラスの作成をパラメーター化する場合があります。メタクラスは、インスタンスが他のクラスである単なるクラスです。これは私があなたが望むと思う多くのことをするものの例です(あなたの質問とコメントから):

from copy import copy

class MetaStruct(type):
    def __init__(cls, name, bases, cls_dict):
        try:
            fields = cls_dict['fields']
        except KeyError:
            raise TypeError("No 'fields' attribute defined in class " + `name`)

        # field names may be separated by whitespace and/or commas
        fields = fields.replace(',', ' ').split()
        del cls_dict['fields']  # keep out of class instances

        if 'default_field_value' not in cls_dict:
            default_field_value = None  # default default field value
        else:
            default_field_value = cls_dict['default_field_value']
            del cls_dict['default_field_value']   # keep out of class instances

        super(MetaStruct, cls).__init__(name, bases, cls_dict)

        def __init__(self, **kwds):
            """ __init__() for class %s """ % name
            self.__dict__.update(zip(fields, [copy(default_field_value)
                                                  for _ in xrange(len(fields))]))
            self.__dict__.update(**kwds)

        def __setattr__(self, field, value):
            """ Prevents new field names from being added after creation. """
            if field in self.__dict__:
                self.__dict__[field] = value  # avoid recursion!
            else:
                raise AttributeError('Can not add field %r to instance of %r' %
                                     (field, name))
        # add defined methods to class instance
        setattr(cls, '__init__', __init__)
        setattr(cls, '__setattr__', __setattr__)

示されているように定義されたメタクラスを使用して、さまざまなクラスを宣言し、それらの1つ以上のインスタンスを作成できます。Pythonでは、メモリはほとんどがあなたのために管理されているので、newPHPが明らかに必要とするような演算子はありません。その結果、ポインタがないため、クラスメンバーへのアクセスは、通常、ではなくドット表記で行われ->ます。

そうは言っても、構造体のようなクラスを宣言し、そのインスタンスをいくつか作成して、それらのメンバーにアクセスする例を次に示します。

# sample usage
class SWF_RGBA(object):
    __metaclass__ = MetaStruct
    fields = 'red, green, blue, alpha'
    default_field_value = 0  # otherwise would be None

c1 = SWF_RGBA()
print vars(c1)  # {'blue': 0, 'alpha': 0, 'green': 0, 'red': 0}
c2 = SWF_RGBA(red=1, blue=4)
print vars(c2)  # {'blue': 4, 'green': 0, 'alpha': 0, 'red': 1}

キーワード引数を使用して、コンストラクター呼び出しで必要な数のクラスのフィールドに値を割り当てることができます。この引数は任意の順序で指定できます。割り当てられていないフィールドには、デフォルト値の。が与えられますNone。フィールドはどのタイプでもかまいません。

作成されたクラスのインスタンスの既存のフィールドは、ドット表記を使用して参照できます。

print c2.blue  # 4
c2.green = 3  # assign a new value to existing green attribute

ただし、インスタンスの作成後に新しいフィールドを追加することはできません。

c2.bogus = 42  # AttributeError: Can not add field 'bogus' to instance of 'SWF_RGBA'
于 2012-08-12T09:51:23.367 に答える
1

クラス変数が望ましい場合もありますが、そうではないと思います。通常、必要なメンバー変数のほとんどは、initメソッドで値を割り当てることによって宣言されるインスタンス変数になります。

于 2012-08-11T20:46:55.490 に答える