python To efficiently use the result of function in if statement - python

Is there any other code form, that one can both use a function in if statement and get the value of function without executing the function twice?
For example,
There exists a function, fun1(arg), which takes an hour to return its result (The result value can be either None or some int)
and I want to do some further calculation(for example get its squared value) only if the result from fun1 is not None.
This will be done by:
result = fun1(arg)
if result:
result = result * result
Is there any shorter form such as
if (result = fun1(arg)):
result = result * result
in python?

It may be more "clean" in a code manner, it is possible in C/C++ to do the 2nd one. Not in Python to the best of my knowledge. Moreover, the two examples you gave have the exact same needs in term of memory and computation. So it would be totally equivalent to use any of these two.
The two are absolutely identical. So my answer would be, go with your first method that you already know how to code 👍.
Do not over complicate when it is not necessary, it is a good piece of advice in general.

This is coming in a future version of python. See the following PEP
https://www.python.org/dev/peps/pep-0572/
It'll be known as an assignment expression. The proposed syntax is like;
# Handle a matched regex
if (match := pattern.search(data)) is not None:
# Do something with match

No you can't do this. Statements in Python not work as expressions in C with ;.

Well the second possible solution you wrote is incorrect since the 'result' variable in the if statement has no preassigned value. I would simply go with the first one...

What you are trying to do in your 2nd code is assignment inside expressions, which can't be done in Python.
From the official docs
Note that in Python, unlike C, assignment cannot occur inside expressions. C programmers may grumble about this, but it avoids a common class of problems encountered in C programs: typing = in an expression when == was intended.
also, see:
http://effbot.org/pyfaq/why-can-t-i-use-an-assignment-in-an-expression.htm

Related

assignment operator for a function return

Clearly, it may not make that much sense to make an assignment to a function return, yet I've just encountered a strange situation and could not find a proper rule for that.
The code below does not run:
def foo():
a = [1,2,3,4,5]
return a
foo()= 10
however,
def foo():
a = [1,2,3,4,5]
return a
foo()[2] = 10
works perfectly. It is not clear to me what is going on here. It looks to me that there is an inconsistency here...
Thanks a lot.
It is not clear to me what is going on here.
It's fairly simple, really; the left-hand-side of an assignment statement is not allowed to just be any kind of expression, but some "kinds" of expression are valid assignment targets, and for those kinds of expression it doesn't matter what kinds of sub-expressions they may have. In your example, the left-hand-side is a subscription, which is a valid assignment target, so it's a syntactically valid assignment statement.
In particular, a subscription has two sub-expressions but it doesn't matter what lexical form those sub-expressions have. For example, the below may look perfectly normal to you, where the first sub-expression foo.bar is an attributeref and the second sub-expression index + 5 is an a_expr:
foo.bar[index + 5] = value
This example probably also looks perfectly normal: the first sub-expression baz[get_x()] is another subscription, and the second sub-expression get_y() is a call.
baz[get_x()][get_y()] = value
As for why it's allowed, the simple reason is that it would be a bit silly and arbitrary for the Python developers to decide on a list of restrictions on the sub-expressions. The meaning of the assignment statement is well-defined so long as the left-hand-side is one of the required lexical forms, so the only reason to impose further restrictions on the sub-expressions of those lexical forms would be to try to prevent mistakes by the programmer.
On the other hand, code like func_call()[index] = value is not necessarily a mistake anyway, because the list that func_call() returns might well be referenced elsewhere, so the mutation will be visible through other references to that list.
In python, not every value can be used of the left side of the assignment (so called lvalue). Basically, only 3 things can be lvalues:
a name, like abc
an attribute any_expression.name
a subscript any_expression[slice]
Other values, like literals, arithmetic expressions, function calls etc cannot be used on the left side:
123 = 123 # no
a + b = 123 # no
func() = 123 # no
See assignment in the grammar spec: https://docs.python.org/3/reference/grammar.html

Basic python question about assignment and changing variable

Extremely basic question that I don't quite get.
If I have this line:
my_string = "how now brown cow"
and I change it like so
my_string.split()
Is this acceptable coding practice to just straight write it like that to change it?
or should I instead change it like so:
my_string = my_string.split()
don't both effectively do the same thing?
when would I use one over the other?
how does this ultimately affect my code?
always try to avoid:
my_string = my_string.split()
never, ever do something like that. the main problem with that is it's going to introduce a lot of code bugs in the future, especially for another maintainer of the code. the main problem with this, is that the result of this the split() operation is not a string anymore: it's a list. Therefore, assigning a result of this type to a variable named my_string is bound to cause more problems in the end.
The first line doesn't actually change it - it calls the .split() method on the string, but since you're not doing anything with what that function call returns, the results are just discarded.
In the second case, you assign the returned values to my_string - that means your original string is discarded, but my_string no refers to the parts returned by .split().
Both calls to .split() do the same thing, but the lines of your program do something different.
You would only use the first example if you wanted to know if a split would cause an error, for example:
try:
my_string.split()
except:
print('That was unexpected...')
The second example is the typical use, although you could us the result directly in some other way, for example passing it to a function:
print(my_string.split())
It's not a bad question though - you'll find that some libraries favour methods that change the contents of the object they are called on, while other libraries favour returning the processed result without touching the original. They are different programming paradigms and programmers can be very divided on the subject.
In most cases, Python itself (and its built-in functions and standard libraries) favours the more functional approach and will return the result of the operation, without changing the original, but there are exceptions.

Is it advisable to use print statements in a python function rather than return

Lets say I have the function:
def function(a)
c = a+b
print(c)
Is it advisable to use the print statement in the function to display output rather than placing a return statement at the end and using the print(function(a))?
Also what implications would there be if I used both a print statement and a return statement in a function to display the same output? Lets imagine I need to show the answer for c and then use the value of c somewhere else. Does this break any coding conventions?
So the highlight of the question isn't the difference between print and return, but rather if it is considered a good style to use both in the same function and if it has a possible impact on a program. For example in:
def function(a)
c = a+b
print(c)
return c
value = function
print(value)
Would the result be two c's? Assume c = 5; therefore, would the output be(?):
5
5
print and return solve two completely different problems. They appear to do the same thing when running trivial examples interactively, but they are completely different.
If you indeed just want to print a result, use print. If you need the result for further calculation, use return. It's relatively rare to use both, except during a debugging phase where the print statements help see what's going on if you don't use a debugger.
As a rule of thumb I think it's good to avoid adding print statement in functions, unless the explicit purpose of the function is to print something out.
In all other cases, a function should return a value. The function (or person) that calls the function can then decide to print it, write it to a file, pass it to another function, etc.
So the highlight of the question isnt the difference between print and
return but rather if it is considered good style to use both in the
same function and its possible impact on a program.
It's not good style, it's not bad style. There is no significant impact on the program other than the fact you end up printing a lot of stuff that may not need to be printed.
If you need the function to both print and return a value, it's perfectly acceptable. In general, this sort of thing is rarely done in programming. It goes back to the concept of what the function is designed to do. If it's designed to print, there's usually no point in returning a value, and if it's designed to return a value, there's usually no point in printing since the caller can print it if it wants.
Well return and print are entirely two different processes.
Whereas print will display information to the user or through the console; and return is used for collecting data from a method that fulfills a certain purpose (to use later on throughout your program).
And to answer your question, I believe it would return the two values; since one prints the c variable itself, and the other returns the value c to present as well? Correct me if I'm wrong.

Why isn't there an ignore special variable in python?

Let's say I want to partition a string. It returns a tuple of 3 items. I do not need the second item.
I have read that _ is used when a variable is to be ignored.
bar = 'asd cds'
start,_,end = bar.partition(' ')
If I understand it correctly, the _ is still filled with the value. I haven't heard of a way to ignore some part of the output.
Wouldn't that save cycles?
A bigger example would be
def foo():
return list(range(1000))
start,*_,end = foo()
It wouldn't really save any cycles to ignore the return argument, no, except for those which are trivially saved, by noting that there is no point to binding a name to a returned object that isn't used.
Python doesn't do any function inlining or cross-function optimization. It isn't targeting that niche in the slightest. Nor should it, as that would compromise many of the things that python is good at. A lot of core python functionality depends on the simplicity of its design.
Same for your list unpacking example. Its easy to think of syntactic sugar to have python pick the last and first item of the list, given that syntax. But there is no way, staying within the defining constraints of python, to actually not construct the whole list first. Who is to say that the construction of the list does not have relevant side-effects? Python, as a language, will certainly not guarantee you any such thing. As a dynamic language, python does not even have the slightest clue, or tries to concern itself, with the fact that foo might return a list, until the moment that it actually does so.
And will it return a list? What if you rebound the list identifier?
As per the docs, a valid variable name can be of this form
identifier ::= (letter|"_") (letter | digit | "_")*
It means that, first character of a variable name can be a letter or an underscore and rest of the name can have a letter or a digit or _. So, _ is a valid variable name in Python but that is less commonly used. So people normally use that like a use and throw variable.
And the syntax you have shown is not valid. It should have been
start,*_,end = foo()
Anyway, this kind of unpacking will work only in Python 3.x
In your example, you have used
list(range(1000))
So, the entire list is already constructed. When you return it, you are actually returning a reference to the list, the values are not copied actually. So, there is no specific way to ignore the values as such.
There certainly is a way to extract just a few elements. To wit:
l = foo()
start, end = foo[0], foo[-1]
The question you're asking is, then, "Why doesn't there exist a one-line shorthand for this?" There are two answers to that:
It's not common enough to need shorthand for. The two line solution is adequate for this uncommon scenario.
Features don't need a good reason to not exist. It's not like Guido van Rossum compiled a list of all possible ideas and then struck out yours. If you have an idea for improved syntax you could propose it to the Python community and see if you could get them to implement it.

input in if condition in python

Can inputting and checking be done in the same line in python?
Eg) in C we have
if (scanf("%d",&a))
The above statement if block works if an integer input is given. But similarly,
if a=input():
Doesn't work in python. Is there a way to do it?
No, Python can't do assignment as part of the condition of an if statement. The only way to do it is on two lines:
a=input()
if a:
// Your code here
pass
This is by design, as it means that assignment is maintained as an atomic action, independent of comparison. This can help with readability of the code, which in turn limits the potential introduction of bugs.
You can't do it. This was a deliberate design choice for Python because this construct is good for causing hard to find bugs.
see #Jonathan's comment on the question for an example

Categories

Resources