I’m trying to port something I wrote in PHP into Python, mainly as an exercise to better learn the language. The code in question is a SWF parser. In PHP, I have all my data structure declared as classes. I’m trying to do the same in Python but there doesn’t seem to be a explicit way to declare a class variable. So I end up with many classes that look like this:
class SWFRGBA(object):
red = 0
green = 0
blue = 0
alpha = 0
Do Pythoners actually write things like this?
[EDIT]
Let me post some actual code to illustrate the issue. The function below reads the vector shapes in an SWF file. The readUB(), readSB() reads a certain number of bits interpretating them unsigned or signed. Sometimes, the number of bits required for a given field is itself read from the bitstream. Three types of records might appear: straight edge, quadratic curve, or style change. A style change record might move the pen position, change the line style index, change one of the two fill style indices, or replace the style arrays.
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;
}
Yes, I’m afraid a class like that would look kind of dumb to anyone who knew Python well.
A real Pythonista might use a metaclass to parameterize the making of the sort of classes you want. A metaclass is just a class whose instances are other classes. Here’s an example of one that does many of the things I think you want (from your question and comments):
With the metaclass defined as shown, you can then use it to declare different classes and then create one or more instances of them. In Python memory is mostly managed for you, so there is no
newoperator like PHP apparently requires. As a result of that, there are no pointers, so access to class members is generally done through dot notation rather than->.With that said, here’s an example of declaring a struct-like class, creating a couple of separate instances of it, and accessing their members:
You can assign values to as many or few of the class’s fields as you wish in the constructor call by using keyword arguments, which can be given in any order. Unassigned fields are given a default value of
None. Fields may be of any type.Any existing field of instances of the class created can be referred to using dot notation:
But new fields cannot be added after an instance is created: