Global variables as input parameters - python-3.x

I doubt whether it is appropriate to use input variables in functions in cases where the input variable will always be the same.
mynum = int(datetime.today().weekday())
def somefuncion():
result = 3 + mynum
return result
optionA = somefuncion()
def somefunction2(number):
result = 3 + number
return result
optionB = somefunction2(mynum)
print(optionA == optionB) # true
Is there good practice in this respect ? or is it indifferent ?

In your case, it would probably be more appropriate to create constant variables.
MYNUM = 12
MYNUM_PLUS_TREE = MY_NUM + 3
That way, when you modify the value of MYNUM in your development, it automatically modifies the value of all the constant values that are generated from it (here it is MYNUM_PLUS_TREE).
The logic I apply here is the following: if a function always return the same value, then it is a "constant function", as in mathematics. Therefore, using a constant variable is preferable.

If you are sure that you are not going to modify the value of the variable anywhere in the code then you should declare it as a constant and use it that way within the code. i.e. not include it as an input variable.
Python, constants are capitalized (PEP 8 standards) which helps the programmer know it's a constant.
i.e
CONSTANT = "Whatever"
in your example:
MYNUM = int(datetime.today().weekday())
def somefuncion():
result = 3 + MYNUM
return result

Related

Functions - Variables - Scope

I have the below code.
a = 10
def f(x):
return x + a
a = 3
f(1)
If we print(f1) the result is 4. It seems that the second assignment of a is used here (a=3). Could someone explain to me if there is a particular reason or rule for not using the first assignment (a=10)?
Thank you,
Dimitrios
a and x are resolved each time return x + a is executed. You reassign a before calling f. f knows that a is not a local variable so looks up "a" in its enclosing scope. That "a" has a 3 in it, and that is what is used.
As a general rule, it would be very bad for f to use the original assignment when its executed. That would mean that functions couldn't take advange of global variables changing. It would also require that global variables be assigned before the function is even defined, which is not particularly useful for a dynamic language.
You can hack it, though. If you define a parameter with a default value, it will be assigned when the function is defined and you get what you want.
a = 10
def f(x, a=a):
return x + a
a = 3
print(f(1))
You see, you've defined a before you defined f(x). But your call to f(1) was after you assigned the value 3 to "a".
f(x) will always use the current value of "a" when it its called, not when it is defined. If you want a constant value for "a" inside f(x), you should declare it inside the function, something like:
def f(x):
a = 10
return x + a

Idiomatic way for single-expressions procs in nim

Why do I see
proc simple(a, b: int) : int =
result = a + b
so often in nim code when it seems as if
proc simple(a, b: int) : int =
a + b
would suffice? Is there any semantic difference between those two that I'm missing?
The only reference to implicitly returning the last statement I found on nim-lang wasn't in the manual but in the tut where it states that
[...] a proc's body can consist of a single expression whose value is
then returned implicitly.
Which seems misleading: it seems as it works for every 'last expression' (unless result was already set, then the result of the statement has to be discarded)
In the coding conventions (https://nim-lang.org/docs/nep1.html#introduction-coding-conventions) they recommend to use return only if it's needed in the flow.
The book Nim in Action says 'it's not idiomatic to use the return keyword as the last statement of the proc', but it's not explicit about result = a + b vs a + b. From the snippets around the book, the convention seems to be:
Prefer a + b.
Use result = a + b only if you are modifying result, as in result.add(b).
Use return a only to do an early exit from the proc.
The book also list this gotcha that won't compile:
proc resultVar: string =
result = "The result"
"This cause an error"
The reason behind code like result = a + b or return a is that people can't get all the idiomatics, specially when they are beginners like me. I still see for i in range(len(variable)) in Python code, which is not only non-pythonic but ugly and underperformant.
One of the more exotic features is the implicit result variable: every procedure in Nim with a non-void return type has an implicit result variable that represents the value that will be returned [Wikipedia].

Pythonic way of creating if statement for nested if statements

I'm kind of newbie as programmer, but I wish to master Python and I'm developing open source application. This application has function to gather some information. This function takes 1 parameter. This parameter can be 0, 1 or 2. 0 = False, 1 = True, 2 = Multi. Also I have an if statement that does 2 actions. 1st - (when False) gathers single type value, 2nd - (when True) gathers multiple type values and when parameter is 2 (multi) then it will gather single type (1st) and multiple types (2nd). My if statement looks like this:
if False:
get_single_type = code.of.action
generators.generate_data(False, get_single_type)
elif True:
get_multiple_type = code.of.action
generators.generate_data(True, get_multiple_type)
else:
get_single_type = code.of.action
generators.generate_data(False, get_single_type)
get_multiple_type = code.of.action
generators.generate_data(True, get_multiple_type)
Is there maybe better way of avoiding this kind of coding, like in last else statement when I call both single and multiple.
Thank you in advance.
One thing I learned from Python is that although it lacks the Switch operator, you can use dictionary in a similar fashion to get things done since everything is an object:
def get_single():
# define your single function
get_single_type = code.of.action
generators.generate_data(False, get_single_type)
def get_multi():
# define your multi function
get_multiple_type = code.of.action
generators.generate_data(True, get_multiple_type)
actions = {
0: [get_single],
1: [get_multi],
2: [get_single, get_multi]
}
parameter = 0 # replace this line with however you are capturing the parameter
for action in actions[parameter]:
action()
This way you avoid c+p your code everywhere and have it referenced from the function, and your "actions" dictionary define the function to be used based on the parameter given.
In this case since you have multiple functions you want to call, I kept all dictionary items as a list so the structure is consistent and it can be iterated through to perform any number of actions.
Ensure you use leave out the () in the dictionary so that the functions aren't instantiated when the dictionary is defined. And remember to add () when you are actually calling the function from the dictionary to instantiate it.
This is something you will often encounter and it is pretty much always bad practice to be repeating code. Anyway, the way to do this is use two if-statements. This way, even if the first case passes, the second case can still pass. Oh, and assuming your variable that can be 0, 1 or 2 is called x, then we could either use or and two checks:
if x == 0 or x == 2:
but, personally, I prefer using in on a tuple:
if x in (0, 2):
get_single_type = code.of.action
generators.generate_data(False, get_single_type)
if x in (1, 2):
get_multiple_type = code.of.action
generators.generate_data(True, get_multiple_type)

How can I convert a string containing an equation into a double-precision value?

I have the following string:
A = 'A = cos(2*pi*f1*t) + 4*sin(2*pi*f2*t)';
And have defined the variables f1 and f2 (two frequency values) and t (a vector of time points). How I can convert the equation in A to a double-precision value?
I tried:
B = str2num(A); % Result is an empty matrix
and:
B = str2double(A); % Result is a NaN value
and:
B = double(A);
But no luck. How can I do this?
Assuming you have a string like so:
str = 'A = cos(2*pi*f1*t) + 4*sin(2*pi*f2*t)';
And your variables f1, f2, and t have been defined, you would need to use eval to evaluate the string (and you might want to add a ';' to the end to suppress output to the screen):
eval([str ';']);
It should be noted that eval isn't usually the best option, even though sometimes it may be unavoidable. It can have unintended consequences. For example, if a user entered clear all into your uicontrol, it would erase your workspace. They might also inadvertently shadow a function by making a bad choice of variable name, like entering sin = sin(2*pi*f*t). In other words, you should usually try to find alternatives that don't require eval to function.

Convert string to a variable name

I am using R to parse a list of strings in the form:
original_string <- "variable_name=variable_value"
First, I extract the variable name and value from the original string and convert the value to numeric class.
parameter_value <- as.numeric("variable_value")
parameter_name <- "variable_name"
Then, I would like to assign the value to a variable with the same name as the parameter_name string.
variable_name <- parameter_value
What is/are the function(s) for doing this?
assign is what you are looking for.
assign("x", 5)
x
[1] 5
but buyer beware.
See R FAQ 7.21
http://cran.r-project.org/doc/FAQ/R-FAQ.html#How-can-I-turn-a-string-into-a-variable_003f
You can use do.call:
do.call("<-",list(parameter_name, parameter_value))
There is another simple solution found there:
http://www.r-bloggers.com/converting-a-string-to-a-variable-name-on-the-fly-and-vice-versa-in-r/
To convert a string to a variable:
x <- 42
eval(parse(text = "x"))
[1] 42
And the opposite:
x <- 42
deparse(substitute(x))
[1] "x"
The function you are looking for is get():
assign ("abc",5)
get("abc")
Confirming that the memory address is identical:
getabc <- get("abc")
pryr::address(abc) == pryr::address(getabc)
# [1] TRUE
Reference: R FAQ 7.21 How can I turn a string into a variable?
Use x=as.name("string"). You can use then use x to refer to the variable with name string.
I don't know, if it answers your question correctly.
strsplit to parse your input and, as Greg mentioned, assign to assign the variables.
original_string <- c("x=123", "y=456")
pairs <- strsplit(original_string, "=")
lapply(pairs, function(x) assign(x[1], as.numeric(x[2]), envir = globalenv()))
ls()
assign is good, but I have not found a function for referring back to the variable you've created in an automated script. (as.name seems to work the opposite way). More experienced coders will doubtless have a better solution, but this solution works and is slightly humorous perhaps, in that it gets R to write code for itself to execute.
Say I have just assigned value 5 to x (var.name <- "x"; assign(var.name, 5)) and I want to change the value to 6. If I am writing a script and don't know in advance what the variable name (var.name) will be (which seems to be the point of the assign function), I can't simply put x <- 6 because var.name might have been "y". So I do:
var.name <- "x"
#some other code...
assign(var.name, 5)
#some more code...
#write a script file (1 line in this case) that works with whatever variable name
write(paste0(var.name, " <- 6"), "tmp.R")
#source that script file
source("tmp.R")
#remove the script file for tidiness
file.remove("tmp.R")
x will be changed to 6, and if the variable name was anything other than "x", that variable will similarly have been changed to 6.
I was working with this a few days ago, and noticed that sometimes you will need to use the get() function to print the results of your variable.
ie :
varnames = c('jan', 'feb', 'march')
file_names = list_files('path to multiple csv files saved on drive')
assign(varnames[1], read.csv(file_names[1]) # This will assign the variable
From there, if you try to print the variable varnames[1], it returns 'jan'.
To work around this, you need to do
print(get(varnames[1]))
If you want to convert string to variable inside body of function, but you want to have variable global:
test <- function() {
do.call("<<-",list("vartest","xxx"))
}
test()
vartest
[1] "xxx"
Maybe I didn't understand your problem right, because of the simplicity of your example. To my understanding, you have a series of instructions stored in character vectors, and those instructions are very close to being properly formatted, except that you'd like to cast the right member to numeric.
If my understanding is right, I would like to propose a slightly different approach, that does not rely on splitting your original string, but directly evaluates your instruction (with a little improvement).
original_string <- "variable_name=\"10\"" # Your original instruction, but with an actual numeric on the right, stored as character.
library(magrittr) # Or library(tidyverse), but it seems a bit overkilled if the point is just to import pipe-stream operator
eval(parse(text=paste(eval(original_string), "%>% as.numeric")))
print(variable_name)
#[1] 10
Basically, what we are doing is that we 'improve' your instruction variable_name="10" so that it becomes variable_name="10" %>% as.numeric, which is an equivalent of variable_name=as.numeric("10") with magrittr pipe-stream syntax. Then we evaluate this expression within current environment.
Hope that helps someone who'd wander around here 8 years later ;-)
Other than assign, one other way to assign value to string named object is to access .GlobalEnv directly.
# Equivalent
assign('abc',3)
.GlobalEnv$'abc' = 3
Accessing .GlobalEnv gives some flexibility, and my use case was assigning values to a string-named list. For example,
.GlobalEnv$'x' = list()
.GlobalEnv$'x'[[2]] = 5 # works
var = 'x'
.GlobalEnv[[glue::glue('{var}')]][[2]] = 5 # programmatic names from glue()

Resources