What's the best way to minimize the need of run time checks?

BartC bc at freeuk.com
Sun Aug 14 12:31:19 EDT 2016


On 14/08/2016 14:18, Chris Angelico wrote:
> On Sun, Aug 14, 2016 at 8:49 PM, BartC <bc at 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
>




More information about the Python-list mailing list