This question already has answers here:
Creating functions (or lambdas) in a loop (or comprehension)
(6 answers)
Closed 8 years ago.
when working with python, it bothered me that while obj.method() is perfectly fine, method(obj) isn't allowed. So I figured I'd try to write some code to fix that. I came up with the next:
def globalclassfuncs(defobj):
for i in inspect.getmembers(defobj, predicate=inspect.ismethod):
def scope():
var = i[0];
setattr(sys.modules[__name__], i[0], lambda obj, *args: getattr(obj, var)(*args));
scope();
However, there's something weird with this. When I remove def scope(): and scope(), so that it'll run without a function definition in the for loop, or when I change the getattr() function to use i[0] directly instead of through var, somehow all new defined functions point to the last defined function instead of the function they should point to. Why does this behaviour change so much on such small changes in the code?
Seems like a case of late binding closure
Related
This question already has answers here:
Given a function with closure, can I refer back to it's closure scope?
(1 answer)
What exactly is contained within a obj.__closure__?
(4 answers)
Closed 2 years ago.
I would like to know if there is any method to check whether two functions have the same arguments at runtime in python 3.
Basically, I have this function (func) that takes another function and an argument. I want to check the values assigned to args in the lambda function
func(another_func, args):
return lambda(x : another_func(x, args))
It is not feasible to run the code before and check the results because I am implementing a lazy framework. My main goal is to be able to understand what are the arguments of the function because there is one variable argument that I do not care but there is one static that is created before running the function.
##EDIT
I actually solved this problem using the inspect module (getclosure) for those who are interested!
I actually solved this problem using the inspect module (getclosure) for those who are interested!
Extension (Martijn Pieters):
I think you are referring to getclosurevars(). You can also just access function.closure, and access the value of each cell via its cell_contents attribute.
This question already has answers here:
How to get the original variable name of variable passed to a function [duplicate]
(13 answers)
Closed 7 years ago.
I'd like to be able to access the name of a variable that is passed to a function as e.g.
def f(x):
'''Returns name of list/dict variable passed to f'''
return magic(x)
>>a = [1,2,3]
>>print( f(a) )
'a'
>>print( f(2) )
None
I suspect this is possible using Python introspection but I don't know enough to understand the inspect module. (NB I know that the need for a function like magic() is questionable, but it is what I want.)
Actually, this is not possible. In Python names and values are quite separate. Inside f, you have access to the value of x, but it is not possible to find out what other names other functions might have given to that value.
Think of names as being somewhat like pointers in C. If you have a pointer, you can find out what object it points to. But if you have the object, you cannot find out what pointers are pointing to it.
This question already has answers here:
Does it make a difference using self for a temporary variable in a Python method?
(4 answers)
Closed 7 years ago.
Sorry, this is a really basic question, but I am just wondering when it is necessary to prepend self._ to variable declarations within methods? Every time I declare a variable within a method should I declare it with self._ included? Is there any situation where I should not do this?
Which of these methods would be valid for example (for some hypothetical class):
def thing_counter(self, thing):
length_of_thing = len(thing)
return length_of_thing
OR
def thing_counter(self, thing):
self._length_of_thing = len(thing)
return self._length_of_thing
Both work, but which would be strictly correct?
I know that a variable declaration is not really needed here, I am just trying to use a simple example.
Cheers!
Both work equally.
In the first version, length_of_thing will be created inside the function, and the return will return a copy to the caller. length_of_thing itself will not exist anymore after the return.
In the second one, self._length_of_thing will be created, not inside the function, but inside the instance of the class. The result is that it will be visible to all other methods. And the return still returns a copy.
So possibly this version uses a little more memory, as the variable self._length_of_thing remains alive till the instance of the class is destroyed.
This question already has answers here:
Creating functions (or lambdas) in a loop (or comprehension)
(6 answers)
Closed 6 months ago.
in order to automatically generate parameterized tests, I am trying to add methods to a class in by freezing some parameters of an existing method. Here is the piece of Python 3 code
class A:
def f(self, n):
print(n)
params = range(10)
for i in params:
name = 'f{0}'.format(i)
method = lambda self: A.f(self, i)
setattr(A, name, method)
However, the following lines then produce rather disappointing output
a = A()
a.f0()
prints "9" (instead of "0"). I must be doing something wrong, but I can't see what. Can you help ?
Thanks a lot
Edit: this question is indeed a duplicate. I would like to acknowledge the quality of all comments, which go much deeper than the raw answer.
Try
method = lambda self, i=i: A.f(self, i)
because otherwise when you call the method i's value may have changed
The best way to "freeze" parameters in Python is to use functools.partial. It's roughly equivalent to warwaruk's lambda version, but if you have a function with lots of arguments yet only want to freeze one or two of them (or if you only know certain arguments and don't care about the rest) using partial is more elegant as you only specify the arguments you want to freeze rather than having to repeat the whole function signature in the lambda.
An example for your program:
class A:
def f(self, n):
print(n)
from functools import partial
for i in range(10): # params
setattr(A, 'f{0}'.format(i), partial(A.f, n=i))
Depending on which version of Python 3 you're using, you may not need to include the 0 in the string format placeholder; starting with 3.1, iirc, it should be automatically substituted.
This question already has answers here:
Local variables in nested functions
(4 answers)
Closed 9 years ago.
I'm looking into generating a Python class dynamically from data.
(The purpose is to let users specify some software tests in a simple file, without knowing any Python).
I have run into an effect I did not expect;
as a toy example to quickly check that I can create methods according to a naming scheme I did the following:
import unittest
attrdict = {}
for i in range(3):
attrdict["test%s"%i]= types.MethodType(lambda self: i)
attrdict["runTest"]=lambda self: [eval("self.test%s()"%i) for i in range(3)]
dynTC = type('dynTC', (unittest.TestCase,), attrdict )
now when I execute
dynTC().runTest()
... I would expect
[0,1,2]
as output, but the actual result is
[2,2,2]
I would expect the lambda definitions to bind a deep copy of the loop index, since it is just a number rather than a more complex structure, but clearly there's stuff going on here that I don't understand.
I have a feeling this may be a common 'gotcha' for new Python programmers, but all the terms I can think of to describe the problem are so generic that my searches only return a deluge of unrelated answers.
Could you please explain to me what is happening here instead of what I expected, and preferably also what I should have done to create the desired effect of several /different/ methods.
The problem is with this line...
attrdict["test%s"%i]= types.MethodType(lambda self: i)
When you define a lambda that references a variable which isn't one of its arguments, the variable will be resolved from the scope in which the lambda was defined at the point when it's actually called, so you'll always get whatever the current value of i is, rather than the value of i at the point when you defined the lambda.
In your case, the value of i will end up as 2 after the for i in range(3) loop completes, so you need to create a closure to bind i to a specific value when creating the lambda, by changing the line to...
attrdict["test%s"%i]= types.MethodType(lambda self, i=i: i)