I have following code
fset = [ obj for name,obj in inspect.getmembers(sys.modules[__name__]) if inspect.isfunction(obj) ]
def func(num):
pass
if __name__ == "__main__":
print(fset)
prints
[]
however this
def func(num):
pass
fset = [ obj for name,obj in inspect.getmembers(sys.modules[__name__]) if inspect.isfunction(obj) ]
if __name__ == "__main__":
print(fset)
prints
[<function func at 0x7f35c29383b0>]
so how can fset be list of all functions in current module where fset is defined at the top of all functions ?
EDIT 1: What I am trying to do is
def testall(arg):
return any(f(arg) for f in testfunctions)
def test1(arg):
#code here
# may call testall but wont call anyother test*
def test2(arg):
#code here
# may call testall but wont call anyother test*
More test function may be added in the future. So thats the reason of fset/testfunctions
We can list down all the functions present in a Python module by simply using the dir() method in the Python shell or in the command prompt shell.
dir() is a built-in function that also returns the list of all attributes and functions in a module.
The dir() functions shows all members a module has.
The __module__ property is intended for retrieving the module where the function was defined, either to read the source code or sometimes to re-import it in a script.
EDIT 1: What I am trying to do is
def testall(arg):
return any(f(arg) for f in testfunctions)
def test1(arg):
#code here
# may call testall but wont call anyother test*
This works just fine:
def testall(arg):
testfunctions = [obj for name,obj in inspect.getmembers(sys.modules[__name__])
if (inspect.isfunction(obj) and
name.startwith('test') and name != 'testall')]
return any(f(arg) for f in testfunctions)
def test1(arg):
#code here
# may call testall but wont call anyother test*
In this case, testfunctions
isn't evaluated until testall
is called, so there's no problem here—by that time, all top-level module code (including the test1
definition) will have been evaluated, so testfunctions
will get all of the top-level functions. (I'm assuming here that testall
or test1
is being called from an if __name__ == '__main__'
block at the bottom of the module, or another script is doing import tests; tests.test1(10)
, or something similar.)
In fact, even if you explicitly named test1
and test2
, there would be no problem:
def testall(arg):
testfunctions = ('test1',)
return any(f(arg) for f in testfunctions)
def test1(arg):
#code here
# may call testall but wont call anyother test*
Again, test1
is already defined by the time you call testall
, so everything is fine.
If you want to understand why this works, you have to understand the stages here.
When you import a module, or run a top-level script, the first stage is compilation (unless there's already a cached .pyc file). The compiler doesn't need to know what value a name has, just whether it's local or global (or a closure cell), and it can already tell that sys
and inspect
and test1
are globals (because you don't assign to them in testall
or in an enclosing scope).
Next, the interpreter executes the compiled bytecode for the top-level module, in order. This includes executing the function definitions. So, testall
becomes a function, then test1
becomes a function, then test2
becomes a function. (A function is really just the appropriate compiled code, with some extra stuff attached, like the global namespace it was defined in.)
Later, when you call the testall
function, the interpreter executes the function. This is when the list comprehension (in the first version) or the global name lookup (in the second) happens. Since the function definitions for test1
and test2
have already been evaluated and bound to global names in the module, everything works.
What if you instead later call test1
, which calls testall
? No problem. The interpreter executes test1
, which has a call to testall
, which is obviously already defined, so the interpreter calls that, and the rest is the same as in the previous paragraph.
So, what if you put a call to testall
or test1
in between the test1
and test2
definitions? In that case, test2
wouldn't have been defined yet, so it would not appear in the list (first version), or would raise a NameError
(second version). But as long as you don't do that, there's no problem. And there's no good reason to do so.
If you're worried about the horrible performance cost of computing testfunctions
every time you call testall
… Well, first, that's a silly worry; how many times are you going to call it? Are your functions really so fast that the time to call and filter getmembers
even shows up on the radar? But if it really is a worry, just cache the value in your favorite of the usual ways—mutable default, privat global, function attribute, …:
def testall(arg, _functions_cache=[]):
if not _functions_cache:
_functions_cache.extend([…])
It can't be. Function definitions are executed in Python. The functions don't exist until their definition is executed. Your fset
variable can't be defined until after the functions are defined.
To exclude any imported functions this works:
import sys
import inspect
[obj for name,obj in inspect.getmembers(sys.modules[__name__])
if (inspect.isfunction(obj) and
name.startswith('test') and
obj.__module__ == __name__)]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With