Welcome, guest | Sign In | My Account | Store | Cart

The with statement in Python 2.5 can be used similarly to the anonymous blocks of code in Ruby.

Python, 33 lines
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
from __future__ import with_statement
from contextlib import contextmanager

class Table(object):
    def __init__(self, table_name):
        self.table_name = table_name
        self.fields = {}

    def __setattr__(self, attr, value):
        if attr in ("fields", "table_name"):
            object.__setattr__(self, attr, value)
        else:
            self.fields[attr] = value

    def execute(self):
        print "Creating table %s with fields: %s" % (self.table_name, self.fields)

@contextmanager
def create_table(table_name):
    table=Table(table_name)
    yield table
    table.execute()

#try it!
with create_table("Employee") as t:
    t.first_name = {"type" : "char", "length" : 30 }
    t.last_name = {"type" : "char", "length" : 30 }
    t.age = {"type" : "int"}

#prints:
#Creating table Employee with fields: {'first_name': {'length':
#30, 'type': 'char'}, 'last_name': {'length': 30, 'type': 'char'}, 'age':
#{'type': 'int'}}

This can used for the similar purposes as in Ruby: small DSL's for SQL DDL statements or unit testing or whatever.

2 comments

Ivo Danihelka 14 years, 9 months ago  # | flag

Nice. It is also possible to save some typing with dict:

t.first_name = dict(type="char", length=30)
Christon DeWan 12 years, 6 months ago  # | flag

Save even more typing by implementing __getattr__ instead:

from contextlib import contextmanager

class Table(object):
    def __init__(self,table_name):
        self.table_name = table_name
        self.fields = {}
    def __getattr__(self,name):
        def f(**kvs):
            self.fields[name] = kvs
        return f
    def execute(self):
        print "Creating table %s with fields %s"%(self.table_name,self.fields)

@contextmanager
def create_table(table_name):
    table = Table(table_name)
    yield table
    table.execute()


with create_table('cookies') as t:
    t.kind(type='char',length=30)
    t.yumminess(type='char',length=30)
    t.servings(type='int')

You could also explicitly define the keyword args available to the column definitions for extra safety.