Skip to main content
Code Review

Return to Answer

replaced http://stackoverflow.com/ with https://stackoverflow.com/
Source Link

Regarding metaclass, it depends of your usecases. Here it seems like there is only few sets of classes that can be built given the GF class template because g_power can only be 4, 8 or 16. In this case metaclass or class decorators class decorators be a good fit.*

Have a look at How can I dynamically create derived classes from a base class How can I dynamically create derived classes from a base class for more information on how dynamic class creation works.

Regarding metaclass, it depends of your usecases. Here it seems like there is only few sets of classes that can be built given the GF class template because g_power can only be 4, 8 or 16. In this case metaclass or class decorators be a good fit.*

Have a look at How can I dynamically create derived classes from a base class for more information on how dynamic class creation works.

Regarding metaclass, it depends of your usecases. Here it seems like there is only few sets of classes that can be built given the GF class template because g_power can only be 4, 8 or 16. In this case metaclass or class decorators be a good fit.*

Have a look at How can I dynamically create derived classes from a base class for more information on how dynamic class creation works.

add more information regarding the dynamic construction of class
Source Link

This approach can also works in the other cases an is kind of the simpler both to use and to understand since it's only basic function calls. It's my prefered solution.

Have a look at How can I dynamically create derived classes from a base class for more information on how dynamic class creation works.

This approach can also works in the other cases an is kind of the simpler both to use and to understand since it's only basic function calls. It's my prefered solution.

Have a look at How can I dynamically create derived classes from a base class for more information on how dynamic class creation works.

Source Link

Defining a function inside a class create a staticmethod in Python 3 so you don't need to use staticmethod decorator. What you might want to use is classmethod to define a method which gets the class as first arguments. You code could be rewritten as:

class GP(object):
 
 @classmethod
 def setup(klass, g_power):
 # ... check for valid input
 # use klass instead of `GF`
 klass.field_power = g_power
 klass.field_len = 1 << g_power

It can be used just like a you do currently GP.setup(42). What changes is that you have a reference to the current class the consequence is that you can inherit class GP an call MyChildClass.setup which will will initialize MyChildClass and its namespace and not re-use the namespace of the parent class GP. If you need to inherit and need to have separate class properties (e.g. GP.field_power and GP.field_len) for each subclass, you will need to use classmethod decorator and rework your code to use klass like it's done in the above snippet and type(self) in the methods to access the properties of the correct class e.g. type(self).field_power instead of GP.field_power.

Regarding metaclass, it depends of your usecases. Here it seems like there is only few sets of classes that can be built given the GF class template because g_power can only be 4, 8 or 16. In this case metaclass or class decorators be a good fit.*

Using class decorators you end up writing the following code:

@setupGF(8)
class GF8(GF):
 pass

setupGF will takes klass argument and do the same things as you current GF.setup.

The metaclass method looks a bit different. You have to declare your class configuration upfront too, but with a class property:

class GF8(GF, metaclass=MetaGF):
 g_power = 8

But before showing the metaclass code, this can be used also without metaclass. Say you declare a class like that:

class GF8(GF):
 g_power = 8

You can conditionally call type(self).setup() when the class is not yet initialized. This can only work if you properly defined setup as a classmethod.

The metaclass will avoid the conditional call to the setup method. So it's in this case metaclass can be used as an optimisation.

The simplest way to define a metaclass is to use a function that will construct the final class and execute setup(g_power) code:

def MetaGF(name, bases, namespace):
 # construct class just like you would dynamically create a class
 klass = type(name, bases, namespace)
 # call setup
 setup_gf_class(klass.g_power)
 # return the initialized class
 return klass
class GF8(BaseGF, metaclass=MetaGF):
 g_power = 8

But if you have more important number of class that you must generate/configure at runtime you must take a more radical path using dynamic class construction:

class BaseGF(object):
 """ implements Galois Field arithmetic for 2^4, 2^8 and 2^16
 overloads +, -, *, / and str() """
 def __init__(self, n):
 self.value = n & type(self).mask
 def __str__(self):
 return 'GF({}) element {:0>3d}d 0x{:0>2x}'.format(
 self.field_power,
 self.value,
 self.value
 )
 def __add__(self, other):
 if isinstance(other, type(self)):
 return(type(self)(self.value ^ other.value))
 else:
 raise TypeError('both args must be of GF type')
 def __sub__(self, other):
 return self + other
 def __mul__(self, other):
 if isinstance(other, type(self)):
 if self.value == 0:
 return type(self)(0)
 if other.value == 0:
 return type(self)(0)
 log_s = type(self).logs[self.value]
 log_o = type(self).logs[other.value]
 log_p = (log_s + log_o) % self.mask
 return type(self)(type(self).alogs[log_p])
 else:
 raise TypeError('both args must be of the same GF type')
 def __truediv__(self, other):
 if isinstance(other, type(self)):
 if other.value == 0:
 raise ValueError('cannot divide by 0')
 if self.value == 0:
 return type(self)(0)
 log_s = type(self).logs[self.value]
 log_o = type(self).logs[other.value]
 log_p = (log_s - log_o) % self.mask # always returns positive
 return type(self)(type(self).alogs[log_p])
 else:
 raise TypeError('both args must be of the same GF type')
def MetaGF(g_power):
 name = 'GF(%s)' % g_power
 GF = type(name, (BaseGF,), dict())
 if g_power not in (4, 8, 16):
 raise ValueError('cant do field size of {} yet'.format(g_power))
 GF.field_power = g_power
 GF.field_len = 1 << g_power
 GF.mask = GF.field_len-1
 GF.prim_poly = (0, 0, 0, 0, 9, 0, 0, 0, 29, 0, 0, 0, 0, 0, 0, 0, 32790)[g_power]
 GF.alogs = []
 GF.logs = [None]
 sr = 1
 for index in range(GF.field_len-1):
 GF.alogs.append(sr)
 sr <<= 1
 if sr & GF.field_len:
 sr ^= GF.prim_poly
 sr &= (GF.mask)
 for sr in range(1, GF.field_len):
 GF.logs.append(GF.alogs.index(sr))
 return GF
GF8 = MetaGF(8)
print(GF8(12)+GF8(7))
# test cases from the Intel paper
print(GF8(2)*GF8(8))
print(GF8(18)*GF8(5))
print(GF8(13)/GF8(17))
print(GF8(2)/GF8(11))
lang-py

AltStyle によって変換されたページ (->オリジナル) /