setting variables in outer functions

Dustan DustanGroups at gmail.com
Wed Oct 31 18:49:28 EDT 2007


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.

> 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.

> 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.




More information about the Python-list mailing list