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

Chris Angelico rosuav at gmail.com
Sat Aug 13 07:10:32 EDT 2016


On Sat, Aug 13, 2016 at 8:09 PM, BartC <bc at freeuk.com> wrote:
> The language doesn't make it easy for itself!

No, it doesn't. But it does make things easy for *me*, the programmer.
And yaknow what? If I want a language that makes things easy on
*itself*, I can always go write assembly language code. That's not
what I want, usually. It's definitely not what I want for efficient,
productive code on a project with more than one programmer.

At the very highest level of abstraction are human thoughts. At the
lowest, we have actual CPU-level opcodes and whatnot. In between, we
have layer upon layer of execution systems, designed to spare us
humans the hassle of translating our thoughts all the way down. When
you write code, you're reducing your thoughts to a more concrete
level; and you can pick any of quite a number of actual abstraction
levels. Programmers are generally more productive when they get to
write more abstract code, rather than mess around with the lower, more
concrete, levels - maybe it doesn't seem like much difference on
initial coding, but it's HUGELY beneficial when you edit afterwards.
In fact, the correct way to edit code is to go right back to the
highest level of abstraction - the human thought - and either correct
an error in translation (ie "this is what was intended, so make the
code do that" - debugging, at its most fundamental) or change the
thought and retranslate. Keeping the code closer to that thought is
critical to that.

Python is already at a fairly high level of abstraction. That's part
of what makes it so good. Another important part, though, is its
incredible dynamism, which allows you to *create new levels* above
what the language itself offers. Consider this code, for instance:

class Invoice(Base):
    __tablename__ = "invoices"
    id = Column(Integer, primary_key=True)
    customer_id = Column(Integer)
    date = Column(Date, nullable=False)
    updated = Column(Boolean, nullable=False, default=False)

It's a declarative way to create a database table. It's pretty
readable. It's fully executable, thanks to some magic in the "Base"
class (itself made by SQLAlchemy's declarative_base() factory, if you
want to look up the docs and find something that I got wrong here).
But in concrete terms, all it's doing is subclassing a class and
creating some class-level attributes. If Python's class system were a
simple and rigid thing like you have in C++, sure, maybe some simple
jobs would be a bit easier - but this kind of thimg would be
*impossible*. You can't use a C++ class to represent something like
this, simply by subclassing the right thing.

And if subclassing isn't enough, there's no end of stuff you can do
with decorators. Try this:

class Foo:
    @prop
    class demo:
        """Declarative property"""
        def get(self):
            print("Getting %s.demo" % self)
            return 42
        def set(self, val):
            print("Setting %s.demo" % self)
        def delete(self):
            print("Deleting %s.demo" % self)

Yaknow, because @property is just waaaaaaay too clunky, right? :) But
I needed a simple demo. The decorator isn't even all that complicated.

def prop(cls):
    return property(cls.get, getattr(cls, "set"), getattr(cls,
"delete"), cls.__doc__)

Now, try to do this kind of thing in a strict language. Use a class to
create something that isn't a class. Slap metaprogramming into
anything you want. Make executable DSLs that seamlessly integrate with
the rest of the code. It might be possible, but it sure won't be this
easy!

ChrisA



More information about the Python-list mailing list