0

Is it possible to use with statement in Python anonymous functions? For example, I have a function that writes 1 to a file:

def write_one(filename):
    with open(filename, 'wt') as fp:
        fp.write('1')

But this function is to be organized in a dict:

my_functions = {
    ....
}

Obviously I can write this statement to add this function to the dict:

my_functions['write_one'] = write_one

But the problem is the name write_one still exists in the current scope. How can I introduce an anonymous function without polluting the current namespace?

For simple functions, I can use lambda. For slightly complicated functions, I can return a tuple to execute multiple statements (to be precise, expressions). But I didn't find a way to cleverly use lambda so that it can work with with statements. If this is impossible, where it says so in its documentation?

The solution with a del write_one doesn't look good to me. I don't want this name to be introduced at all in the current namespace.

In a word, what I want is something like this:

my_functions['write_one'] = def(filename):
    with open(filename, 'wt') as fp:
        fp.write('1')

This is kind of awkward with Python's indentation-based rules, I know. But it does its job.

16
  • 5
    No, it is not. lambda expressions can only contain expressions, not statements. Commented Dec 26, 2018 at 20:17
  • @juanpa.arrivillaga Is lambda the only way to construct an anonymous function in Python? I'm talking about anonymous functions not lambda. Commented Dec 26, 2018 at 20:21
  • Yes, it is. I rarely use lambda expressions, only when I'm being super lazy, or for very simple one-offs that I pass to a higher-order function like map Commented Dec 26, 2018 at 20:22
  • @juanpa.arrivillaga So where in the doc it says lambda is the only way to construct an anonymous functions? Commented Dec 26, 2018 at 20:23
  • 1
    Yes. or you could just believe people with experience in the language. Up to you. Commented Dec 26, 2018 at 20:28

2 Answers 2

4

Lambda expressions are quite restricted in what they can do. From the docs

Note that functions created with lambda expressions cannot contain statements or annotations.

Just use a full function definition. If you really want to avoid polluting the namespace, just del the name afterwards.

Or if you simply want to avoid the module namespace from having a bunch of these small functions for code-completion purposes, use _ in the front of the function name.

If you truly want to avoid it, you could use the function constructor and dynamically compile code, etc. Or use some other kind of dynamic code execution, e.g. using eval or exec. But that is almost certainly not worth the trouble. Especially if you can just del the name after you are done using it.

Or perhaps the best approach is to put all these functions in another namespace, like another module.

Sign up to request clarification or add additional context in comments.

4 Comments

By the way, and I by no means endorse this, and it may annoy you slightly, there is a hack around this - using exec. Now that's a recipe for bugs! Or deleting the hard-drive for that matter.
@kabanus sure, I had added these sorts of highly hacky options as edits.
Ah I see now - disagree a bit that a "function in a function" is hacky, but the rest I agree with completely.
@kabanus I didn't mean that, I mean using eval, exec or the function constructor
1

There are not many namespaces in Python - a function is basically the local one. That gives a good hint to a possible solution:

def gen_functions():
    def f1(i):
        print(i)
    def f2(i):
        print(i+1)
    return f1,f2

my_funcs = dict(zip(('a','b'),gen_functions()))
my_funcs['a'](2)
my_funcs['b'](7)
f1(3)

Run this:

>py bla.py
2
8
Traceback (most recent call last):
  File "bla.py", line 11, in <module>
    f1(3)
NameError: name 'f1' is not defined

So you can make arbitrarily complex functions - to hide them from the global namespace you just enclose them in another function.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.