class Queue2Stacks(object):
def __init__(self):
# Two Stacks
self.instack = []
self.outstack = []
def enqueue(self,element):
# Add an enqueue with the "IN" stack
self.instack.append(element)
def dequeue(self):
if not self.outstack:
while self.instack:
# Add the elements to the outstack to reverse the order when called
self.outstack.append(self.instack.pop())
return self.outstack.pop()
Can someone please help me understand this question? I don't really understand how does the if not self.outstack work here. I thought the self.outstack start with an empty list, why would it triggers this statement? I also don't understand the while self.instack here, self.instack is a list that we appended from enqueue function right? What would break this while loop?
The if condition you refer to:
if not self.outstack:
...means "if outstack is empty". This is necessary, because the intended action is to pop a value from that stack (see return statement). Now if there is nothing there, we cannot just raise an exception "sorry, nothing there any more", as there might still be values in the other stack : instack. So in that case we need to return a value from that stack: the value we need to return is at the bottom of instack. So we will need to pop all values from that stack, and append them to outstack, which effectively will put them in reverse order: the value that was at the bottom of instack, will end up at the top of outstack, and that is exactly what we want, because we will pop that element as return value.
The while condition is saying: "while there are still values in instack". This is needed, because we want all values to be popped from that stack.
Better understanding of the loop structures may help with this piece of code.
Here's a resource: http://openbookproject.net/thinkcs/python/english3e/conditionals.html
if not (apples >= 5):
print("You have a few apples only.")
is similar to that of:
if (apples <= 5):
print("You have a few apples only.")
the logic gate is a little more deeper with the understanding of "not" as in not a "!" operator. Hope that helps with the understanding of your code.
Related
I am using python 3.8.5 and lark-parser 0.11.2. I have a question about Visitors.
I have a grammar for my needs and Lark is working great. I have a case where,
under some conditions, I want to evaluate a returned parse tree and scan it to
get a, possibly empty, list of variable names appearing in the tree.
A sample expression is:
count + num_items
The parse tree from the expression is:
Tree('add', [Tree('variable', [Token('VARIABLE', 'count')]), Tree('variable', [Token('VARIABLE', 'num_items')])])
I figured that I would write a Visitor class that would scann the tree for variables and store them in an internal list:
from lark import Visitor, v_args
#v_args(inline=True)
class FindVariables(Visitor):
def __init__(self):
super().__init__()
self.variable_list = []
def variable(self, var):
try:
self.variable_list.append(var)
except Exception as e:
raise
I am trying to use it as:
fv = FindVariables()
fv2 = fv.visit(parse_result)
for var in fv.variable_list:
...
The issue I have is that when fv = FindVariables() is executed I get a
TypeError exception:
f() missing 1 required positional argument: 'self'
If I change the call above to:
fv = FindVariables().visit(parse_result)
the statement runs but fv does not "see" variable_list.
I am probably misusing the Visitor class. Is there a best/better way to approach this?
Well, I am answering my question but I am not sure that it is the answer.
I changed Visitor to Transformer in the code block in the question and it just worked.
I am glad that I have a solution but it feels like Visitor should have been the right tool here. Still happy to find out if I am misusing the lib here and if there is a better way.
I have been stuck on this problem for about 1 hour : I want my command while to access in the next block. Case is a class: cases is the object. I made a definition that say on some condition : my object case become NoneType. There is the condition if element_voisin == case to be sure that the element is still a case and not a NoneType. If it's still a case I want to access case.ajouter une mine voisine() but my program won't go in. If you need more information tell me! I relly want this to work please.
for element in coordonnees_voisine:
element_voisin = self.obtenir_case(element[0], element[1])
if element_voisin == case:
case.ajouter_une_mine_voisine()
else:
None
Replace
if element_voisin == case:
with
if element_voisin is case:
When comparing objects, you want to use is, not ==.
Write a function list_files_recursive that returns a list of the paths of all the parts.txt files without using the os module's walk generator. Instead, the function should use recursion. The input will be a directory name.
Here is the code I have so far and I think it's basically right, but what's happening is that the output is not one whole list?
def list_files_recursive(top_dir):
rec_list_files = []
list_dir = os.listdir(top_dir)
for item in list_dir:
item_path = os.path.join(top_dir, item)
if os.path.isdir(item_path):
list_files_recursive(item_path)
else:
if os.path.basename(item_path) == 'parts.txt':
rec_list_files.append(os.path.join(item_path))
print(rec_list_files)
return rec_list_files
This is part of the output I'm getting (from the print statement):
['CarItems/Honda/Accord/1996/parts.txt']
[]
['CarItems/Honda/Odyssey/2000/parts.txt']
['CarItems/Honda/Odyssey/2002/parts.txt']
[]
So the problem is that it's not one list and that there's empty lists in there. I don't quite know why this isn't not working and have tried everything to work through it. Any help is much appreciated on this!
This is very close, but the issue is that list_files_recursive's child calls don't pass results back to the parent. One way to do this is to concatenate all of the lists together from each child call, or to pass a reference to a single list all the way through the call chain.
Note that in rec_list_files.append(os.path.join(item_path)), there's no point in os.path.join with only a single parameter. print(rec_list_files) should be omitted as a side effect that makes the output confusing to interpret--only print in the caller. Additionally,
else:
if ... :
can be more clearly written here as elif: since they're logically equivalent. It's always a good idea to reduce nesting of conditionals whenever possible.
Here's the approach that works by extending the parent list:
import os
def list_files_recursive(top_dir):
files = []
for item in os.listdir(top_dir):
item_path = os.path.join(top_dir, item)
if os.path.isdir(item_path):
files.extend(list_files_recursive(item_path))
# ^^^^^^ add child results to parent
elif os.path.basename(item_path) == "parts.txt":
files.append(item_path)
return files
if __name__ == "__main__":
print(list_files_recursive("foo"))
Or by passing a result list through the call tree:
import os
def list_files_recursive(top_dir, files=[]):
for item in os.listdir(top_dir):
item_path = os.path.join(top_dir, item)
if os.path.isdir(item_path):
list_files_recursive(item_path, files)
# ^^^^^ pass our result list recursively
elif os.path.basename(item_path) == "parts.txt":
files.append(item_path)
return files
if __name__ == "__main__":
print(list_files_recursive("foo"))
A major problem with these functions are that they only work for finding files named precisely parts.txt since that string literal was hard coded. That makes it pretty much useless for anything but the immediate purpose. We should add a parameter for allowing the caller to specify the target file they want to search for, making the function general-purpose.
Another problem is that the function doesn't do what its name claims: list_files_recursive should really be called find_file_recursive, or, due to the hardcoded string, find_parts_txt_recursive.
Beyond that, the function is a strong candidate for turning into a generator function, which is a common Python idiom for traversal, particularly for situations where the subdirectories may contain huge amounts of data that would be expensive to keep in memory all at once. Generators also allow the flexibility of using the function to cancel the search after the first match, further enhancing its (re)usability.
The yield keyword also makes the function code itself very clean--we can avoid the problem of keeping a result data structure entirely and just fire off result items on demand.
Here's how I'd write it:
import os
def find_file_recursive(top_dir, target):
for item in os.listdir(top_dir):
item_path = os.path.join(top_dir, item)
if os.path.isdir(item_path):
yield from find_file_recursive(item_path, target)
elif os.path.basename(item_path) == target:
yield item_path
if __name__ == "__main__":
print(list(find_file_recursive("foo", "parts.txt")))
I wasn't entirely sure how to word this question, so I'll stick with explaining my specific goal.
I'm trying to implement an 'eat' option to a user_input function for a text adventure. I want it to check if the verb is 'eat', check if the item is in the player's inventory, check if the item is consumable or not, and then - my goal - show that the player eats it (and only show it once, see below). The 'eat' option has no functionality as of yet, I'm only testing print statements.
I'm totally aware that the code below is not the most efficient way to handle user input (I'm still tweaking ways to handle input that is unexpected), so I'm 100% open to criticism. This was just my initial way of handling it and I'd like to try to make it work. I have a few other verbs ('go', 'look', 'take', etc.) that work, I'm just having a lot of trouble with 'eat'.
def user_input(self):
player = Player()
while True:
user_input = input("> ").lower()
words = user_input.split(" ")
wordlist = list(words)
verb = wordlist[0]
if len(wordlist) == 2:
noun = wordlist[1]
if noun not in items:
print("Somehow '{}' isn't the right word.".format(noun))
continue
else:
pass
# The above works fine because I don't have
# an issue with any of the other verbs regarding
# that bit of code.
# There's more code between these blocks to:
# handle if the user enters a noun that is > 1 word,
# define a few more verbs,
# then,
if verb == "eat":
for item in player.inventory:
if item.name == noun:
if isinstance(item, Consumable):
print("You eat the {}.".format(noun))
break
else:
print("You can't eat that!")
break
else:
print("You don't have '{}'.".format(noun))
I had to use the for loop (at least, I think I had to) because I'm iterating over a list that has objects in them, not strings, so I couldn't just use
if noun in player.inventory:
(I still tried it a million times though, it took forever to come up with a solution for that problem). Here's my specific example for the code above:
class Fists(Weapons):
def __init__(self):
self.name = "fists"
# more instance variables for Fists()
class LeatherWallet(Classy):
def __init__(self):
self.name = "leather wallet"
# more ...
class Pizza(Consumable):
def __init__(self):
self.name = "pizza"
# more ...
class Player():
def __init__(self):
self.inventory = [Fists(), LeatherWallet(), Pizza()]
# other stuff
*eat fists
You can't eat that!
*eat leather wallet
You don't have 'leather wallet'.
You can't eat that!
*eat pizza
You don't have 'pizza'.
You don't have 'pizza'.
You eat the pizza.
From the looks of it, it has got to be a simple fix, because it's clear what's happening as it iterates over the list. I just don't know how to (or if you can) wrangle a for loop to make it check conditions first then print later. At the risk of sounding dumb, I turn to you all for help!
Thank you, and please let me know if I can make this question/my goal any clearer.
Edit:
Tried to make the goal a little clearer in opening paragraphs.
You're not saying what you want the output to be, but my best guess is you don't want to say "you don't have X" more than once.
One way to do this is to use a flag, initialized to false, set to true when you find the item. When you get out of the loop the flag will tell you if you found it.
Something like this:
if verb == "eat":
found = false
for item in player.inventory:
if item.name == noun:
found = true
if isinstance(item, Consumable):
print("You eat the {}.".format(noun))
break
else:
print("You can't eat that!")
break
if !found:
print("You don't have '{}'.".format(noun))
for loops have else clauses that are run if the loop doesn't exit with a break. The idea is that the loop is looking for an item, will break when it finds it, and the else clause handles the default case where you don't find what you're looking for. The variables used inside the loop are still valid after the loop ends so the found (or defaulted) variable can be used in the next bit of code.
In your case, if you move that final else clause out one level, it will only run if the item is not found. In your example output, the two "you don't have 'pizza1" lines will no longer be printed.
for item in player.inventory:
if item.name == noun:
if isinstance(item, Consumable):
print("You eat the {}.".format(noun))
break
else:
print("You can't eat that!")
break
else:
print("You don't have '{}'.".format(noun))
item = None # <-- you can give a default value if you want to
# use the variable later
Looping through the list is okay until the list gets large. Then you are better off indexing the list with a dict for faster lookup.
self.inventory = dict((item.name, item)
for item in (Fists(), LeatherWallet(), Pizza()))
Then the for loop is replaced with
try:
item = player.inventory[noun]
if isinstance(item, Consumable):
print("You eat the {}.".format(noun))
else:
print("You can't eat that!")
except KeyError:
print("You don't have '{}'.".format(noun))
So, another approach is to just make this work, right?
if noun in player.inventory:
...
You have (at least) two ways to do it.
List comprehension
The first and easy one is using a list comprehension:
inventory_items = [item.name for name in player.inventory]
if noun in inventory_items:
...
That's it.
Custom class
The second one is creating an Inventory class inheriting from list and overriding the __contains__ method so you can compare them however you want.
Something like:
class Inventory(list):
def __contains__(self, item):
"""
Override `list.__contains__`.
"""
# First, check whether `item` is in the inventory.
#
# This is what a normal `list` would do.
if list.__contains__(self, item):
return True
# If we couldn't find the item in the list searching
# the "normal" way, then try comparing comparing it
# against the `name` attribute of the items in our
# inventory.
for inventory_item in self:
# Ensure we can do `inventory_item.name` so we don't get
# an AttributeError.
if 'name' not in dir(inventory_item):
continue
if inventory_item.name == item:
return True
return False
Then you instantiate your inventory like:
self.inventory = Inventory([Fists(), LeatherWallet(), Pizza()])
Remember that Inventory inherits from list, so if you can do list(x) then you should also be able to do Inventory(x) and get a very similar result (depending on how much you override in your class).
You could also get creative and make all items inherit from an Item class where you define the __eq__ method and make Pizza() == 'pizza' to simplify the Inventory comparisons.
I was reading up on questions from a python quiz. Here is the following code and its respective question:
class Player(object):
def __init__(self, name, health):
self._name = name
self._health = health
def get_health(self):
"""Return the players health."""
## LINE ##
What is the required code for ## LINE ## so that the method satisfies the comment?
(a) print(self.health)
(b) return self.health
(c) print(self._health)
(d) return self._health
(e) More than one of the above is correct.
So, I'm wondering, is this question ambiguous?
If I state that a specific function's purpose is to "return the value of x", could that not be interpreted as both literally employing the return command to give x's value and using the print command to display the value.
Both give the same answer at face value in the interpreter.
Of course, things are different if you attempt to manipulate it indirectly:
get_health() * 5 yields a normal output if using return
get_health() * 5 yields an error if using print
So should I always treat 'return something' as actually using the return command?
I suppose print and return would both be viable only if the function's purpose said something like "Display the value in the python interpreter".
The correct answer is simply d): return self._health.
You almost answered your own question. Return in programming parlance means use of (the) return (Python/C/... statement, or an implicit return in other languages, etc).
The point here is that that the comment is meant for programmers, not users.
A print statement would imply something to the user running your program ("return output visible to the user"), but the user will not see or know about that comment.
And, as you already pointed out, the use of returning an actual value allows constructs like get_health() * 5.
Going one small step further, I would expect a printing function to be called print_health(); but that's up to the logic of the programming standard & style that is being used.