I have a Python file from which I would like to get all functions. I want to pass these functions to another file in order to collect data about these functions.
For Example.py:
class Example:
def method_to_extract(name: str) -> none:
print(name)
I want to extract this method as an object through the file name and pass it as an argument to another function, like
func = magic_method(Example.py) # returns method_to_extract as a callable object
collect_data(func)
Is this possible? So far, I have only been able to extract the names of functions as strings. However, that does not help me, as I want to collect data about the functions like the number of arguments, type hints, and more, and therefore need to be able to access the entire function.
I also tried getting the function using func = getattr(class, funcname), but I wasn't able to pass func as a parameter and extract the data I need.
I can think of 3 solutions, dependant on your particular needs.
Simplest one: don't use classes, just global functions:
# file1.py
def method_to_extract(name):
print(name)
And then in another file just import and use it:
# file2.py
from file2 import method_to_extract
method_to_extract()
In case you especially want to use methods inside of a class, you can make them static with #staticmethod decorator:
# file1.py
class Example:
#staticmethod
def method_to_extract(name):
print(name)
And then in another file just import and use it:
# file2.py
from file2 import Example
Example.method_to_extract()
More on staticmetod decorator here: https://www.programiz.com/python-programming/methods/built-in/staticmethod
Of course, not all of your methods can be static. Then you just have to create an instance of the class and then use its methods:
# file1.py
class Example:
def method_to_extract(name):
print(name)
And then in another file just import and use it:
# file2.py
from file2 import Example
instance = Example()
instance.method_to_extract()
Basically, the above three approaches are in general only possible ways of accessing some particular function or method in python and the fact of exporting them to another file doesn't change a thing.
Something like this:
from Example import Example.method_to_extract as mte
collect_data(mte)
The code you show is not entirely correct; you would have to make method_to_extract a #staticmethod if it's inside the Example class. Perhaps a better solution then would be to define it outside the class; or define a #classmethod which you can call to return a method of that class as an object. But both of these are generally best avoided; your class should probably simply have a method which implements collect_data, and your code should simply call that instead.
Related
I'm working on a function library/module for a project. I was wondering, to use it in another file as a module, do I need to put it in a class? I've tried adding my module to other files, but it doesn't work. Also, a lot of other built-in modules are in a class. Should I put it in a class or not? I'm also looking for an objective answer and not if it's a common practice or not.
You can put it in a class or let it outside a class. It depends on the use of this function.
e.g.:
class MyClass:
#staticmethod
def function(arguments):
# Your code
In order to import it you will have to use this:
from name_of_the_file import name_of_the_class
In the file you will have to use name_of_the_class.name_of_the_function().
e.g.:
MyClass.function(arguments)
If you define the function outside a class:
from name_of_the_file import name_of_the_function
In general, you don't need to put functions in a class. For example, functools.wraps() is a function.
However, you haven't mentioned the actual problem you're having, so this general answer is probably not very helpful.
how do you define dotted function?
i try this:
def myfunc.print(value)
print(value);
but it's said "Invalid syntax"
In python, and in many other languages, the "dot" syntax is a product of code organizational structure. So, X.Y tells python to look for Y inside of X. There are actually a few ways to do this. You can define a class which organizes a set of functions and properties within the class or its associated objects (as #Samwise's answer shows). You can also create a new file "myfunc.py", and have one of the functions defined in that file be def print(): pass - then when you import myfunc in another file you can access myfunc.print. In any case, the dot represents a "belonging" relationship, so you need to have your print function "belong" to the myfunc containing structure in some way.
Here's one way:
>>> class myfunc:
... print = print
...
>>> myfunc.print("foo")
foo
In this example, myfunc is actually a class, and print is a class attribute (which is initialized to point to the print function).
I'm working on a some classes, and for the testing process it would be very useful to be able to run the class methods in a for loop. I'm adding methods and changing their names, and I want this to automatically change in the file where I run the class for testing.
I use the function below to get a list of the methods I need to run automatically (there are some other conditional statements I deleted for the example to make sure that I only run certain methods that require testing and which only have self as an argument)
def get_class_methods(class_to_get_methods_from):
import inspect
methods = []
for name, type in (inspect.getmembers(class_to_get_methods_from)):
if 'method' in str(type) and str(name).startswith('_') == False:
methods.append(name)
return methods
Is it possible to use the returned list 'methods' to run the class methods in a for loop?
Or is there any other way to make sure i can run my class methods in my testingrunning file without having to alter or add things i changed in the class?
Thanks!
Looks like you want getattr(object, name[, default]):
class Foo(object):
def bar(self):
print("bar({})".format(self))
f = Foo()
method = getattr(f, "bar")
method()
As a side note : I'm not sure that dynamically generating lists of methods to test is such a good idea (looks rather like an antipattern to me) - now it's hard to tell without the whole project's context so take this remarks with the required grain of salt ;)
I am writing a Python package in which I have different Classes with a common method called map. That method always returns a function and is intended to be use inside a method of another package. Is there a way to lists all methods that are called map inside my package?
You're going to need to dip into a bit of reflection on this one. The steps you need are to load a reference a given module, grab the list of classes and then examine each class to make sure it has the method map:
import sys, inspect
def map_classes(module_name):
for name, obj in inspect.getmembers(sys.modules[module_name]):
if inspect.isclass(obj):
try:
if callable(getattr(obj, 'map')):
yield name
except AttributeError:
pass
This method will return a generator of all names of all classes within a module that have a map method. Note, if they have a map attribute, it will not return the name of the class.
You don't need the inspect package. Everything you need is built-in.
>>> import numpy as np
>>> for name, obj in np.__dict__.items():
... if hasattr(obj,"tolist"):
... print name, obj
What I am trying to do, is creating a module, with a class; and a function, which is an interface of that class; and a variable name on-the-fly in this function, which is pointing to an instance of that class. This function and the class itself should be in a separate module, and their usage should be in a different python file.
I think, it's much easier to understand what I am trying to do, when you are looking at my code:
This is the first.py:
class FirstClass:
def setID(self, _id):
self.id = _id
def func(self):
pass
# An 'interface' for FirstClass
def fst(ID):
globals()['%s' % ID] = FirstClass(ID)
return globals()['%s' % ID]
Now, if I'm calling fst('some_text') right in first.py, the result is pretty much what I dreamed of, because later on, any time I write some_text.func(), it will call the func(), because some_text is pointing to an instance of FirstClass.
But, when the second.py is something like this:
from first import fst
fst('sample_name')
sample_name.func()
Then the answer from python is going to be like this:
NameError: name 'sample_name' is not defined.
Which is somewhat reasonable.. So my question is: is there a "prettier" method or a completely different one to do this? Or do I have to change something small in my code to get this done?
Thank you!
Don't set it as a global in the function. Instead, just return the new instance from the function and set the global to that return value:
def fst(ID):
return FirstClass(ID)
then in second.py:
sample_name = fst('sample_name')
where, if inside a function, you declare sample_name a global.
The globals() method only ever returns the globals of the module in which you call it. It'll never return the globals of whatever is calling the function. If you feel you need to have access to those globals, rethink your code, you rarely, if ever, need to alter the globals of whatever is calling your function.
If you are absolutely certain you need access to the caller globals, you need to start hacking with stack frames:
# retrieve caller globals
import sys
caller_globals = sys._getframe(1).f_globals
But, as the documentation of sys._getframe() states:
CPython implementation detail: This function should be used for internal and specialized purposes only. It is not guaranteed to exist in all implementations of Python.