What does Pop do in Python
Rough translation - Please send feedback about errors and ambiguities to Mike Müller
18.1 Abstract data types
So far we have only seen specific data types for which we have fully specified how they are implemented. For example, the card class represents a card with 2 integers. As we discussed at the time, this is not the only way to display a map; there are many alternative implementations.
A abstract data type (ADT) specifies a set of operations (or methods) and the semantics of the operations (what they do), it does not specify how they are implemented. That makes it abstract.
Why is this useful?
- The specification of an algorithm becomes easier if one can already designate the necessary operations without having to worry about the operations to be carried out at the same time.
- Since there are typically many ways to implement an ADT, it can be useful to develop an algorithm that can be used with any of the possible implementations.
- Frequently used ADTs, such as the stack discussed in this chapter, are often implemented in standard libraries. In this way they can be used by many programmers.
- The operations on ADT represent a general high-level language for the specification and communication via algorithms.
When we talk about ADT, we often make a distinction between code that uses the ADT, what is called Client code and the code that implemen the DT, the Library code.
18.2 The abstract data type stack
In this chapter we will look at a common ADT, the Stack (eng. pile), employ. A stack is a collection, i.e. a data structure that contains several elements. Other collections we have come across include lists and dictionaries.
An ADT is defined by the operations that can be performed on it. These will interface called. The interface for the ADT stack consists of these operations:
- Initialize a new, empty stack.
- Add a new item to the stack.
- Remove an element from the stack and return it as the result of the method call. The item returned is always the last one added.
- is empty
- Test whether the stack is empty.
A stack is sometimes referred to as a "last in, first out" or LIFO (last in, first out) data structure because the element that was added last is removed first.
18.3 Implementation of stacks with Python lists
The list operations that Python provides are similar to those that define a stack. The interface isn't exactly what it's supposed to be, but we can write code that translates from the ADT stack to built-in operations.
This code we implementation of the ADT stack. In general, an implementation is a set of methods that meet the syntactic and semantic requirements of an interface.
Here is an implementation of the ADT stack using a Python list:
def__init __ (self):
self.items = 
defpush (self, item):
return self.items.pop ()
return (self.items == )
An object stack contains an attribute called items. This was a list of elements in the stack. The initialization method sets items to an empty list.
The push method appends a new element to items and puts it on the stack. To remove an element from the stack, the pop method uses the homonymous * Note list method, with which the last element of the list is removed and returned.
Finally, the method compares isEmptyitems with an empty list to check whether the stack is empty.
An implementation like this, in which the methods consist of simple calls to existing methods, is called a veneer designated. In real life, a veneer is a thin layer of good quality wood that is used in furniture making to hide underlying low quality wood. Computer scientists use this metaphor to describe a small piece of code that hides the details of an implementation and provides a simpler or more standardized interface.
18.4 Laying and fetching
A stack is a generic data typewhich means we can add any type as an element. The following example puts two integers and a string on the stack:
>>> s = Stack ()
>>> s.push (54)
>>> s.push (45)
>>> s.push ("+")
We can use the istEmpty and pop methods to remove all elements and print them out.
while not s.isLeer ():
print s.pop (),
The output looks like this + 45 54. In other words we just used a stack to print the elements backwards! Granted, this isn't the standard format for printing a list, but using a stack made it remarkably easy to implement.
You should compare this short code to the implementation of printBackwaerts in section.
There is a natural parallel between the recursive version printback and the stack algorithms shown here. The difference is that printback uses the Python runtime stack to keep track of the nodes as it goes through the list. On the way back from the recursion, the nodes are then printed out. The stack algorithm does exactly the same thing, with the difference that it uses the stack object instead of the runtime stack.
18.5 Using a stack for evaluating Postfix notations
In most programming languages, mathematical expressions are written with the operator between the two operands, for example 1 + 2. This format is called Infix notation designated. An alternative that is used by some computers becomes Postfix notation called. In postfix notation, the operator follows the operands as in 1 2 +.
The reason that Postfix notation is sometimes useful is that there is a natural way to stack expressions in Postfix notation:
- Starting at the beginning of the expression, take one term (operator or operant) at a time.
- If the term is an operand, put it on the stack.
- If the term is an operator, take two operands off the stack, perform the operations on them, and put the result back on the stack.
- When we get to the end of the expression, there should be exactly one operand left on the stack. This operand is the end result.
Apply this algorithm to the expression 1 2 as an exercise
+ 3 * on.
This example demonstrates one of the advantages of Postfix notation - there is no need to use parentheses to control the order of operations. To get the same result with infix notation we have to (1 + 2) *
As an exercise, write an expression in Postfix notation that corresponds to 1 + 2 * 3.
To implement the previous algorithm we have to go through the string and break it down into operands and operators. This approach is an example of that Parsing. The results of the individual parts of the string are called tokens. You may remember these words from Chapter 1.
Python offers a split method in both the string module and the re module (regular expressions). The string.split function splits a string into a list using a single character as a delimiter. For example:
>>> import string
>>> string.split ("Now is the time", "")
['Now', 'Is', 'The', 'Time']
In this case, the space is required as a separator. The string is consequently split at every space.
The re.split function offers more in that we can use a regular expression instead of a separator. A regular expression allows a set of strings to be specified. For example, [A-z] is the set of all letters (without umlauts and ß) and [0-9] is the set of all digits. The ^ operator negates a set so that [^ 0-9] represents the set of all characters that are not digits. This is exactly the amount we need to break up expressions in Postfix notation:
>>> import right
>>> re.split ("([^ 0-9])", "123 + 456 * /")
['123', '+', '456', '*', '', '/', '']
Note that the order of the arguments differs from that in string.split; the separator comes before the string.
The resulting list contains the operands 123 and 456 and the operators * and /. It also contains two empty strings inserted after the operands.
18.7 Evaluation of Postfix notations
To evaluate expressions in Postfix notation, we will use the parser from the previous section and the algorithm from the previous section. To keep things simple, let's start with an evaluation program that only implements the + and * operators:
tokenList = re.split ("([^ 0-9])", expr)
stack = stack ()
for token in tokenList:
if token == '' or token == '':
if token == '+':
sum = stack.pop () + stack.pop ()
elif token == '*':
product = stack.pop () * stack.pop ()
stack.push (int (token))
return stack.pop ()
The first condition takes care of spaces and empty strings. The next two conditions deal with the operators. We initially assume that everything else must be an operand. Of course, it would be better to check for incorrect input and issue an error message, but we'll get to that later.
We test the whole thing by evaluating the postfix expression (56 + 47) * 2:
>>> print evalPostfix ("56 47 + 2 *")
That's close enough.
18.8 Users and Providers
One of the fundamental goals of ADT is to strictly separate the interests of the provider who writes the code that implements the ADT and the user who applies the ADT. The provider only cares that the implementation is correct in accordance with the specification of the ADT, not how it will be used.
Vice versa goes the user assumethat the implementation is correct and doesn't care about the details. If you use one of the built-in types of Python you have the luxury of thinking solely as a user.
If you are implementing an ADT, you must of course also write the user code to test it. In this case, you play both roles, which can be confusing. You should always try to know what role you are currently playing.
- What would happen if Russia disappeared?
- How much did eBay sell StumbleUpon for?
- Why shouldn't IntelliJ work for me
- Can you smoke Prozac
- Flat roofs are a problem
- You can import Photoshop layers into Nuke
- Pykrete is made from fresh or salt water
- Can Antabuse kill you
- What things about society make you angry
- Why are people against drinking warm cola?
- Where can I learn MuleSoft in India
- How is the cell cycle regulated
- How did math change your life
- What's unfair in the corporate world
- What's your favorite wordless graphic novel
- What are eco-friendly fireworks
- What is code D on W2
- What should I do with inherited stocks
- What is Alan Jackson's most successful song
- Are Ryzen CPUs really better than Intel
- What are the hottest startups in Germany
- What motivates Rupert Murdoch
- There are black holes from Stephen Hawkings
- Where is the Melbourne Convention Center