On 14/08/2016 14:18, Chris Angelico wrote:
On Sun, Aug 14, 2016 at 8:49 PM, BartC <b...@freeuk.com> wrote:
Well, it's using exec(). So it is generating new program code at runtime.
That is possible in quite a few languages, even C.

It doesn't have to; that's only so it doesn't have to manually
construct a Function object. Or you could make a simpler __init__ that
requires keyword arguments. Here's an exec-free version:

def record(name, fieldnames):
    if isinstance(fieldnames, str):
        fieldnames = fieldnames.split()
    class Inner(object):
        __slots__ = fieldnames
        def __init__(self, **kwargs):
            for n in fieldnames:
                if n in kwargs: setattr(self, n, kwargs[n])
        def __repr__(self):
            fields = ', '.join("%s=%r" % (n, getattr(self, n)) for n
in fieldnames)
            return "record %s(%s)" % (type(self).__name__, fields)
    Inner.__name__ = Inner.__qualname__ = name
    return Inner

You lose the ability to construct a record with positional args, and
you lose the argument name info from help() and other forms of
introspection, but it works, and it doesn't use exec.

How do you do that in C? Do you have an 'exec' function in C?

Not built-in to the language. C code can however write out source code, and invoke a C compiler to turn it into a shared library, which can then be linked to dynamically.

But it can't create a new record or struct type at runtime which can then be accessed using normal syntax, in compiled code that already existed before the record was created. (Only if access code is generated too.)

In general, doing the equivalent of what Steven's record() example was doing can also be done across a few languages, up to a point anyway (and usually not in five minutes!):

* Creating a handle to a data structure representing a new record (giving record name and a list of fields).

* Using that handle to create an instance of such a record (represented by any means, even just using a list).

* Allowing some way to set or get fields of each instance.

The last is harder if you want a method that looks like a field access. Doing it via functions is straightforward; allowing dot operators ('d.month') is much harder, especially with more rigid languages where everything is expected to be resolved at compile time.

It's a bit easier in Python because 'd.month' already involves dynamic mechanisms which can be hooked into. In fact, the above implementation and the original are based on classes and their existing means of setting and getting attributes.

So it's about having a more streamlined way to define such a class with a fixed set of attributes. Both use the __slots__ feature to restrict the number of attributes to that fixed list (I imagine it would have been more difficult without that).

--
Bartc


Certainly not in any of my compilers. The nearest equivalent would be
a compile-time directive, eg a preprocessor macro, and that most
definitely isn't this flexible. Types just aren't first-class objects
in C.

ChrisA


--
https://mail.python.org/mailman/listinfo/python-list

Reply via email to