Frage

I want to write a program that accepts as input a number p and produces as output a type-constructor for a number that obeys integer arithmetic modulo p.

So far I have

def IntegersModP(p):
   N = type('IntegersMod%d' % p, (), {})

   def __init__(self, x): self.val = x % p
   def __add__(a, b): return N(a.val + b.val)
   ... (more functions) ...    

   attrs = {'__init__': __init__, '__add__': __add__, ... }

   for name, f in attrs.items():
      setattr(N, name, f)

   return N

This works fine, but I'd like to know what the Pythonic way to do this is, which I understand would use metaclasses.

War es hilfreich?

Lösung 2

Metaclasses are for when your class needs to behave differently from a normal class or when you want to alter the behavior of the class statement. Neither of those apply here, so there's really no need to use a metaclass. In fact, you could just have one ModularInteger class with instances that record their value and modulus, but assuming you don't want to do that, it's still easy to do this with an ordinary class statement:

def integers_mod_p(p):
    class IntegerModP(object):
        def __init__(self, n):
            self.n = n % IntegerModP.p
        def typecheck(self, other):
            try:
                if self.p != other.p:
                    raise TypeError
            except AttributeError:
                raise TypeError
        def __add__(self, other):
            self.typecheck(other)
            return IntegerModP(self.n + other.n)
        def __sub__(self, other):
            ...
    IntegerModP.p = p
    IntegerModP.__name__ = 'IntegerMod{}'.format(p)
    return IntegerModP

Andere Tipps

Like this:

def IntegerModP(p):  # class factory function
    class IntegerModP(object):
        def __init__(self, x):
            self.val = x % p
        def __add__(a, b):
            return IntegerModP(a.val + b.val)
        def __str__(self):
            return str(self.val)
        def __repr__(self):
            return '{}({})'.format(self.__class__.__name__, self.val)

    IntegerModP.__name__ = 'IntegerMod%s' % p  # rename created class
    return IntegerModP

IntegerMod4 = IntegerModP(4)
i = IntegerMod4(3)
j = IntegerMod4(2)
print i + j        # 1
print repr(i + j)  # IntegerMod4(1)
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top