Alex Rivera | Logout

Python equivalent of PHP's compact() and extract()

Asked 2009-04-23T22:21:29.473
14

compact() and extract() are functions in PHP I find tremendously handy. compact() takes a list of names in the symbol table and creates a hashtable with just their values. extract does the opposite. e.g.,

$foo = 'what';
$bar = 'ever';
$a = compact('foo', 'bar');
$a['foo']
# what
$a['baz'] = 'another'
extract(a)
$baz
# another

Is there a way to do the same in Python? I've looked all around and the closest I've come is this thread, which seems to frown on it.

I know about locals(), globals() and vars(), but how can I handily select just a subset of their values?

Does Python have something even better that obviates the need for this?

Edit
Report

2 Answers

10

I'm afraid there are no equivalents in Python. To some extent, you can simulate their effect using (and passing) locals:

>>> def compact(locals, *keys):
...     return dict((k, locals[k]) for k in keys)
...
>>> a = 10
>>> b = 2
>>> compact(locals(), 'a', 'b')
{'a': 10, 'b': 2}

>>> def extract(locals, d):
...     for k, v in d.items():
...         locals[k] = v
...
>>> extract(locals(), {'a': 'foo', 'b': 'bar'}
>>> a
'foo'
>>> b
'bar'

Nevertheless, I don't think these functions are "tremendously handy". Dynamic global/local variables are evil and error-prone -- PHP guys learned that when they discouraged register_globals. From my experience, few experienced PHP programmers or major frameworks use compact() or extract().

In Python, explicit is better than implicit:

a = 1
b = 2
# compact
c = dict(a=a, b=b)

# extract
a, b = d['a'], d['b']
answered 2009-04-23T22:40:07.977
10

Is it worth pointing out that extract() (and to a lesser extent, compact()) is one of the most "evil" features of PHP (along with register_globals and eval), and should be avoided?

extract makes it much harder to determine where a variable was defined. When it is harder to trace a variable back to where it was defined, it's harder to check for common security problems like using uninitialized variables, or unfiltered variables which originated from user input.

compact is not as bad, but if used badly can still make it more difficult than it would otherwise be to see where an array member gets set from a variable.

The equivalent of extract() in many other languages is the with keyword. Python now has a with keyword, though it works a bit differently, making it not quite like extract(). However, in other languages such as Javascript, the with keyword also has a poor reputation.

I think the best advice would be to think differently - instead of trying to emulate a bad feature of PHP, think of other ways to do what you want to do with concise and readable code.

answered 2009-04-24T05:57:58.750

Your Answer