setting variables in outer functions

Chris Mellon arkanes at gmail.com
Wed Oct 31 23:59:50 CET 2007


On Oct 31, 2007 5:49 PM, Dustan <DustanGroups at gmail.com> wrote:
> On Oct 31, 7:08 am, Duncan Booth <duncan.bo... at invalid.invalid> wrote:
>
> > Dustan <DustanGro... at gmail.com> wrote:
> > > On Oct 30, 11:29 am, Duncan Booth <duncan.bo... at invalid.invalid>
> > > wrote:
> > >> Neil Cerutti <horp... at yahoo.com> wrote:
> > >> > It's allows a standard programming idiom which provides a
> > >> > primitive form of object oriented programming using closures to
> > >> > represent state.
> >
> > >> > def account(opening_balance):
> > >> >   balance = opening_balance
> > >> >   def get_balance():
> > >> >     nonlocal balance
> > >> >     return balance
> > >> >   def post_transaction(x):
> > >> >     nonlocal balance
> > >> >     balance += x
> > >> >   return balance, post_transaction
> >
> > >> > fred_balance, fred_post = account(1500)
> > >> > joe_balance, joe_post = account(12)
> > >> > fred_post(20)
> > >> > joe_post(-10)
> > >> > fred_balance()
> >
> > >> TypeError: 'int' object is not callable
> >
> > >> > 1520
> > >> > joe_balance()
> >
> > >> TypeError: 'int' object is not callable
> >
> > >> > 2
> >
> > >> > Python classes will of course nearly always win, though the idiom
> > >> > looks like it might be faster (I don't have Python 3000 to try it
> > >> > out).
> >
> > >> Python classes might be less error prone.
> >
> > > Why would using classes make your code any less prone to typographical
> > > errors?
> >
> > Lots of reasons: shorter and clearer code being high on the list.
>
> It wouldn't be necessarily shorter, depending on what you're working
> with. Clearer is a matter of opinion.
>

It's going to be shorter in any non-trivial example, and even in most
trivial ones (as shown). Clearer may be a matter of opinion, but the
less complicated the code you're looking at is, the less chance you
have to make an error.

> > The
> > class equivalent would be:
> >
> > >>> class Account(object):
> >
> >    def __init__(self, opening_balance):
> >        self.balance = opening_balance
> >
> >    def post_transaction(self, x):
> >         self.balance += x
> >
> > >>> fred = Account(1500)
> > >>> joe = Account(12)
> > >>> fred.post_transaction(20)
> > >>> joe.post_transaction(-10)
> > >>> fred.balance
> > 1520
> > >>> joe.balance
> >
> > 2
> >
> > There is no scope for the particular error I highlighted: you no longer
> > have the duplication of declaring the functions and then returning them.
>
> The 'particular error' you highlighted was a typographical error,
> which can happen in any code. Sure, you can't have the exact same
> typographical error, but that's what happens when you switch between
> paradigms.
>

By having fewer explicit things to manage, you lessen the scope of
errors in naming those things. This is one reason why the DRY
principle is advocated - the fewer times you type something, the fewer
chances you have to typo it.

> > Also you don't need the accessor function at all (and if at some point
> > in the future you do want it you can make it a property).
> >
> > You don't have to invent separate names for each of the returned
> > functions: the dot notation suddenly makes that a no brainer.
>
> Fair enough; you got two valid arguments there.
>
> > Also the class is easier to extend: you no longer have to find and
> > change every call to account() if you want to add another method: just
> > add it.
>
> Of course, there are cases where you'll never want to extend it.
>

Designing it in such a way that it's impossible to extend pretty much
ensures that, doesn't it?

I have no idea why someone who already has a working, object system
would want to implement their own on top of closures. I'd even take
issue with the idea that's it's a "standard" idiom for the quite
uncommon task of creating object systems, it's a well known conceptual
idea but it's not actually implemented as such very often.



More information about the Python-list mailing list