How to acces to a class variable with a string? - python

I have the following code:
import Parameters
def ReadOptionFromParametersFile(self,variable_name):
if (hasattr(Parameters, str(variable_name))):
return Parameters.variable_name
else:
return 0
I want to call this function for different variables. In case the variable is defined on that Parameter file i want to read the value doing Parameters.variable_name. The problem is obviously that the file has no variable called variable_name.
I also tried:
Parameters.str(variable_name)
or
Parameters.eval(variable_name)

You can use getattr to access an attribute by its string name:
return getattr(Parameters, variable_name)
In fact, your entire method can be refactored to just:
def ReadOptionFromParametersFile(self, variable_name):
return getattr(Parameters, variable_name, 0)
The third argument to getattr is an optional default value to return if the attribute is not found.

Related

class employee print method

I am studying classes in python programming in jupyter notebooks and google colab.
I don't understand the results with respect to this class.
class employee_constructor():
def __init__(self,name,surname,salary):
self.name=name
self.surname=surname
self.salary=salary
def increasesalary(self,percentage):
self.salary=self.salary*(1+percentage/100)
def displayEmployee(self):
print('this employee is {} and gets {} dollars'.format(emp1.name,emp1.salary))
now I try to print out results:
emp1=employee_constructor('jose','ferro',1000)
emp2=employee_constructor('manolo','rod','1500')
emp1.displayEmployee
print('before increase',emp1.salary)
emp1.increasesalary(5)
emp1.increasesalary(5)
print('after increase',emp1.salary)
print(emp1.salary)
# this line does not give error and does nothing:
emp1.increasesalary
print(emp1.salary)
# this line gives error:
# increasesalary() missing 1 required positional argument: 'percentage'
emp1.increasesalary()
I don't understand why running the method without the parenthesis would not cause any error (actually the method is not run) whereas with the parenthesis (and not passing the neccesary variable through an error)
secondly, how can I avoid such kind of errors? i.e. if the user passes nothing assume vale zero
note:
this question explains init method and was proposed as solution. My question is related but is not answered there
I don't understand why running the method without the parenthesis would not cause any error (actually the method is not run) whereas with the parenthesis (and not passing the neccesary variable through an error)
When you refer a method (function in the context of an object, self is passed implicitly) by object.method the method object is returned. But to actually execute the function you need to call it i.e. use the parentheses.
For fun, save the returned method object as a variable and call that instead, you'll see that you're doing the same thing as they refer to the same object.
Now, when you called emp1.increasesalary(), you didn't pass the required argument percentage leading to the error. Note again, the self (object itself) is passed implicitly.
how can I avoid such kind of errors? i.e. if the user passes nothing assume vale zero
Make the argument a keyword argument with a default value of 0:
def increasesalary(self, percentage=0):
self.salary = self.salary * (1 + percentage / 100)
you can always use a funtion (without parenthesis) in python:
def f():
pass
print(f)
this will not call the function but just print out its memory location. so a line containing the function f itself is a valid python statement; but it does not call the function.
then: you need to use self and not emp1 in your displayEmployee(self) method:
def displayEmployee(self):
print('this employee is {} and gets {} dollars'.format(self.name, self.salary))
better:
def __str__(self):
return f"this employee is {self.name} and gets {self.salary} dollars"
then you can
print(emp1)

How can I call a method from a name string in Python?

I am using an API to call specific information from a website. I need to be able to parse through the list to utilize the functions. Example:
list = ['doThis','doThat']
for item in list:
sampleobject.item
The issue is when I use this, I get an error saying "sampleobject has no attribute 'item'".
Is there a way that I can pull the quote out of the string to do this?
Try:
methods = ['doThis','doThat']
for method_name in methods:
method = getattr(sampleobject, method_name)
method()
Though it would be easier to do:
sampleobject.doThis()
sampleobject.doThat()
You can call getattr(sampleobject, item) to get the content of a property with the name equal to what is stored in item, which is an element from your list.
I think the problem is not about quotes at all. The problem is that syntax object.member means: evaluate a property named member that is stored in a variable named object. And you expect it to mean: evaluated a property with the name stored in member.

How to generate a new function name from an other one

Let us give an example.
If we have a function def f(func): ..., where func is a parameter corresponding to a function.
If we make the following call f(merge), I would like to return another function name (not a text) merge_ext that could be then executed.
I have identified the fact that a function name col be extract with the syntax my_function.__name__, but how can I generate the new function name that could be used as a function?
It looks like you're after decorators.
A decorator is a function that takes a function as arguments, and returns a function. Simple example :
def simple_decorator(func):
return func
You can use it with the # syntax :
#simple_decorator
def decorated_function(some_arg):
return something
In that case, calling function will call the function returned by the call simple_decorator(function), which means you cannot access the orginal function anymore.
But this can also be expressed like this :
def no_yet_decorated_function(some_arg):
return something
decorated_function = simple_decorator(no_yet_decorated_function)
Now, you can access both your functions.

Python: how to pass argument name using variable

A module I'm using has many functions defined with different argument names more or less serving the same purpose:
def func1(start_date):
....
def func2(startdate):
....
def func3(s_date):
....
def func4(sdate):
....
and they appear all in different positions of the argument list (in the above simplified case they're all in position 1, but in reality that's not the case).
I want to write a wrapper that can pass the actual start_date to any of these functions via a dictionary from function name to argument name:
def func2arg_name():
return {'func1' : 'start_date',
'func2' : 'startdate',
'func3' : 's_date',
'func4' : 'sdate' }
Then the actual wrapper:
f2a = func2arg_name()
def func(func_name, sdate):
locals()[func_name](f2a[func_name] = sdate)
func('func1', '20170101')
Clearly this doesn't work. Essentially the f2a[func_name] is not being recognized as a legit keyword. Does any one know how to do this, i.e. pass the argument name using a variable? Note func1 to func4 are externally defined and cannot be changed.
Make a dict with the argument name as the key, and pass it using unpack operator:
locals()[func_name](**{f2a[func_name]: sdate})
See Unpacking argument lists in the Python tutorial.

How to pass extra arguments to callback register functions with twisted python api?

I have the following python code using the twisted API.
def function(self,filename):
def results(result):
//do something
for i in range(int(numbers)) :
name = something that has to do with the value of i
df = function_which_returns_a defer(name)
df.addCallback(results)
It uses the Twisted API. What i want to achieve is to pass to the callbacked function (results) the value of the name which is constructed in every iteration without changing the content of the functions_which_returns_a defer() function along with the deferred object of course. In every result of the functions_which_returns_a deffer the value of the name should be passed to results() to do something with this. I.e: at the first iteration when the execution reach the results function i need the function hold the result of the deffered object along with the value of name when i=0,then when i=1 the defered object will be passed with the value of name, and so on.So i need every time the result of the defer object when called with the name variable alond with the name variable. When i try to directly use the value of nameinside results() it holds always the value of the last iteration which is rationale, since function_which_returns_a defer(name) has not returned.
You can pass extra arguments to a Deferred callback at the Deferred.addCallback call site by simply passing those arguments to Deferred.addCallback:
def function(self,filename):
def results(result, name):
# do something
for i in range(int(numbers)) :
name = something that has to do with the value of i
df = function_which_returns_a defer(name)
df.addCallback(results, name)
You can also pass arguments by keyword:
df.addCallback(results, name=name)
All arguments passed like this to addCallback (or addErrback) are passed on to the callback function.

Categories

Resources