I am currently taking a Data Structures & Algorithms course, and while learning about Stacks, the instructor has presented a function called check_parens(), which takes an expression as input and checks to see if the parentheses in the expression are well-balanced.
The function is as follows:
def check_parens(expr):
s = Stack()
for c in expr:
if c == '(':
s.push(c)
elif c == ')':
if s.empty() or s.pop()!='(':
return False
return s.empty()
I understand that this function works properly, but I do not understand why "s.pop() != '('" is included in the inner if condition other than to pop off the current element in the stack should it not already be empty. Otherwise, what is the point in checking if an element in the stack is not equal to '('? With this code, the stack will never contain anything but open parentheses.
With this code, the stack will never contain anything but open parentheses.
With this code, yes. But if you for example also allow {} and [], you'll want a check there. Maybe that's your upcoming homework, and they want to be consistent. Or it's just because in general, you don't just store the same value over and over again. Then you could just count up and down instead of using a stack at all. You use a stack when you want to remember different values. But In order to be sure about their motive, you'd have to ask them.
Related
I'm beginner python fan.
Note - I know, one "return" is missing.
Purpose of function: sequences with a repeating beginning are given. We don't know how long these "prefixes" are, but we do know there are 7 different ones (the same length). We need to find these prefixes.
However, I am curious how the program works without that word. Why does the function print sets (last line) - shouldn't it still stop at else: search (...), go back to the top, and throw out just None when set is long enough?
I also noticed that if I put print between 'else:' and 'search(...)', the sets are printed in the normal order, and if under 'search(...)'- in the reverse order (ie from where the words are longest).
I would be grateful if someone could explain why it prints at all and in reverse order :)
def search(seq_list, length, position=1):
seq_set = set()
for a in seq_list:
seq_set.add(a[:position])
if len(seq_set) == length:
return seq_set
else:
search(seq_list, length, position + 1)
print(seq_set)
No, it won't stop. A function doesn't return just because a recursive call returns. search finishes, returns its value, then the caller ignores that value and continues on to print(seq_set).
It's not clear that it "works", since you are printing the local value of seq_set, not the one the recursive call returns and you ignore.
Sometimes inside one function we need to use the return statement several times.
When developer changes a function with multiple returns inside, it's easy to oversee some parts of code where yet another return was "hidden".
If unit tests do not cover all possible paths, disaster is guaranteed - it's only a question of time.
def my_function():
'''Multiple "return" inside'''
if condition 1:
return 1, 2, 3
if condition 2:
return 2, 3, 4
return 5 # this is wrong: only 1 value returned, while 3-tuple expected
Let's assume here: last return is wrong, because other callers expect tuple of 3 items.
I wonder if you know an easy way how to catch such parts of code automatically? I thought I could use AST, but I could not find any useful example of this.
This question is about automatic code analysis and listing such cases found - could be with running a separate script.
Of course I could write a try-to-guess parser (with e.g. regex) and then 'manually' check all unclear cases, but maybe there is a simpler way...
Depending on what version of Python you're using and what you really want to achieve, there are several ways to refactor the code.
One way, as has been already suggested, is to use Type Hints in Python 3.
Another way is refactor your code such that instead of using multiple return statements, you call other more atomic methods that handle those conditions and return the appropriate values. You use exception handling in those atomic methods to make sure the output is as desired, or raise an exception if final return type is unexpected.
def my_function():
'''Multiple "return" inside'''
if condition 1:
output = func_handle_condition_one()
if condition 2:
output = func_handle_condition_two()
output = some_other_value
if type(output) is not tuple:
raise TypeError("Invalid type for output")
return output
Additionally, ensure that you're using the right constructs for your conditions (such as whether you want to use multiple if or the if-elif-else construct). You could even re-factor your calling code to call the right function instead of calling one that has so many conditional statements.
Why not set a variable that gets returned at the end and check for its length
def my_function():
'''Multiple "return" inside'''
return_value=(0,0,0)
if condition 1:
return_value=(1, 2, 3)
elif condition 2:
return_value=(2, 3, 4)
else:
return_value=5 # this is wrong: only 1 value returned, while 3-tuple expected
try:
if len(return_value)==3:
return return_value
else:
print("Error: must return tuple of length 3")
except:
print("Error: must return tuple")
My proposal for the final type check of the result would be:
assert isinstance(return_value, tuple) and len(return_value) == 3
Advantage: as assert is easily switched off after debugging phase; still succinct statement for formulating the expectation.
I created a function in python that will change the priority for the first occurrence of an object, but im having trouble fixing it so that it would only work for the first occurrence without the use of break. In my code below I have used break and it works as intended but I would like to not use it.
def update_priority(self, object, priority):
for i in range(len(self._queue)):
if object == self._queue[i].get_item():
# checking object already has that priority
if priority == self._queue[i].get_priority():
# dont change if it has the priority
pass
# if the object does not have that priority set to new
else:
self._queue[i].set_priority(pri)
break
else:
pass
It sounds like you also want to learn how to reduce the length of the code. A rule of thumb is to concentrate on making your code clear and concise first, so you can try to identify ways to simplify the structure. For example, you can restructure and remove redundant branches. Many of your cases are just passes. Also, yes, college classes say that break statements aren't great. For clarity, you might want to use a conditional variable to end the loop. In this case, you don't really need to do that, but an alternative is to wrap the code in a function and bypass the rest of a loop simply by returning, You already use a function, so you can just return from the function if all you do is update the one item's priority (and exit). Perhaps you want to return a status code indicating that an item was found or not. (True or False).
def update_priority(self, object, priority):
# check all items in the queue (you do not require the index.)
# the entry is stored in "entry"
for entry in self._queue:
# if you find the object and its priority needs an update
if object == entry.get_item() and priority != entry.get_priority():
# set the priority
entry.set_priority(priority)
# return true for success, you found the object and updated it
return True
""" If you arrive at this line, the object didn't exist or
it didn't need an update (if you need to distinguish between "object not found" and
"object found but didn't update," use an extra flag or nest the != entry.get_priority as you did before"""
return False
Your solution is correct you do not need to change it so it doesnt use break. There is no other way to end a loop unless its a while loop and the condition is false or you reach the end of range in a for loop.
I have searched over internet why i should use return False/True over just return but can not find the answer.
Why would i want to have statement return True/False inseatd of just return ?
Can you please show me an example ?
def test(var):
if var > 5:
return True
else:
return False
test(8)
>>> True
#------------------------
def test(var):
if var > 5:
return
else:
return
test(8)
>>> None
Analogy: A function is a cloneable assistant ready to perform a task, and give you an answer. The task is defined by the parameters of the function (the stuff inside the parentheses). Let's rewrite the names to give them semantic meaning (i.e. names which illustrate what we expect).
def isXGreaterThanY(.....
Here, the name of the task is "is X greater than Y?". If you go up to your cloneable assistant and ask "is X greater than Y?", your assistant will not be able to accomplish what you want unless you tell them what X and Y are.
def isXGreaterThanY(x, y):
.........
Now I can start to explain where you may be going wrong. One error at this level of programming is that just because you see something that does almost what one wants on a webpage, one may be tempted to copy it syntactically and try to fiddle around with the syntax and hope it will just work. This will never work. It is not the point of programming.
Some everyday people think that programming is about magic words (not that I am implying you think that) that solve your problem. This is not the case. Rather, programming is (classically) about being able to make automatons (these little assistants) which manipulate information for you. The rote, mechanical manipulation of information is what computers are good at. We want our tasks to be replicable though, so we give them names like "is X greater than Y?", and specify them in what is known, aptly, as procedures (a.k.a. functions).
Let's consider what you wrote:
def isXGreaterThanY(x, y):
if x > y:
return True
else:
return False
A procedure is all about control flow. Each part of the procedure is either a statement or expression (which you can, at this level, consider to be the same thing). A procedure usually has an answer: whenever control flow hits a "return ANSWER" statement, the entire procedure stops (the task is finished) and your magical assistant returns to you with the answer on a piece of paper with ANSWER written on it. A procedure which returns an answer is known as a 'function', and this is almost always what we want (procedures which do ugly 'side-effects' behind the scenes are usually not what we want).
Below, I illustrate the idea that takes us from syntax (what we write down) to mechanical actions. A procedure is made up of syntactic expressions, and each expression may have subexpressions, etc.
We have the if __ then __ else __ statement, which consists of three subexpressions:
the query clause of x > y, which consists of:
the _ > _ operator acting on:
the variable x
the variable y
the "then" clause of return True, which consists of:
the return statement, returning:
the literal boolean value True
the "else" clause of return False, which consists of:
the return statement, returning:
the literal boolean value False
This 'syntax tree' is what the computer sees. Now, the programming language associates meaning to these expressions: it knows how to navigate this tree in what is known as "control flow". In particular, in the programming language Python, we know that when we see an if-then-else statement, that first we check the test condition. In this case we look at the test condition and notice it is a naked comparison (we ask the CPU, and it gives either True or False back). If the comparison is true, we will do the "then" clause, which returns; i.e. hands you a slip of paper with the answer True. If the comparison was false, we'd do the "else" clause, and hand you a slip of paper with the answer False.
In this way, whenever you ask your assistant "is X greater than Y? where X=... and Y=...", your assistant will (in effect) look at the instructions you've specified in the procedure, and interpret them with the assistant's eye being always fixed on one expression at a time (the "control flow" can be thought of as a highlighted or underlined 'active' subexpression, i.e. control flow is the path your assistant's eye takes while looking through the code). In this particular case, your procedure begins with an if-then-else clause, which it interprets as a branching point in the control flow (a fork in the road); it takes the appropriate branch, and in this case, will discover one of the two 'return' statements, and then dutifully give you a slip of paper.
Control flow is determined by the semantics (meaning) behind special control-flow statements, such as if-then-else. Other control flow structures are interpreted differently. for x in range(7): ... will pretend x is 1 and execute ..., pretend x is 2 and execute ..., etc.
A while True: ... will loop forever, performing the ... over and over again.
A break (break out of) means "stop the while loop" or "stop the for loop prematurely".
A continue means "skip the rest of the ... in this while/for loop, but keep on looping".
You can implement your own control flow using the above and your own custom functions, with what is known as recursion (another topic outside this answer's scope).
That is control flow and imperative programming in a nutshell.
By the way, it is better form to do this:
def isXGreaterThanY(x, y):
# this is a comment
# you can insert a print x>y here, or print(x>y) depending on your version of python
return (x > y)
The expression x > y evaluates to True/False before it's fed into the if-then-else statement. So, you could just return the expression as the answer. However, by that point, your function is simple enough that you wouldn't write a function answer:
#print isXGreaterThanY(1,3)
print (1 > 3)
One major problem is that your second function will return None either way. Returning a boolean value is a way to have the return value of your function be meaningful/useful elsewhere.
If it returns a value like True or False, you can in turn use the return value of your function in cases like:
if test(8):
# do something it returns True
else:
# do something otherwise
Otherwise, you function is meaningless because test() will return the same thing regardless of input.
I was once told that a function should either "do something" or "return something". Your second example function, doesn't "do anything", because the > comparison has no effect if you are not making some choice based on the results of that comparison. It also doesn't really return anything (at least not anything meaningful) because it will return None no matter what - in fact, even if you remove the return keyword, it will still just return None.
This question already has answers here:
How to properly ignore exceptions
(12 answers)
Closed 9 years ago.
I have try-except block in python, and I want to do nothing when exception occurs. My code is as follows:
for i in range(len(grid)):
for j in range(len(grid[i])):
try:
count = count > int(grid[i][j]) ? count : int(grid[i][j])
except:
//Do nothing here
How do I do nothing when exception is caught.
Thanks.
pass is the keyword you are looking for.
Let us write the code properly.
We want to iterate over each cell of the grid. So do that. Don't create lists of numbers (range) that you iterate over and then use to index back in. Python's for-loops work directly with the container. It is convenient and easy to understand and good. Don't fight that.
There is no ?: construct in Python. There is a x if y else z construct, but that is not appropriate here. You are clearly trying to set count to the maximum of its current value and the cell value. There is a built-in function for that.
You really want the maximum of all of those cells. So ask for that directly; don't assume that you have to implement the high-water-mark algorithm yourself. You don't. (This also protects you from having to pick an initial value for count, which might be wrong.) We don't need to iterate with an explicit loop for this. We can specify the list of values to pass to max with a generator expression.
You want to "ignore" values that can't be converted to integers. Notwithstanding that there probably is something wrong with your other code if the existence of such values could possibly occur in the first place: we can simply make a test, and filter out the values that fail the test.
Thus:
def is_integral(value):
try:
int(value)
return True
except:
return False
# Now, get the maximum of all the integral values:
count = max(
int(cell) for row in grid for cell in row
if is_integral(cell)
)
You can use pass, but also ... is synonymous in Python 3.x, which can be nice for writing psuedocode.
I see a lot of people use pass where they truly need to do nothing, while using ... where they are using it as a placeholder.
class SomeInterface:
def do_something(self):
pass
class SomeImplementation(SomeInterface):
def do_something(self)
...
This makes it easy to search for ... and find areas where you have unimplemented code, without the false positives from pass.
Note that passing on an exception is generally a bad practice, as you will virtually always want to act on exceptions. You should definitely, at the very least, specify the exact exception(s) you want to catch, as otherwise you will catch all exceptions, potentially causing bugs you can't detect if a different exception rears it's head.
for i in range(len(grid)):
for j in range(len(grid[i])):
try:
count = count > int(grid[i][j]) ? count : int(grid[i][j])
except:
pass
result = x if a > b else y
Is the ternary operator
The do nothing statement is
pass