Declare global variable and passing value across methods in Python OOP - python

Declare global variable and passing value across methods
in Python OOP.
So, I would like to pass the result of nethod1 to
method2.
For example
import pandas as pd
class ExampleClass(object):
def method1(self):
file_path="/some/path/"
file_data="populaion_data.csv"
data=pd.read_csv(file_path+file_data)
res = data.head(5)
def method2(self):
"""
In his method, i would like to do the following tasks
(1)read the "res" from the method1.
(2)want to get the value of "file_path" from method1 again.
"""
And, also I think it would be better to declare the
"file_path" value as a global vaiable, so I can use that
value across several methods.

If you want the variable to be accessible across methods in the same class, you can just declare an instance variable:
import pandas as pd
class ExampleClass(object):
def __init__(self):
self.file_path = "/some/path/"
self.res = ''
def method1(self):
file_data="populaion_data.csv"
data=pd.read_csv(self.file_path+file_data)
self.res = data.head(5)
def method2(self):
"""
In his method, i would like to do the following tasks
(1)read the "res" from the method1.
(2)want to get the value of "file_path" from method1 again.
"""
#self.file_path and self.res will be accessible here too.
print (self.file_path, self.res)
a = ExampleClass()
a.method2()

You can do the following:
def method1(self):
self.file_path = "some/path/"
file_data = "population_data.csv"
data=pd.read_csv(file_path+file_data)
self.res = data.head(5)
def method2(self):
print(self.file_path, self.res)
Note that you will have to call method2 after method1 however. You can also call method1 from method2 and then use the values like this:
def method1(self):
file_path = "some/path/"
file_data = "population_data.csv"
data=pd.read_csv(file_path+file_data)
res = data.head(5)
return (file_path, res)
def method2(self):
file_path, res = self.method1()
You can also define it as a class variable or a static variable.
To define it as a static variable simply do:
class ExampleClass:
file_path = "some/path"
data=pd.read_csv(file_path+file_data)
res = data.head(5)
def method2(self):
print(self.file_path, self.res)

This is not an OOP question. With OOP you manipulate objects defined by Classes which are, from a basic point of view, types A type is a component having a state (data) and behavior (integrated functions called methods). Thus, there is no global variables in OOP. Data can be provided to objects trough methods parameters and the result of the processing should be returned by the method.
In this cas, I don't see the reason why those functions are within a class except if you need objects as defined in previous answers. Based on your code example, this is resolved with functions for which, data should be passed as parameters:
import pandas as pd
DEFAULT_FILE_PATH ="/some/path/"
def method1(filename, file_path='/'):
data=pd.read_csv(file_path + file_data)
return data.head(5)
def method2(data, file_path='/'):
"""
In his method, i would like to do the following tasks
(1)read the "res" from the method1.
(2)want to get the value of "file_path" from method1 again.
"""
So you know what file_path is, you can use it as
method2(method1("populaion_data.csv", DEFAULT_FILE_PATH), DEFAULT_FILE_PATH)

Related

How to pass return value of method within class?

What is the proper way to pass a returned value from a method within a class? Do you always call the method when needed or can the returned value be stored in the init method?
Let's say I have:
class Foo():
def __init__(self):
def heavy_method(self):
#slow crunching
return crunch
def use_heavy_crunch(self):
data = self.heavy_crunch()
for i in data:
#do data stuff
#return data stuff
def other_func_that_need_heavy_method(self):
pass
d = Foo()
d.use_heavy_crunch()
What I wonder is if above structure is the correct way or if the below way is equivalent or better?
class Foo()
def __init__(self):
self.data = None
def heavy_method(self):
#slow crunching
self.data = crunch
def use_heavy_crunch(self):
for i in self.data:
#do data stuff
#return data stuff
def other_func_that_need_heavy_method(self):
pass
d = Foo()
d.heavy_method()
d.use_heavy_crunch()
So in the above example a method is called within an other method, while in the below example the return value of the method is passed to a variable in the init method and later on used in another function.
If I understand correctly you're trying to do something like
class Foo():
def __init__(self):
self.data = self.heavy_method() # we assign the return value to an attribute of our object
def heavy_method(self):
#slow crunching
return crunch
def use_heavy_crunch(self):
for i in self.data: # Notice it's now self.data
#do data stuff
#return data stuff
def other_func_that_need_heavy_method(self):
pass
d = Foo()
d.use_heavy_crunch()
You don't want the initialization method of class to perform heavy processing tasks, its generally bad practice, the class initialization should only be used to initialize class based instance variable.
If you are planning to call d.use_heavy_crunch() multiple times in future after the instance d is created and the return value of d.heavy_method() did not change over time then the second approach is good way to go, as in case of first approach every time you call d.use_heavy_crunch() you are calling d.heavy_method() and performing the same tasks repeatedly. In the second approach you would only call d.heavy_method() once and later use its result in other methods of class.

invoking a class method inside the class itself

Hi everyone i wanna use a calculated value from a method of the class itself for the rest of the class methods but it must calculate once for all and i need to invoke method inside the class itself i write an example:
class something():
def __init__():
pass
def __sum(self, variable_1, variable_2):
self.summation = sum(variable_1, variable_2)
# I need to calculate summation here once for all:
# how does the syntax look likes, which one of these are correct:
something.__sum(1, 2)
self.__sum(1, 2)
# If none of these are correct so what the correct form is?
# For example print calculated value here in this method:
def do_something_with_summation(self):
print(self.summation)
Something like this seems to be what you're looking for:
class Something:
def __init__(self):
self.__sum(1, 2)
def __sum(self, variable_1, variable_2):
self.summation = sum(variable_1, variable_2)
Not saying this is the ideal approach or anything, but you haven't really given us much to go off of.
In general, make sure self is the first argument in all class methods, and you can call that class method at any time using either self.method_name() if you are using it from within another class method or instance.method_name() if you're using it externally (where instance = Something()).
Assuming that you would receive variable1 and variable2 when you instantiate the class one solution could be:
class something():
def __init__(self, variable1, variable2):
self.summation = variable1 + variable2
def do_something_with_summation(self):
print(self.summation)
If instead you're creating variable1 and variable2 inside other methods, then you could make them class variables:
class Something():
def __init__(self):
#Put some initialization code here
def some_other_method(self):
self.variable1 = something
self.variable2 = something
def sum(self):
try:
self.summation = self.variable1 + self.variable2
except:
#Catch your exception here, for example in case some_other_method was not called yet
def do_something_with_summation(self):
print(self.summation)

Python How to create method of class in runtime

I am curious how to create a custom method for a class at runtime...
I mean for example with name of method, name of parameters, body of method read from database and assign this method to a class or to an instance.
I have a found possibility to add method that is already written:
class A:
def __init__(self):
pass
def method(self):
return True
A.method = method
a = A()
print(a.method())
but I am interested in completely assembling a new method from scratch:
name = "method"
params = ["self"] # Params in list should be a strings
body = "return True"
# To create method from pieces
Is it possible using __dict__ ? Or how else this be done?
Methods are another attribute on the object that is the class. They can be added like other attributes:
Code:
class A:
def __init__(self):
pass
def method(self):
return True
def another_method(self):
return False
setattr(A, 'another_method', another_method)
Test Code:
a = A()
print(a.another_method())
Results:
False
Methods from a string:
Add if you really need to get your methods from a database or such you can use exec like:
method_string = """
def yet_another_method(self):
return type(self).__name__
"""
exec(method_string)
setattr(A, 'yet_another_method', yet_another_method)
a = A()
print(a.yet_another_method())
Results:
A
This answer has to be treated with care, using exec or eval can run arbitary code and may compromise your system. So if you rely on user-input to create the function you mustn't use this!!!
The warning aside you can simply create anything using exec:
exec("""
def method():
return True
""")
>>> method()
True
So what you basically need is just a way to get your requirements in there:
functionname = 'funfunc'
parameters = ['a', 'b']
body = 'return a + b'
exec("""
def {functionname}({parameters}):
{body}
""".format(
functionname=functionname,
parameters=', '.join(parameters),
body='\n'.join([' {line}'.format(line=line) for line in body.split('\n')])))
The body will be indented so that it's valid syntax and the parameter list will be joined using ,. And the test:
>>> funfunc(1, 2)
3
One of the best solutions that I have found is the following:
def import_code(code, name, add_to_sys_modules=0):
"""
Import dynamically generated code as a module. code is the
object containing the code (a string, a file handle or an
actual compiled code object, same types as accepted by an
exec statement). The name is the name to give to the module,
and the final argument says wheter to add it to sys.modules
or not. If it is added, a subsequent import statement using
name will return this module. If it is not added to sys.modules
import will try to load it in the normal fashion.
import foo
is equivalent to
foofile = open("/path/to/foo.py")
foo = importCode(foofile,"foo",1)
Returns a newly generated module.
"""
import sys,imp
module = imp.new_module(name)
exec(code,module.__dict__)
if add_to_sys_modules:
sys.modules[name] = module
return module
class A:
def __init__(self):
pass
name = "method"
params = ["self"] # Params in list should be a strings
body = "return True"
scratch = "def {0}({1}):\n\t{2}".format(name, ','.join(params), body)
new_module = import_code(scratch, "test")
A.method = new_module.method
a = A()
print(a.method())
Original function import_code by the following link http://code.activestate.com/recipes/82234-importing-a-dynamically-generated-module/
Using this solution I can dynamically create methods, load them in runtime and link to whatever I want object !!

Inheritance of function from class but editing that function

I'm using Python and I have two classes. I want to import a function for a class but with the ability of adding things to that function.
class Main(self):
def __init__(self):
thingstodo()
def function(self, keypressed):
#LOTS OF CODE
keyname = keypressed
if keyname = "Escape":
dosomething()
class Main2(Main):
def __init(self):
Main.__init__(self)
def function(self, keypressed):
Main.function(self, keypressed)
if keyname = "control":
dootherthing()
Basic principles
You cannot access local variables from one function (or method) in another function. This is by design.
This class Main(self): is wrong. In Python 3 do class Main:. While using self as the name of the first argument in method is a strong convention, self is just an ordinary name not a reserved keyword or built-in.
There are several problems here:
def __init(self):
Main.__init__(self)
a. The method name needs to __init__() not __init.
b. Don't hardwire the name of the parent class with Main.__init__(self) use super().__init__().
c. If you don't do anything extra in the __init__() of Main2, than you don't need to implement the __init__() at all.
Possible solution
For your problem, using a dictionary with the key press names as keys and the functions for the actions as values seems useful.
First define a few small helper functions:
def thingstodo():
print('thingstodo')
def dosomething():
print('something')
def dootherthing():
print('dootherthing')
Now your main class:
class KeyAction: # Python 3
def __init__(self):
thingstodo()
self.key_actions = {'Escape': dosomething}
def handel_key_press(self, keypressed):
#LOTS OF CODE
keyname = keypressed
func = self.key_actions.get(keyname)
if func is not None:
func()
Names are important, therefore I use KeyAction instead of Main.
This line self.key_actions = {'Escape': dosomething} is the core of this solution. Here self.key_actions is a dictionary that maps names of key press events to functions. Note dosomething without the () because I put the function object into the dictionary rather than calling this function.
Calling this function is a bit different:
func = self.key_actions.get(keyname)
if func is not None:
func()
I use the get() method of the dictionary. This returns the value for the key if the key is in it and None if not. Now func holds either a reference to the function dosomething if the key was Escape or None. If it is a function I call it with func().
An alternative here could be a try-except:
def handel_key_press(self, keypressed):
#LOTS OF CODE
keyname = keypressed
try:
self.key_actions[keyname]()
except KeyError:
pass
Now, in your child class, you only need to add another key-value pair to self.key_actions to extend its functionality:
class ExtendedKeyAction(KeyAction):
def __init__(self):
super().__init__()
self.key_actions['control'] = dootherthing
Make two instances and test your code:
key_action = KeyAction()
key_action.handel_key_press('Escape')
key_action.handel_key_press('undefined')
extended_key_action = ExtendedKeyAction()
extended_key_action.handel_key_press('Escape')
extended_key_action.handel_key_press('control')
extended_key_action.handel_key_press('undefined')
prints:
thingstodo
something
thingstodo
something
dootherthing

Python metaprogramming: automatically generate member functions

How do I write a function that adds a method to a class? I have:
class A:
def method(self):
def add_member(name):
self.new_method = def name...?
add_member("f1")
add_member("f2")
In order to answer what I'm trying to do. I'm trying to factor out some pyqt slots. I want to be able to call a function create_slider that will create a QSlider and a QLabel and create the slider handling code, and make the slider-handler update the text in the QLabel. Here's the slot that needs to be factored out:
def on_sample_slider(self, value):
self.samples = pow(4, value)
self.sample_label.setText('%d' % self.samples)
here's a method that generates some UI, but it would be nice to also have it generate the on_sample_slider method every time it is called:
def insert_labeled_slider(hbox, name, slider_target):
# name
hbox.addWidget(QLabel(name))
# label
label = QLabel()
label.setMinimumSize(40, 0)
hbox.addWidget(self.sample_label)
#slider
slider = QSlider(Qt.Horizontal)
slider.setRange(0, 6)
slider.setTracking(True)
slider.setPageStep(1)
hbox.addWidget(slider)
self.connect(self.sample_slider, SIGNAL('valueChanged(int)'),
self.on_sample_slider)
self.sample_slider.setValue(0)
return (label, slider)
Final code:
def attach_on_slider(obj, name, variable, label, base):
def on_slider(self, value):
variable = base**value
label.setText('%d' % variable)
# This next line creates a method from the function
# The first arg is the function and the second arg is the object
# upon which you want it to be a method.
method = types.MethodType(on_slider, obj)
obj.__dict__["on_slider_" + name] = method
return method
class A:
def insert_labeled_slider(hbox, name, label_name, variable):
# name
hbox.addWidget(QLabel(label_name))
# label
label = QLabel()
label.setMinimumSize(40, 0)
hbox.addWidget(label)
#slider
slider = QSlider(Qt.Horizontal)
slider.setRange(0, 6)
slider.setTracking(True)
slider.setPageStep(1)
hbox.addWidget(slider)
on_slider_method = attach_on_slider(self, name, variable, label, 4)
self.connect(slider, SIGNAL('valueChanged(int)'),
on_slider_method)
slider.setValue(0)
return (label, slider)
Here's an real example from your newly posted code:
import types
def attach_on_sample_slider(obj, base):
def on_sample_slider(self, value):
self.samples = base**value
self.sample_label.setText('%d' % self.samples)
# This next line creates a method from the function
# The first arg is the function and the second arg is the object
# upon which you want it to be a method.
obj.on_sample_slider = types.MethodType(on_sample_slider, obj)
You can now call it like
def some_method(self, foo):
attach_on_sample_slider(self, 4)
original post
Since you say the the member functions are identical, I would do it something like this
def make_method(name):
def method(self, whatever, args, go, here):
#whatever code goes here
method.__name__ = name
return method
class A(object):
method1 = make_method('method1')
method2 = make_method('method2')
Strictly speaking, passing in the name and setting the __name__ attribute on the new function isn't necessary but it can help with debugging. It's a little bit of duplication and can pay for itself. If you are going to skip that though, you might as well do
class A(object):
def method1(self, arg1, arg2):
#code goes here
method2 = method1
method3 = method1
This creates identical methods. Calling either of them will yield the same method.
The first form is more powerful because you can pass other arguments besides the name into make_method and have the different versions of the returned method access those parameters in closure so they work differently. Here's a stupid example with functions (works the same with methods):
def make_opener(filename):
def opener():
return open(filename)
return opener
open_config = make_opener('config.cfg')
open_log = make_opener('log.log')
Here, they're all essentially the same function but do slightly different things because they have access to the value of filename that they were created with. Closures are definitely something to look into if you're going to be doing a lot of this sort of thing.
There can be a lot more to this so if you have particular questions that this doesn't address, you should update your question.
Add bound methods to instantiated objects in Python tells this issue.

Categories