0

I've got the following Python code:

def GF(p, m=1):
    # Yeah, I know this should be a metaclass, but I can't find a good tutorial on them
    q = p ** m
    class _element:
        p = p
        m = m
        q = q
        def __init__(self, value):
            self.value = value
        def __repr__(self):
            return 'GF(%i, %i)(%i)' % (self.p, self.m, self.value)
        ...
    return _element

The problem here is with the line p = p: the left side "binds" p to the class' definition, preventing it from pulling in p from the locals.

One fix I can see is hacking around the variable names to fit:

def GF(p, m=1):
    q = p ** m
    _p, _m, _q = p, m, q
    class _element:
        p = _p
        m = _m
        q = _q
        def __init__(self, value):
            self.value = value
        def __repr__(self):
            return 'GF(%i, %i)(%i)' % (self.p, self.m, self.value)
        ...
    return _element

Is there a more recognized or stable way to do this?

  • 1
    I think the best you could do here would be to move the class definition to a separate factory function; it wouldn't be part of your public interface, so you could arbitrarily choose its parameter names to not conflict with the class attributes. Another advantage of this approach is that the factory could cache the created classes (keyed by a `(p, m)` tuple), rather than create a brand-new class each time. – jasonharper Nov 23 '22 at 22:04
  • You can solve this by doing the initialization in `__init__`, using `self.p = p`, etc. I think class attributes are overrated. The `__init__` is more explicit. – Tim Roberts Nov 23 '22 at 22:54
  • 1
    I think the underscore thing is fine and better than the alternatives. – Ry- Nov 24 '22 at 03:11

1 Answers1

0

Firstly, here's a good tutorial. Secondly, you can use the type function in python to create classes.
type(name, bases, attrs) So to answer your question here's some code :

def display(self):
    return 'GF(%i, %i)(%i)' % (self.p, self.m, self.value)

def constructor(self, value):
    self.value = value

def GF(p, m=1):
    q = p ** m
    return type("_element", (), {'p': p, 'm': m, 'q': q, '__repr__':display, '__init__':constructor})