I have a class and multiple functions that run in succession as:
class ClassA():
def __init__(self):
....
def calc_A(self, param1, param2 ,param3):
res = self.__calc_B(param1=param1)
res_2 = self.__calc_C(res=res, param2, param3)
def __calc_B(self, param1):
return param1**2
def __calc_C(self, param1):
return res + param1
As you can see calc_A() takes in parameters for __calc_B() and __calc_C(). The original class is getting pretty complex as I need quite a number of parameters to run all the functions and I see myself repeating a lot of docstrings for params that get used in more than one function.
Question 1:
Is it best practice to just use *args for __calc_B() and __calc_C() or should it be handled in a completely different way?
Question 2:
Additionally, do I describe the parameters in the docstring in calc_A() or in every function?
*args is never best practice because looking at the function you won't know what is supposed to go into the function. Only by writing documentation to the function can a user figure out what the inputs are supposed to be. Making input parameters explicit if possible is generally favored, because they show up when the user calls help.
Docstrings mainly serve to help users who can learn what the function does by calling help(function). __calc_B and __calc_C seem to be functions that are not supposed to be used by the user, so a docstring is not strictly necessary. It is most important to choose good descriptive names for these functions so that you or someone else who needs to understand the code can figure out what it does. You could still write a docstring or comments if it's a particularly difficult function, but they don't need to be so detailed.
If you find no other alternatives, there are ways of generating docstrings dynamically but this is generally not recommended.
Related
I am creating a module in which I'm defining multiple functions and I want to give the users some help regarding it, just like the help() function does. Still, I'm not quite sure how I do that, so can someone help me with it, for example, if I want help regarding this function, what will I have to do?
def shanky_calculate_average(*args):
my_average = sum(args) / len(args)
return my_average
I just want to know if I can get help in the same way as you can on things like help(pandas.read_excel)
What help() actually does is printing the function name with arguments and its docstring. Docstrings are comments directly after the function or class definition and are declared using either '''triple single quotes''' or """triple double quotes""".
So doing something like this:
def shanky_calculate_average(*args):
'''
Computes the average of the arguments.
Example: shanky_calculate_average(1,2,3,4)
'''
my_average = sum(args) / len(args)
return my_average
will result in help(shanky_calculate_average)
to print
shanky_calculate_average(*args)
Computes the average of the arguments.
Example: shanky_calculate_average(1,2,3,4)
As a sidenote, you can also access docstrings via the __doc__ property of the object like this: shanky_calculate_average.__doc__.
def foo(myarg, **other_args):
# do something
return bar(**other_args)
Is it possible to annotate this function in a way that would make it clear to IDEs that other_args are the arguments of function bar()? So that the IDE would provide a helpful code completion in this case.
Is there a better way to do this? Like I'm passing in arguments to func that will be used in inside_func function?
def inside_func(arg1,arg2):
print arg1, arg2
return
def func(arg1, arg2):
inside_func(arg1,arg2)
return
Of course it is.
Your outer function provides a service, and to do its job it may need inputs to work with. How it uses those inputs is up to the function. If it needs another function to do their job and they pass in the arguments verbatim, is an implementation detail.
You are doing nothing more than standard encapsulation and modularisation here. This would be correct programming practice in any language, not just Python.
The Python standard library is full of examples; it is often used to provide a simpler interface for quick use-cases. The textwrap.wrap() function for example:
def wrap(text, width=70, **kwargs):
"""Wrap a single paragraph of text, returning a list of wrapped lines.
Reformat the single paragraph in 'text' so it fits in lines of no
more than 'width' columns, and return a list of wrapped lines. By
default, tabs in 'text' are expanded with string.expandtabs(), and
all other whitespace characters (including newline) are converted to
space. See TextWrapper class for available keyword args to customize
wrapping behaviour.
"""
w = TextWrapper(width=width, **kwargs)
return w.wrap(text)
This does nothing else but pass the arguments on to other callables, just so your code doesn't have to remember how to use the TextWrapper() class for a quick one-off text wrapping job.
Can you please help me guys. I believe I've got pretty easy questions but don't want to stuff up with my assignment. I'm going to have Class in my module, this class will have few functions.
I just want to be sure it works alright and this is a not ugly code practice.
I.e. my first function test_info accepts one parameter test_code and returns something and the second function check_class accepts two parameter, one of them is called test_code as well
Can I use same argument name: test_code? Is it normal code practice?
def test_info (self, test_code):
my_test_code = test_code
#here we'll be using my_test_code to get info from txt file and return other info
def check_class (self, test_code, other_arg):
my_test_code = test_code
#here some code goes
Also is it fine to use my_test_code in both functions to get argument value or is it better to use different ones like my_test_code_g etc.
Many thanks
Yes you may.
The two variables test_code are defined only in the scope of their respective functions and therefore will not interfere with one another since the other functions lie outside their scope.
Same goes for my_test_code
Read online about variable scopes. Here is a good start
There is no technical reason to resolve this one way or another. But if the variables don't serve exactly the same purpose in both functions, it's confusing for a human reader if they have the same name.
We're considering using Python (IronPython, but I don't think that's relevant) to provide a sort of 'macro' support for another application, which controls a piece of equipment.
We'd like to write fairly simple functions in Python, which take a few arguments - these would be things like times and temperatures and positions. Different functions would take different arguments, and the main application would contain user interface (something like a property grid) which allows the users to provide values for the Python function arguments.
So, for example function1 might take a time and a temperature, and function2 might take a position and a couple of times.
We'd like to be able to dynamically build the user interface from the Python code. Things which are easy to do are to find a list of functions in a module, and (using inspect.getargspec) to get a list of arguments to each function.
However, just a list of argument names is not really enough - ideally we'd like to be able to include some more information about each argument - for instance, it's 'type' (high-level type - time, temperature, etc, not language-level type), and perhaps a 'friendly name' or description.
So, the question is, what are good 'pythonic' ways of adding this sort of information to a function.
The two possibilities I have thought of are:
Use a strict naming convention for arguments, and then infer stuff about them from their names (fetched using getargspec)
Invent our own docstring meta-language (could be little more than CSV) and use the docstring for our metadata.
Because Python seems pretty popular for building scripting into large apps, I imagine this is a solved problem with some common conventions, but I haven't been able to find them.
Decorators are a good way to add metadata to functions. Add one that takes a list of types to append to a .params property or something:
def takes(*args):
def _takes(fcn):
fcn.params = args
return fcn
return _takes
#takes("time", "temp", "time")
def do_stuff(start_time, average_temp, stop_time):
pass
I would use some kind of decorator:
class TypeProtector(object):
def __init__(self, fun, types):
self.fun, self.types = fun, types
def __call__(self, *args, **kwargs)
# validate args with self.types
pass
# run function
return fun(*args, **kwargs)
def types(*args):
def decorator(fun):
# validate args count with fun parameters count
pass
# return covered function
return TypeProtector(fun, args)
return decorator
#types(Time, Temperature)
def myfunction(foo, bar):
pass
myfunction('21:21', '32C')
print myfunction.types
The 'pythonic' way to do this are function annotations.
def DoSomething(critical_temp: "temperature", time: "time")
pass
For python 2.x, I like to use the docstring
def my_func(txt):
"""{
"name": "Justin",
"age" :15
}"""
pass
and it can be automatically assign to the function object with this snippet
for f in globals():
if not hasattr(globals()[f], '__call__'):
continue
try:
meta = json.loads(globals()[f].__doc__)
except:
continue
for k, v in meta.items():
setattr(globals()[f], k, v)