Setting a variable to a parameter value inline when calling a function - python

In other languages, like Java, you can do something like this:
String path;
if (exists(path = "/some/path"))
my_path = path;
the point being that path is being set as part of specifying a parameter to a method call. I know that this doesn't work in Python. It is something that I've always wished Python had.
Is there any way to accomplish this in Python? What I mean here by "accomplish" is to be able to write both the call to exists and the assignment to path, as a single statement with no prior supporting code being necessary.
I'll be OK with it if a way of doing this requires the use of an additional call to a function or method, including anything I might write myself. I spent a little time trying to come up with such a module, but failed to come up with anything that was less ugly than just doing the assignment before calling the function.
UPDATE: #BrokenBenchmark's answer is perfect if one can assume Python 3.8 or better. Unfortunately, I can't yet do that, so I'm still searching for a solution to this problem that will work with Python 3.7 and earlier.

Yes, you can use the walrus operator if you're using Python 3.8 or above:
import os
if os.path.isdir((path := "/some/path")):
my_path = path

I've come up with something that has some issues, but does technically get me where I was looking to be. Maybe someone else will have ideas for improving this to make it fully cool. Here's what I have:
# In a utility module somewhere
def v(varname, arg=None):
if arg is not None:
if not hasattr(v, 'vals'):
v.vals = {}
v.vals[varname] = arg
return v.vals[varname]
# At point of use
if os.path.exists(v('path1', os.path.expanduser('~/.harmony/mnt/fetch_devqa'))):
fetch_devqa_path = v('path1')
As you can see, this fits my requirement of no extra lines of code. The "variable" involved, path1 in this example, is stored on the function that implements all of this, on a per-variable-name basis.
One can question if this is concise and readable enough to be worth the bother. For me, the verdict is still out. If not for the need to call the v() function a second time, I think I'd be good with it structurally.
The only functional problem I see with this is that it isn't thread-safe. Two copies of the code could run concurrently and run into a race condition between the two calls to v(). The same problem is greatly magnified if one fails to choose unique variable names every time this is used. That's probably the deal killer here.
Can anyone see how to use this to get to a similar solution without the drawbacks?

Related

Defining a function in Python (There's a big catch) [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
So a few days ago we got this exercise where we need to make a function that takes two lists as input and calculates the difference of their averages.
Sounds simple enough, but there are a few catches:
the entire thing needs to be one line long
you can absolutely NOT use ':'
They encouraged us to use 'import', 'help()' and 'dir()'.
The thing is that I know how to make it only one line long, but the no ':' is really annoying.
The way I see it, I first need to define a function (without code) then change it's 'func_code' attr.
Any ideas on how can I do it?
And how do the params fit into this?
Any answer is appreciated!!!
Edit: thanks for all the answers and the creative minds that said char(58) is the solution, it is really creative and I haven't thought of that solution but it's not allowed since you are using ':' even though not directly.
No : means you can't use lambda. That leaves higher-order functions or eval trickery.
eval('lambda a,b{}sum(a)/len(a)-sum(b)/len(b)'.format(chr(58)))
This meets the letter of the law, but violates its spirit.
Unfortunately, without a function composition function, higher-order functions don't work very well. Implementing one without : is tricky.
Here's what should be a fairly self-contained solution, using a pickled code object. I've created it in Python 3.6, and the specific bytestring is very likely to be version specific, but you can create your own version pretty easily using the expanded code below. Anyway, here's the oneliner:
f = __import__('types').FunctionType(__import__('pickle').loads(b'\x80\x03cipykernel.codeutil\ncode_ctor\nq\x00(K\x02K\x00K\x02K\x04KCC t\x00|\x00\x83\x01t\x01|\x00\x83\x01\x1b\x00t\x00|\x01\x83\x01t\x01|\x01\x83\x01\x1b\x00\x18\x00S\x00q\x01N\x85q\x02X\x03\x00\x00\x00sumq\x03X\x03\x00\x00\x00lenq\x04\x86q\x05X\x01\x00\x00\x00aq\x06X\x01\x00\x00\x00bq\x07\x86q\x08X\x1e\x00\x00\x00<ipython-input-1-384cc87bd499>q\tX\x16\x00\x00\x00difference_of_averagesq\nK\x01C\x02\x00\x01q\x0b))tq\x0cRq\r.'), globals())
Here's what I'm doing without the one-line shenanigans:
import types # replace these import statements with calls to __import__ in the oneliner
import pickle
def difference_of_averages(a, b):
return sum(a)/len(a) - sum(b)/len(b)
payload = pickle.dumps(difference_of_averages.__code__) # embed as a literal in the oneliner
f = types.FunctionType(pickle.loads(payload), globals())
Hmm, having tried this on the few different interpreters I have at hand, it looks like my pickle string includes some nonsense from the IPython interpreter I created it in. If you get errors using my string, I'd suggest just building your own (which, if it contains any junk, will at least be junk compatible with your environment).
Not using ':' is tricky because you normally use it to define the function body, like this:
def average(number_list):
return sum(number_list) / len(number_list)
However, I know of one way to define a function that doesn't require require writing a block for its body: You can assign a lambda function (or even an already-defined function) to a function you want to define, simply by using the equal sign (=). For example, if you want to create an average() function, you might write:
average = lambda number_list: sum(number_list) / len(number_list)
average might look like a variable, but you can use it as a function. It simply calls the lambda function that takes a number_list as input and returns the average value of the number_list. You can call it like this:
value = average([10, 11, 12]) # sets value to 11
Now, lambda functions can only have one line. But that's not really a problem for you, since your task requires you to only use one line.
Do you understand what to do now? Your exercise requires you to find the average of two lists, so you might consider using a lambda function that takes two inputs (instead of just one, like in the example I gave above). Also bear in mind that you need to return the difference, and if the difference should always be positive, consider using Python's abs() function somewhere in your code.
Edit: Well, gilch's response made me realize that I can't use lambda because even they use :. So apparently you can't use my advice. It's still good to know about lambda functions, though.
The fact that you are encouraged to use import makes me wonder if it's okay for you to use an already-defined function from some module to define your own function. Kind of like this:
import math; average = math.difference_of_averages
However, that depends on you being able to find a (probably standard) function that does exactly what you want. (I've briefly checked the math and numpy modules, and haven't found anything that matches yet.)
And maybe this means that you can create a module and define it anyway you like. The module is in its own world, so it's not constrained to the rules of your exercise.
Then again, maybe not.
So unless you want to "sneak-in" a : in an eval statement (as gilch suggested), like this:
average = eval('lambda number_list' + chr(58) + ' sum(number_list) / len(number_list)')
there's no way I know of off hand to avoidi using :.

Are there any dangers associated with using kwarg=kwarg in Python functions?

I've sometimes seen code with kwarg=kwarg in one of the functions as shown below:
def func1(foo, kwarg):
return(foo+kwarg)
def func2(bar, kwarg):
return(func1(bar*2, kwarg=kwarg))
print(func2(4,5))
I've normally tried to avoid this notation (e.g. by using kwarg1=kwarg2) in order to avoid any possible bugs, but is this actually necessary?
There's nothing wrong with it - in this case kwarg is just a variable name - it's not reserved. There may be a bit of confusion with it though, since def func(**kwargs): is the common syntax for creating a dictionary of all the "key word arguments" that are passed into the function. Since you're not doing that here, using such a similar name is unnecessarily confusing. Although it's not clear you're talking about using that exact name, so maybe this is just an issue with the example.
But broadly speaking, passing something=something is fairly common practice. You'll see it in lots of places, for example if you're iterating through a color pallette in Matplotlib, you might pass color=color into plot, or if you're building a list of headers in Pandas you might pass coloumns=columns into DataFrame.
Bottom line is it should be clear. If it is, it's good. If it's not, it isn't.

Does python remember the result of an operation if it appears twice in the code?

I've been developing a sudoku solver in Python and the following question came up while trying to improve performance:
Does python remember the result of a calculation if the same calculation has to be performed multiple times throughout the code? Example: compare the following 2 bits of code:
if get_single(foo, bar) is not None:
position = get_single(foo, bar)
single = get_single(foo, bar)
if single is not None:
position = single
Are these 2 pieces of code equal in performance or does the second piece perform faster because the calculation is only performed once?
No, Python does not remember function calls or other calculations automatically. In general, it would be very bad if it did—imagine if every call to, say, random.randrange(6) returned the same value as the first call.
However, it's not hard to explicitly make it remember calls for specific functions where it's useful. This is usually called "memoization".
See the lru_cache decorator in the docs, for a nice example built into the stdlib.* All you have to do to make it remember every call to get_single(foo, bar) is change the definition of get_single like this;
#functools.lru_cache(maxsize=None)
def get_single(foo, bar):
# etc.
Or, if get_single is someone else's code that you're importing and can't touch, you can just wrap it:
get_single = functools.lru_cache(maxsize=None)(othermod.get_single)
… and then call your wrapper instead of the module's version.
* Note that lru_cache was added in Python 3.2. If you're using 2.7 (or, for some reason, 3.0-3.1), you can install the backport from PyPI, or find any of dozens of other memoizing caches on PyPI or ActiveState—or even, noticing that the functools docs link to the source, like many other stdlib modules meant to also serve as example code, copy the source to your own project. Although, IIRC, the 3.2 code needs a small change to work with 2.7 because it relies on nonlocal to hide its internals.
That being said, even if you know get_single is memoized, it's still not very good style to call it twice. If you only need to do this once, just write the three lines of code. If you need to do it repeatedly, write a wrapper function that wraps up those three lines or code, and then calling that function will be shorter than even the two-line version.

Analogue of devar in Python

When writing Python code, I often find myself wanting to get behavior similar to Lisp's defvar. Basically, if some variable doesn't exist, I want to create it and assign a particular value to it. Otherwise, I don't want to do anything, and in particular, I don't want to override the variable's current value.
I looked around online and found this suggestion:
try:
some_variable
except NameError:
some_variable = some_expensive_computation()
I've been using it and it works fine. However, to me this has the look of code that's not paradigmatically correct. The code is four lines, instead of the 1 that would be required in Lisp, and it requires exception handling to deal with something that's not "exceptional."
The context is that I'm doing interactively development. I'm executing my Python code file frequently, as I improve it, and I don't want to run some_expensive_computation() each time I do so. I could arrange to run some_expensive_computation() by hand every time I start a new Python interpreter, but I'd rather do something automated, particularly so that my code can be run non-interactively. How would a season Python programmer achieve this?
I'm using WinXP with SP3, Python 2.7.5 via Anaconda 1.6.2 (32-bit), and running inside Spyder.
It's generally a bad idea to rely on the existence or not of a variable having meaning. Instead, use a sentinel value to indicate that a variable is not set to an appropriate value. None is a common choice for this kind of sentinel, though it may not be appropriate if that is a possible output of your expensive computation.
So, rather than your current code, do something like this:
# early on in the program
some_variable = None
# later:
if some_variable is None:
some_variable = some_expensive_computation()
# use some_variable here
Or, a version where None could be a significant value:
_sentinel = object()
some_variable = _sentinel # this means it doesn't have a meaningful value
# later
if some_variable is _sentinel:
some_variable = some_expensive_computation()
It is hard to tell which is of greater concern to you, specific language features or a persistent session. Since you say:
The context is that I'm doing interactively development. I'm executing my Python code file frequently, as I improve it, and I don't want to run some_expensive_computation() each time I do so.
You may find that IPython provides a persistent, interactive environment that is pleasing to you.
Instead of writing Lisp in Python, just think about what you're trying to do. You want to avoid calling an expensive function twice and having it run two times. You can write your function do to that:
def f(x):
if x in cache:
return cache[x]
result = ...
cache[x] = result
return result
Or make use of Python's decorators and just decorate the function with another function that takes care of the caching for you. Python 3.3 comes with functools.lru_cache, which does just that:
import functools
#functools.lru_cache()
def f(x):
return ...
There are quite a few memoization libraries in the PyPi for 2.7.
For the use case you give, guarding with a try ... except seems like a good way to go about it: Your code is depending on leftover variables from a previous execution of your script.
But I agree that it's not a nice implementation of the concept "here's a default value, use it unless the variable is already set". Python does not directly support this for variables, but it does have a default-setter for dictionary keys:
myvalues = dict()
myvalues.setdefault("some_variable", 42)
print some_variable # prints 42
The first argument of setdefault must be a string containing the name of the variable to be defined.
If you had a complicated system of settings and defaults (like emacs does), you'd probably keep the system settings in their own dictionary, so this is all you need. In your case, you could also use setdefault directly on global variables (only), with the help of the built-in function globals() which returns a modifiable dictionary:
globals().setdefault("some_variable", 42)
But I would recommend using a dictionary for your persistent variables (you can use the try... except method to create it conditionally). It keeps things clean and it seems more... pythonic somehow.
Let me try to summarize what I've learned here:
Using exception handling for flow control is fine in Python. I could do it once to set up a dict in which I can store what ever I want.
There are libraries and language features that are designed for some form of persistence; these can provide "high road" solutions for some applications. The shelve module is an obvious candidate here, but I would construe "some form of persistence" broadly enough to include #Blender's suggest to use memoization.

Hot swapping python code (duck type functions?)

I've been thinking about this far too long and haven't gotten any idea, maybe some of you can help.
I have a folder of python scripts, all of which have the same surrounding body (literally, I generated it from a shell script), but have one chunk that's different than all of them. In other words:
Top piece of code (always the same)
Middle piece of code (changes from file to file)
Bottom piece of code (always the same)
And I realized today that this is a bad idea, for example, if I want to change something from the top or bottom sections, I need to write a shell script to do it. (Not that that's hard, it just seems like it's very bad code wise).
So what I want to do, is have one outer python script that is like this:
Top piece of code
Dynamic function that calls the middle piece of code (based on a parameter)
Bottom piece of code
And then every other python file in the folder can simply be the middle piece of code. However, normal module wouldn't work here (unless I'm mistaken), because I would get the code I need to execute from the arguement, which would be a string, and thus I wouldn't know which function to run until runtime.
So I thought up two more solutions:
I could write up a bunch of if statements, one to run each script based on a certain parameter. I rejected this, as it's even worse than the previous design.
I could use:
os.command(sys.argv[0] scriptName.py)
which would run the script, but calling python to call python doesn't seem very elegant to me.
So does anyone have any other ideas? Thank you.
If you know the name of the function as a string and the name of module as a string, then you can do
mod = __import__(module_name)
fn = getattr(mod, fn_name)
fn()
Another possible solution is to have each of your repetitive files import the functionality from the main file
from topAndBottom import top, bottom
top()
# do middle stuff
bottom()
In addition to the several answers already posted, consider the Template Method design pattern: make an abstract class such as
class Base(object):
def top(self): ...
def bottom(self): ...
def middle(self): raise NotImplementedError
def doit(self):
self.top()
self.middle()
self.bottom()
Every pluggable module then makes a class which inherits from this Base and must override middle with the relevant code.
Perhaps not warranted for this simple case (you do still have to import the right module in order to instantiate its class and call doit on it), but still worth keeping in mind (together with its many Pythonic variations, which I have amply explained in many tech talks now available on youtube) for cases where the number or complexity of "pluggable pieces" keeps growing -- Template Method (despite its horrid name;-) is a solid, well-proven and highly scalable pattern [[sometimes a tad too rigid, but that's exactly what I address in those many tech talks -- and that problem doesn't apply to this specific use case]].
However, normal module wouldn't work here (unless I'm mistaken), because I would get the code I need to execute from the arguement, which would be a string, and thus I wouldn't know which function to run until runtime.
It will work just fine - use __import__ builtin or, if you have very complex layout, imp module to import your script. And then you can get the function by module.__dict__[funcname] for example.
Importing a module (as explained in other answers) is definitely the cleaner way to do this, but if for some reason that doesn't work, as long as you're not doing anything too weird you can use exec. It basically runs the content of another file as if it were included in the current file at the point where exec is called. It's the closest thing Python has to a source statement of the kind included in many shells. As a bare minimum, something like this should work:
exec(open(filename).read(None))
How about this?
function do_thing_one():
pass
function do_thing_two():
pass
dispatch = { "one" : do_thing_one,
"two" : do_thing_two,
}
# do something to get your string from the command line (optparse, argv, whatever)
# and put it in variable "mystring"
# do top thing
f = dispatch[mystring]
f()
# do bottom thing

Categories

Resources