Python Equivalent of PHP's Compact() and Extract()

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

It's not very Pythonic, but if you really must, you can implement compact() like this:

import inspect

def compact(*names):
caller = inspect.stack()[1][0] # caller of compact()
vars = {}
for n in names:
if n in caller.f_locals:
vars[n] = caller.f_locals[n]
elif n in caller.f_globals:
vars[n] = caller.f_globals[n]
return vars

It used to be possible to implement extract() like this, but in modern Python interpreters this doesn't appear to work anymore (not that it was ever "supposed" to work, really, but there were quirks of the implementation in 2009 that let you get away with it):

def extract(vars):
caller = inspect.stack()[1][0] # caller of extract()
for n, v in vars.items():
caller.f_locals[n] = v # NEVER DO THIS - not guaranteed to work

If you really feel you have a need to use these functions, you're probably doing something the wrong way. It seems to run against Python's philosophy on at least three counts: "explicit is better than implicit", "simple is better than complex", "if the implementation is hard to explain, it's a bad idea", maybe more (and really, if you have enough experience in Python you know that stuff like this just isn't done). I could see it being useful for a debugger or post-mortem analysis, or perhaps for some sort of very general framework that frequently needs to create variables with dynamically chosen names and values, but it's a stretch.

It there an equivalent to PHP's extract in Python?

One generally uses locals() to achieve this result, but the exact functionality is up to you.

>>> print apple
Traceback (most recent call last):
File "<stdin>", line 1, in ?
NameError: name 'apple' is not defined
>>> print banana
Traceback (most recent call last):
File "<stdin>", line 1, in ?
NameError: name 'banana' is not defined

>>> variables = {"apple" : "a rigid, juicy fruit", "banana" : "a soft, fleshy fruit"}
>>> for variable,value in variables.iteritems():
... locals()[variable] = value
...
>>> print apple
a rigid, juicy fruit
>>> print banana
a soft, fleshy fruit

EDIT

Thanks to everyone who has diligently commented on the badness of this approach. I wholeheartedly agree that THIS IS A BAD APPROACH, and it deserves to be mentioned in the actual response for anyone who stumbles across this page. (Never underestimate that; I saw this technique in a code snippet somewhere. I can see why in that particular case it was harmless, but I know I can't go around encouraging bad methodology just because there are situations in which it won't break.)

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

It's not very Pythonic, but if you really must, you can implement compact() like this:

import inspect

def compact(*names):
caller = inspect.stack()[1][0] # caller of compact()
vars = {}
for n in names:
if n in caller.f_locals:
vars[n] = caller.f_locals[n]
elif n in caller.f_globals:
vars[n] = caller.f_globals[n]
return vars

It used to be possible to implement extract() like this, but in modern Python interpreters this doesn't appear to work anymore (not that it was ever "supposed" to work, really, but there were quirks of the implementation in 2009 that let you get away with it):

def extract(vars):
caller = inspect.stack()[1][0] # caller of extract()
for n, v in vars.items():
caller.f_locals[n] = v # NEVER DO THIS - not guaranteed to work

If you really feel you have a need to use these functions, you're probably doing something the wrong way. It seems to run against Python's philosophy on at least three counts: "explicit is better than implicit", "simple is better than complex", "if the implementation is hard to explain, it's a bad idea", maybe more (and really, if you have enough experience in Python you know that stuff like this just isn't done). I could see it being useful for a debugger or post-mortem analysis, or perhaps for some sort of very general framework that frequently needs to create variables with dynamically chosen names and values, but it's a stretch.

very unsafe behavior of extract() and compact() function with non standard variables, it is a bug or a feature ;)?

PHP is open source. Feel free to contribute a patch to fix this behavior if you feel it should be fixed and/or join the PHP mailing list to discuss this topic with other PHP developers.

Simply ranting is pointless, especially here.

extract an array into multiple comma separated variables

Without naming a value you can't simply define it back into local variable table.

For example:

$vars = [1];

Cannot become $This = 1;

You would need to do:

$vars = ['This' => 1];

Here is an example of how you can group compact() variables which you later want to extract():

<?php

$This = 1;
$That = 2;
$Bla = 3;
$Foo = 4;
$Bar = 5;

$vars = ['This', 'That', 'Bla', 'Foo', 'Bar'];

$vars = compact(...$vars);

/*
Array
(
[This] => 1
[That] => 2
[Bla] => 3
[Foo] => 4
[Bar] => 5
)
*/

$vars = extract($vars);

/*
$This = 1;
$That = 2;
$Bla = 3;
$Foo = 4;
$Bar = 5;
*/

Fastest way to add many parameters with their names as keys to a dict programmatically

Simple Method using locals:

def create_results(age, sex, marital_status = "single"):
return {k:v for k, v in locals().items() if not k.startswith('__')}

res = create_results(34, "male")

print(res)

Output:

{'marital_status': 'single', 'sex': 'male', 'age': 34}


Related Topics



Leave a reply



Submit