Variable interpolation in Python [duplicate] - python

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Unpythonic way of printing variables in Python?
In PHP one can write:
$fruit = 'Pear';
print("Hey, $fruit!");
But in Python it's:
fruit = 'Pear'
print("Hey, {0}!".format(fruit))
Is there a way for me to interpolate variables in strings instead? And if not, how is this more pythonic?
Bonus points for anyone who gets the reference

The closest you can get to the PHP behaviour is and still maintaining your Python-zen is:
print "Hey", fruit, "!"
print will insert spaces at every comma.
The more common Python idiom is:
print "Hey %s!" % fruit
If you have tons of arguments and want to name them, you can use a dict:
print "Hey %(crowd)s! Would you like some %(fruit)s?" % { 'crowd': 'World', 'fruit': 'Pear' }

The way you're doing it now is a pythonic way to do it. You can also use the locals dictionary. Like so:
>>> fruit = 'Pear'
>>> print("Hey, {fruit}".format(**locals()))
Hey, Pear
Now that doesn't look very pythonic, but it's the only way to achieve the same affect you have in your PHP formatting. I'd just stick to the way you're doing it.

A slight adaptation from the NamespaceFormatter example in PEP-3101:
import string
class NamespaceFormatter(string.Formatter):
def __init__(self, namespace={}):
super(NamespaceFormatter, self).__init__()
self.namespace = namespace
def get_value(self, key, args, kwds):
if isinstance(key, str):
try:
# Check explicitly passed arguments first
return kwds[key]
except KeyError:
return self.namespace[key]
else:
super(NamespaceFormatter, self).get_value(key, args, kwds)
fmt = NamespaceFormatter(globals())
fruit = 'Pear'
print fmt.format('Hey, {fruit}!')
for:
Hey, Pear!

Something like this should work:
"%(fruit)s" % locals()

Don't do it. It is unpythonic. As example, when you add translations to your app, you can't longer control which variables are used unless you check all the translations files yourself.
As example, if you change a local variable, you'll have to change it in all translated strings too.

Related

define a dict of variables in a for loop : hello = var('hello')

var = {'hello': 'world', 'good': 'day', 'see': 'you'}
Function:
def func(key):
return newfunc(var[key])
I would like to get something like this: hello = func('hello') = newfunc('world').
varlist = list(var.keys())
for i, variab in enumerate(varlist):
varname = variab
variab = func(varname)
But the problem at last the variables are not defined because the variable variab is overwritten when the next iteration starts. So do I have other ways to code a for loop to define all the variables in the dict?
I know I can keep writing hello = func('hello') and other variables every line but I would like to know if another method is possible.
You may find this article to be a worthwhile read: http://stupidpythonideas.blogspot.com/2013/05/why-you-dont-want-to-dynamically-create.html/
The short answer to the problem is that when you do:
variab = func(varname)
You aren't defining a new variable, you are just defining the value stored in the variable. Variab is static. The name isnt changing. To define a static variable, you use the syntax
globlas()[variablename] = variablevalue
And while this is possible, it begs the question of why? There is pretty much no need to create variables dynamically in this way, and there's a reason why you don't generally see this pattern in programming. The solution? Use a data structure to solve the problem properly.
The article suggests dictionaries, but depending on your data structure you can use classes as well. It depends on the problem you are trying to accomplish.
If you must use dynamically created global variables I would strongly recommend getting past the new to Python stage before doing so. Again, the current code patterns and data structures exist for a reason, and I would discourage willingly avoiding them in favor of a workaround style solution.
Dynamically creating variables can be done, but it is not wise. Maintenance is a nightmare. It would be better to store the functions in a dictionary with the key value being what the dynamically created variable would have been. This should give you an idea of how it can be done:
#!/usr/bin/python
h = {'hello': 'world', 'good': 'day', 'see': 'you' }
def func(v):
def newfunc():
return v
return newfunc
for k,v in h.items():
h[k] = func(v)
a = h['hello']()
b = h['good']()
c = h['see']()
print("a = {}".format(a))
print("b = {}".format(b))
print("c = {}".format(c))
First of all, are those values callable functions or just string values?
If they are some callable functions, something like:
a = {'hello': hello, 'world': world}
It is simple and straight forward:
A = {'hello': hello, 'world': world}
def foo(var):
callback = A.get(var, None)
# You cancheck and raise when the value
# is not a method.
if not callable(callback):
raise
return callback
foo('hello')
You can put the variable, fn pairs in a dict.
Also some comments:
you don't use the index i in the for loop so there is no point in using enumerate.
there is no point renaming variab to varname. If you want to use this name then just use it from the beginning.
you can iterate the dict_keys so there is no need for the varlist = list(var.keys()) line, you can just use for variab in var.keys()...
... actually you don't even need the var.keys(). for key in dictionary iterates through the keys of the dictionary, so you can just use for variab in var.
So something like this would work:
fn_dict = {}
for varname in var:
fn_dict[varname] = func(varname)
At the end of the loop you will have the fn_dict populated with the key, function pairs you want.

How to pass in a dictionary with additional elements in python?

I have a dictionary:
big_dict = {1:"1",
2:"2",
...
1000:"1000"}
(Note: My dictionary isn't actually numbers to strings)
I am passing this dictionary into a function that calls for it. I use the dictionary often for different functions. However, on occasion I want to send in big_dict with an extra key:item pair such that the dictionary I want to send in would be equivalent to:
big_dict[1001]="1001"
But I don't want to actually add the value to the dictionary. I could make a copy of the dictionary and add it there, but I'd like to avoid the memory + CPU cycles this would consume.
The code I currently have is:
big_dict[1001]="1001"
function_that_uses_dict(big_dict)
del big_dict[1001]
While this works, it seems rather kludgy.
If this were a string I'd do:
function_that_uses_string(myString + 'what I want to add on')
Is there any equivalent way of doing this with a dictionary?
As pointed out by Veedrac in his answer, this problem has already been solved in Python 3.3+ in the form of the ChainMap class:
function_that_uses_dict(ChainMap({1001 : "1001"}, big_dict))
If you don't have Python 3.3 you should use a backport, and if for some reason you don't want to, then below you can see how to implement it by yourself :)
You can create a wrapper, similarly to this:
class DictAdditionalValueWrapper:
def __init__(self, baseDict, specialKey, specialValue):
self.baseDict = baseDict
self.specialKey = specialKey
self.specialValue = specialValue
def __getitem__(self, key):
if key == self.specialKey:
return self.specialValue
return self.baseDict[key]
# ...
You need to supply all other dict method of course, or use the UserDict as a base class, which should simplify this.
and then use it like this:
function_that_uses_dict(DictAdditionalValueWrapper(big_dict, 1001, "1001"))
This can be easily extended to a whole additional dictionary of "special" keys and values, not just single additional element.
You can also extend this approach to reach something similar as in your string example:
class AdditionalKeyValuePair:
def __init__(self, specialKey, specialValue):
self.specialKey = specialKey
self.specialValue = specialValue
def __add__(self, d):
if not isinstance(d, dict):
raise Exception("Not a dict in AdditionalKeyValuePair")
return DictAdditionalValueWrapper(d, self.specialKey, self.specialValue)
and use it like this:
function_that_uses_dict(AdditionalKeyValuePair(1001, "1001") + big_dict)
If you're on 3.3+, just use ChainMap. Otherwise use a backport.
new_dict = ChainMap({1001: "1001"}, old_dict)
You can add the extra key-value pair leaving original dictionary as such like this:
>>> def function_that_uses_bdict(big_dict):
... print big_dict[1001]
...
>>> dct = {1:'1', 2:'2'}
>>> function_that_uses_bdict(dict(dct.items()+[(1001,'1001')]))
1001
>>> dct
{1: '1', 2: '2'} # original unchanged
This is a bit annoying too, but you could just have the function take two parameters, one of them being big_dict, and another being a temporary dictionary, created just for the function (so something like fxn(big_dict, {1001,'1001'}) ). Then you could access both dictionaries without changing your first one, and without copying big_dict.

Set variables from variables?

I've got many, many strings, all formatted like this: "lot1", "lot2", "lot3"... What I'd like to do is use a function argument to determine which variable to use. Here's a pseudoexample:
def printlot(someInt):
print lot%i % (someInt)
Basically, I'd like to use multiple strings to form the name of another string to act with. This seems simple enough, but I haven't learned how to do it in my two years of Pythoning.
What nneonneo said is correct, but you're really going to want to use a dict explicitly. That is, you want to do this:
lot_data = {'lot1': 10, 'lot2': 20, 'lot3': 30}
i = 2
print lot_data['lot%d' % i]
Instead of this:
lot1 = 10
lot2 = 20
lot3 = 30
i = 2
print vars()['lot%d' % i]
You can access all visible variables as a dictionary using the vars builtin function:
vars()['lot%d' % someInt]
Different scopes can be accessed with globals or locals.
Note, however, that this is generally considered "unpythonic" behaviour. Instead of creating many similarly-named variables, a more Pythonic approach would be to make a list or dictionary.

question about managing values with multiple subvalues in python 3k

I have a question reguarding how I would perform the following task in python.
(I use python 3k)
what I have are several variables which can yield further variables on top of those
and each of those have even more variables
for example:
a generic name would be
item_version_type =
where each part (item, version, and type) refer to different variables(here there are 3 for each)
item = item_a, item_b, item_c
version = range(1,3)
itemtype = itemtype_a, itemtype_b, itemtype_c
simply listing each name and defining it is annoying:
itema_ver1_typea =
itemb_ver1_typea =
itemc_ver1_typea =
itema_ver2_typea =
etc.
etc.
etc.
especially when I have something where one variable is dependent on something else
for example:
if value == True:
version = ver + 1
and to top it off this whole example is rather simply compared to what I'm actually
working with.
one thing I am curious about is using multiple "." type of classes such as:
item.version.type
I know that this can be done
I just can't figure out how to get a class with more than one dot
either that or if anyone can point me to a better method
Thanks for help.
Grouping of data like this can be done in three ways in Python.
First way is tuples:
myvariable = ('Sammalamma', 1, 'Text')
The second way is a dictionary:
myvariable = {'value': 'Sammalamma', 'version': 1, 'type': 'Text'}
And the third way is a class:
class MyClass(object):
def __init__(self, value, version, type):
self.value = value
self.version = version
self.type = type
>>> myvariable = MyClass('Sammalamma', 1, 'Text')
>>> myvariable.value
'Sammalamma'
>>> myvariable.version
1
>>> myvariable.type
'Text'
Which one to use in each case is up to you, although in this case I would claim that the tuple doesn't seem to be the best choice, I would go for a dictionary or a class.
None of this is unique to Python 3, it works in any version of Python.
In addition to #Lennart Regebro's answer if items are immutable:
import collections
Item = collections.namedtuple('Item', 'value version type')
items = [Item(val, 'ver'+ver, t)
for val in 'abc' for ver in '12' for t in ['typea']]
print(items[0])
# -> Item(value='a', version='ver1', type='typea')
item = items[1]
print(item.value, item.type)
# -> b typea
sorry for posting this here instead of the comments but I have no clue how to work the site here.
for clarification
what I need is basically to have be able to get an output of said such as where
I could take a broad area (item) narrow it further (version) and even further (type as in type of item like lets say types are spoon, knife, fork)
or a better description is like arm.left.lower = lower left arm
where I could also have like leg.left.lower
so I could have arm.both.upper to get both left and right upper arms
where a value would be assigned to both.
what I need is to be able to do truth tests etc. and have it return the allowable values
such as
if leg == True
output is --> leg.both.lower, leg.both.upper, leg.left.upper leg.right.upper, etc., etc., etc.
if upper == True
output is --> leg.both.upper, leg.left.upper, etc., etc., etc.
hopefully that helps
Basically I get how to get something like item.version but how do I get something
like item.version.type
I need to have it to be more specific than just item.version
I need to be able to tell if item is this and version is that then type will be x
like
item.version.type
if version == 3:
item.version = spoon.3.bent
#which is different from
if version == 2:
item.version.type = spoon.2.bent

Use a string to call function in Python [duplicate]

This question already has answers here:
Calling a function of a module by using its name (a string)
(18 answers)
Closed 9 years ago.
Some days ago I was searching on the net and I found an interesting article about python dictionaries. It was about using the keys in the dictionary to call a function. In that article the author has defined some functions, and then a dictionary with key exactly same as the function name. Then he could get an input parameter from user and call the same method (something like implementing case break)
After that I realised about the same thing but somehow different. I want to know how I can implement this.
If I have a function:
def fullName( name = "noName", family = "noFamily" ):
return name += family
And now if I have a string like this:
myString = "fullName( name = 'Joe', family = 'Brand' )"
Is there a way to execute this query and get a result: JoeBrand
For example something I remember is that we might give a string to exec() statement and it does it for us. But I’m not sure about this special case, and also I do not know the efficient way in Python. And also I will be so grateful to help me how to handle that functions return value, for example in my case how can I print the full name returned by that function?
This does not exactly answer your question, but maybe it helps nevertheless:
As mentioned, eval should be avoided if possible. A better way imo is to use dictionary unpacking. This is also very dynamic and less error prone.
Example:
def fullName(name = "noName", family = "noFamily"):
return name + family
functionList = {'fullName': fullName}
function = 'fullName'
parameters = {'name': 'Foo', 'family': 'Bar'}
print functionList[function](**parameters)
# prints FooBar
parameters = {'name': 'Foo'}
print functionList[function](**parameters)
# prints FoonoFamily
You could use eval():
myString = "fullName( name = 'Joe', family = 'Brand' )"
result = eval(myString)
Beware though, eval() is considered evil by many people.
I know this question is rather old, but you could do something like this:
argsdict = {'name': 'Joe', 'family': 'Brand'}
globals()['fullName'](**argsdict)
argsdict is a dictionary of argument, globals calls the function using a string, and ** expands the dictionary to a parameter list. Much cleaner than eval. The only trouble lies in splitting up the string. A (very messy) solution:
example = 'fullName(name=\'Joe\',family=\'Brand\')'
# Split at left parenthesis
funcname, argsstr = example.split('(')
# Split the parameters
argsindex = argsstr.split(',')
# Create an empty dictionary
argsdict = dict()
# Remove the closing parenthesis
# Could probably be done better with re...
argsindex[-1] = argsindex[-1].replace(')', '')
for item in argsindex:
# Separate the parameter name and value
argname, argvalue = item.split('=')
# Add it to the dictionary
argsdict.update({argname: argvalue})
# Call our function
globals()[funcname](**argsdict)

Categories