I have just started to study Python and I am now in the process of doing some exercises.
Specifically, this exercise asks to write a Python program to sum three given integers. However, if two values are equal sum will be zero.
This is my code:
from sys import argv
script, x, y, z = argv
def sum(x, y, z):
if x == y or y == z or x==z:
sum = 0
else:
sum = x + y + z
return sum
print (sum)
I am opening the script in WindowPowerShell specifying the script name (es3.py) and the three variables, e.g: 1 2 3.
However I get the following message:
<function sum at 0x0000000001E0F048>
instead of the result I was expecting.
Does anyone have any ideas of why this is happening?
Thanks.
Let me comment your code:
script, x, y, z = argv
# we now have four new variables inside the main module:
# script, x, y, z
# all functions defined here have access to these but
# cannot modify them (unless we use "global").
def sum(x, y, z):
# while sum() in principle has access to the
# variables defined outside of sum(),
# sum() (the function) also takes three parameters.
# these need to be passed in with a function call
# (i.e. sum(x, y, z)).
#
# x, y, z here are unrelated to x, y, z outside of sum().
# in fact the parameters shadow the global variables,
# making them inaccessible (via direct means).
if x == y or y == z or x==z:
sum = 0
# this defines a local variable "sum".
# it is unrelated to the function "sum"
else:
sum = x + y + z
# x, y, z are strings, so "sum" is now a string, too.
return sum
print (sum)
# here, you refer to the function "sum".
# the variable "sum" only exists inside the function "sum".
If you want the result of sum() (the function), you need call it with parameters:
print(sum(x, y, z))
You cannot access the variable sum outside of the function.
If you
print(sum)
then you print the function sum.
If you want to print the result, you must call sum:
print(sum(x, y, z))
print (sum(x,y,z))
means call your function/method and print the return value.
print (sum)
means print the meta data of your data(sum is also a type of data)
You should print the result of the sum function :
print(sum(x, y, z))
This way the return value of the sum function will be printed out. The way you did it, just prints out a function reference.
Also as a side note, that sum() is a built-in python function, so it's best to avoid naming conflicts and name your functions accordingly.
Try the following code:
from sys import argv
script, x, y, z = argv
def sum_(x, y, z):
if x == y or y == z or x==z:
the_sum = 0
else:
the_sum = int(x) + int(y) + int(z)
return the_sum
print(sum_(x, y, z))
Related
If I define a symbolic expression inside a function, how do I evaluate that expression using .subs() outside that function. The following code demonstrates the issue:
import sympy as sp
def myFun():
x = sp.symbols("x", positive = True)
y = 3*x
return y
expr = myFun()
print(expr.subs({x:10}))
Running the code above gives NameError: name 'x' is not defined.
How can I perform this evaluation? Two things I could think of is declaring x to be a global variable using global x inside myFun(). However, I want to avoid this method. Another way is to lambdify the expression in myFun() before returning the expression. But I would prefer not to use this method because in the real problem I am working with, I have multiple variables in my expression and would like to substitute only some of the variables at one stage, and the remaining variables at a later stage. Would you adopt one of the two approaches I mentioned or is it possible to evaluate the expression using .subs() using some other approach?
#cards answer is not going to work, the reason is that you have defined x to be positive, instead when calling print(expr.subs({'x':10})) the string 'x' will generate a generic symbol, without assumptions.
You either create your symbols outside of the function, like this:
import sympy as sp
x = sp.symbols("x", positive = True)
def myFun():
y = 3*x
return y
expr = myFun()
print(expr.subs({x:10}))
# out: 30
Or you can retrieve the symbols that make up a symbolic expression with the free_symbol attribute, like this:
import sympy as sp
def myFun():
x = sp.symbols("x", positive = True)
y = 3*x
return y
expr = myFun()
x = expr.free_symbols.pop()
print(expr.subs({x:10}))
# out: 30
EDIT (to accommodate comment):
I was just wondering but what if the expression had three variables, say 5*y + 3*x + 7*z? I tried the code you provided. The line expr.free_symbols.pop() only gives one of the variables - it gives x. Is there a way to use free_symbols to get all three variables?
free_symbols returns a set with all variables. If the expression is expr = 5*y + 3*x + 7*z, then expr.free_symbols returns {x, y, z}.
pop() is a method of Python's set: it returns the first element of a set.
To get all the variables of your expression you could try: x, y, z = expr.free_symbols, or x, y, z = list(expr.free_symbols). However, this creates the following problem: execute print(x, y, z) and you'll get something similar to: y z x. In other words, the symbols returned by expr.free_symbols are unordered. This is the default Python behavior.
Can we get ordered symbols? Yes, we can sort them alphabetically with : x, y, z = sorted(expr.free_symbols, key=str). If we now execute print(x, y, z) we will get x y z.
Let's create an expression with two symbols in it:
In [44]: x, y = symbols('x, y')
In [45]: expr = sin(y) + x**2
Suppose that we only have the expression as a local variable. We can find the symbols it contains using free_symbols. We can use that to build a dict that maps symbol names (as strings) to the symbols themselves:
In [46]: expr.free_symbols
Out[46]: {x, y}
In [47]: syms = {s.name: s for s in expr.free_symbols}
In [48]: syms
Out[48]: {'y': y, 'x': x}
This mapping is important because different symbols with the same names but different assumptions are not interchangeable. With that we can substitute the symbol whose name is 'x' like this:
In [49]: expr.subs(syms['x'], 2)
Out[49]: sin(y) + 4
x as a Symbol object is only declared in the function's body, so it's not accessible from the outside. Use 'x' as a string.
x = list(expr.free_symbols)[0]
print(expr.subs({x: 2}))
I have declared global variables that i need to access and modify in a function in a class. This function loops indefinitely once called and stream data passes through it. I need to be able to use x y z variables inside the function, and redefine their values as stream_data comes through.
My current code looks like this:
x = 10
y = 8
z = 2
class Program():
def function(stream_data):
while True:
try:
a = stream_data['data']
if (a - z) > y:
y = a - z
else:
pass
except:
continue
I get error "local variable y defined in enclosing scope on line 7 referenced before assignment".
How can I format this code so that when the function is first called, it uses the global variables, and then on each subsequent calling it uses the variable y it redefined? Thanks I am new to coding and really need help!
Use
global x, y, z to use the global variables
Like This-
x = 10
y = 8
z = 2
class Program():
def function(stream_data):
while True:
try:
global x,y,z
a = stream_data['data']
if (a - z) > y:
y = a - z
else:
pass
except:
continue
Alternatively, you can also initialize x,y,z within your function.
Let me know if this helps!
I have a function that most of the time should return a single value, but sometimes I need a second value returned from the function. Here I found how to return multiple values, but as most of the time I need only one of them I would like to write something like this:
def test_fun():
return 1,2
def test_call():
x = test_fun()
print x
but calling this results in
>>> test_call()
(1,2)
and when trying to return more than two, as in
def test_fun2():
return 1,2,3
def test_call2():
x,y = test_fun2()
print x,y
I get an error
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "my_module.py", line 47, in test_call2
x,y = test_fun2()
ValueError: too many values to unpack
I am thinking about something like in matlab, where x = test_fun() would result in x == 1 (while [x y] = test_fun() would also work as expected). Is something like that possible in python?
You can use star unpacking to gather all additional return values into a list:
x, *y = fun()
x will contain the first return value. y will be a list of the remaining values. y will be empty if there is only one return value. This particular example will only work if the function returns a tuple, even if there is only one value.
When fun always returns 1 or 2 values, you can just do
if y:
print(y[0])
else:
print('only one value')
If, on the other hand, you want to completely ignore the number of return values, do
*x = fun()
Now all the arguments will be gathered into the list. You can then print it with either
print(x)
or
print(*x)
The latter will pass each element as a separate argument, exactly as if you did
x, y, z = fun()
print(x, y, z)
The reason to use *x = fun() instead of just x = fun() is to get an error immediately when a function returns something that isn't a tuple. Think of it as an assertion to remind you to write fun properly.
Since this form of star unpacking only works in Python 3, your only option in Python 2 is to do
x = fun()
and to inspect the result manually.
There are several ways to get multiple return values.
Example 1:
def test_fun():
return 1,2
def test_call():
x, y = test_fun()
print x
print y
you will get correct output:
1
2
When you would like to ignore several return values, you can use * before a variable in python3.
Example 2:
def test_fun2():
return 1,2,3
def test_call2():
x, *y = test_fun2()
print x
print y
you will get the result:
1
(2, 3)
Entering the following code into Python 3.5 shell gives me an answer I didn't expect, very basic I know but would somebody help me with an explanation please.
>>> x = 5
>>> y = 2
>>> a = x*y
>>> x,y,a
(5, 2, 10)
>>> x = 3
>>> x,y,a
(3, 2, 10)
These were all on separate lines each preceded by >>>
I expected 6, but the "new" x has not been used.
The 'a' variable will only be updated if you update it deliberately.
In order to update 'a' after you have changed 'x', you will need to execute the line a = x*y again.
If you copy and paste your code into here http://www.pythontutor.com/visualize.html#mode=edit it will give you a good visualization of what is going on!
a = x*y isn't an equation that automatically updates a whenever you change x or y. It sets a to x*y once when the statement is run. Any changes to x or y afterward have no effect on a.
You'll need to manually update a when you change x or y, or, if the situation allows it, use local functions to do what #Silvio's answer shows. It's handy to create local shortcuts to help clean up code.
When you assign a, the value is set then and there.
a = x * y
The current values of x and y are used. The expression x * y isn't stored anywhere, so Python can't possibly know to update it. If you want a value that automatically updates based on the values of its variables, you can use a closure.
x = 5
y = 2
a = lambda: x * y
print(x, y, a()) # Prints 5 2 10
x = 3
print(x, y, a()) # Prints 3 2 6
This ensures that the expression is evaluated every time a is called.
a variable won't be updated. You may want to create a function this way
def a(x,y):
return x*y
And then you can create the tuple
(x, y, a(x,y))
I have a function that takes 3 keyword parameters. It has default values for x and y and I would like to call the function for different values of z using map. When I run the code below I get the following error:
foo() got multiple values for keyword argument 'x'
def foo(x =1, y = 2, z = 3):
print 'x:%d, y:%d, z:%d'%(x, y, z)
if __name__ == '__main__':
f1 = functools.partial(foo, x= 0, y = -6)
zz = range(10)
res = map(f1, zz)
Is there a Pythonic way to solve this problem?
map(f1, zz) tries to call the function f1 on every element in zz, but it doesn't know with which arguments to do it. partial redefined foo with x=0 but map will try to reassign x because it uses positional arguments.
To counter this you can either use a simple list comprehension as in #mic4ael's answer, or define a lambda inside the map:
res = map(lambda z: f1(z=z), zz)
Another solution would be to change the order of the arguments in the function's signature:
def foo(z=3, x=1, y=2):
You may obtain the equivalent result you expect without using partial:
def foo(x =1, y = 2, z = 3):
print 'x:%d, y:%d, z:%d'%(x, y, z)
if __name__ == '__main__':
f1 = lambda z: foo(x=0, y=-6, z=z)
zz = range(10)
res = map(f1, zz)
Please see this link to have a better understanding: functools.partial wants to use a positional argument as a keyword argument
When trying to call res = map(f1, zz) internally it actually looks like [f1(i) for i in range(10). As you can see you call f1 function with only one positional argument (in this case f1(x=i)). A possible solution would be to do something like this
res = [f1(z=i) for i in range(10)]