String comparison in Python (exact/partial match, etc.)
This article explains string comparisons in Python, including topics such as exact match, partial match, forward/backward match, and more.
Exact match (equality comparison): == , !=
Partial match: in , not in, forward/backward match: startswith() , endswith(), order comparison: < , <= , > , >=, case-insensitive comparison: upper() , lower(), re.search(), re.fullmatch(), re.ignorecase.
If you want to find the position of a substring in a string, see the following article.
- Search for a string in Python (Check if a substring is included/Get a substring position)
Similar to numbers, the == operator checks if two strings are equal. If they are equal, True is returned; otherwise, False is returned.
This operation is case-sensitive, as are other comparison operators and methods. Case-insensitive comparisons are discussed later.
!= returns True if the two strings are not equal, and False if they are equal.
To check for partial matches, use the in operator, which determines if one string contains another string.
x in y returns True if x is contained in y (i.e., x is a substring of y ), and False if it is not. If the characters of x are found individually in y but not in sequence, False is returned.
not in returns True if the substring is not included, and False if it is included.
in and not in are also used to check the existence of elements in a list. See the following article for details.
- The in operator in Python (for list, string, dictionary, etc.)
For forward matching, use the string method startswith() , which checks if a string begins with the specified string.
- Built-in Types - str.startswith() — Python 3.11.3 documentation
You can also specify a tuple of strings.
True is returned if the string starts with any element of the tuple; otherwise, False is returned. Note that specifying a list instead of a tuple will raise an error.
For backward matching, use the string method endswith() , which checks if a string ends with the specified string. Its usage is the same as startswith() .
- Built-in Types - str.endswith() — Python 3.11.3 documentation
You can compare strings with the < , <= , > , and >= operators, just like numbers. Strings are compared in lexical order.
Characters are compared based on their Unicode code points.
- Unicode/Character reference - Wikibooks, open books for an open world
You can get the Unicode code point of a character with the built-in ord() function.
- Convert Unicode code point and character to each other (chr, ord)
Uppercase English letters have smaller code points than their corresponding lowercase letters in the Unicode standard.
When a list of strings is sorted with the list method sort() or the built-in sorted() function, the order is also determined based on Unicode code points.
- Sort a list, string, tuple in Python (sort, sorted)
All comparison operators and methods described so far are case-sensitive.
For case-insensitive comparisons, use upper() or lower() to convert both strings to uppercase or lowercase.
- Uppercase and lowercase strings in Python (conversion and checking)
Regex: re.search() , re.fullmatch()
Regular expressions allow for more flexible string comparisons.
- Regular expressions with the re module in Python
Use re.search() for partial, forward, and backward matching. Note that re.match() can also be used for forward matching, but it is not discussed here.
While various metacharacters (special characters) can be used in regular expression patterns, you can also directly specify a string without any metacharacters. If the string is included, a match object is returned; otherwise, None is returned. Match objects are always evaluated as True .
- How to use regex match objects in Python
The metacharacter ^ matches the start of the string, and $ matches the end of the string.
In addition, a variety of other metacharacters and special sequences are available.
For example, [A-Z] represents any single uppercase alphabet letter, and + means that the previous pattern is repeated one or more times. Thus, [A-Z]+ matches any substring that consists of one or more consecutive uppercase alphabetic characters.
See the following article for basic examples of regular expression patterns, such as wildcard-like patterns.
- Extract a substring from a string in Python (position, regex)
Use re.fullmatch() to check whether the entire string matches a regular expression pattern. Even if some parts match, None is returned if some parts do not match.
\d represents a number and {n} represents n repetitions. Since backslash \ is used in special sequences of regular expressions, such as \d , it is useful to use raw strings ( r'' or r"" ) that treat backslashes as literal characters.
- Raw strings in Python
re.fullmatch() was added in Python 3.4. In earlier versions, you can use re.search() with ^ and $ to achieve the same result. You can also use re.match() and $ , although it is not shown here.
To perform case-insensitive comparisons, specify re.IGNORECASE as the flags argument for functions like re.search() and re.fullmatch() .
Related Categories
Related articles.
- Remove a substring from a string in Python
- Split a string in Python (delimiter, line break, regex, and more)
- Count characters or substrings in a string in Python
- Replace strings in Python (replace, translate, re.sub, re.subn)
- Get the length of a string (number of characters) in Python
- Convert a list of strings and a list of numbers to each other in Python
- Reverse a list, string, tuple in Python (reverse, reversed)
- Handle line breaks (newlines) in strings in Python
- Convert binary, octal, decimal, and hexadecimal in Python
- Convert between Unicode code point and character (chr, ord)
- Right-justify, center, left-justify strings and numbers in Python
5 Best Ways to Perform String Matching in Python
💡 Problem Formulation: How do you verify if a certain pattern or substring exists within a larger string in Python? For instance, checking if the string “cat” is present within the sentence “The black cat jumped over the lazy dog.” The desired output would be a confirmation that the substring “cat” does indeed occur within the provided input string.
Method 1: Using the in Operator
The in operator is the most straightforward way to check for substring presence in Python. It evaluates to True if the substring is found within the larger string, otherwise it returns False . This method is very readable and easy to use, making it perfect for simple substring searching.
Here’s an example:
This snippet checks if the string “cat” is present in the sentence “The black cat jumped over the lazy dog” by using the in operator, printing True to indicate the presence of the substring.
Method 2: Regular Expressions with re.search()
Python’s re module allows for sophisticated string searching using regular expressions. The re.search() function searches the string for the first occurrence of the pattern provided. It is powerful for pattern-based searches and can handle complex string matching scenarios.
The code uses regular expressions to search for the pattern “cat” within the given text. The re.search() function finds the pattern and returns a match object, which is converted to a Boolean to signify the presence of the substring.
Method 3: String Method find()
The find() method is a string operation that returns the starting index of the first occurrence of a substring. If the substring is not found, it returns -1. It is useful for locating the position of a substring within a string as well as verifying its existence.
This code searches for the substring “cat” using the find() method, which returns the index where “cat” is found within the text. The result is compared against -1 to verify if the substring was found.
Method 4: String Method index()
Similar to find() , the index() method returns the starting index of a substring within a string. The difference is that index() raises a ValueError if the substring is not found, which can be used in try-except blocks to handle the searching operation.
This code uses the index() method to attempt to find “cat” in the text. It uses a try-except block to handle the scenario where “cat” might not be present and would otherwise raise a ValueError.
Bonus One-Liner Method 5: Using List Comprehension and __contains__()
For a concise one-liner approach, one can use list comprehension together with the __contains__() method that underlies the in operator. This method is not commonly used but serves as an alternative one-liner for readability, mostly for Python enthusiasts.
The line of code checks for “cat” inside the list that contains the variable “text” using list comprehension, leveraging the __contains__() method. The any() function then evaluates to True if any of the generated values is True.
Summary/Discussion
- Method 1: Using the in Operator. Simple and concise. Best for basic substring checking. Not suitable for complex patterns.
- Method 2: Regular Expressions with re.search() . Powerful for pattern searching. Can be complex to understand for beginners or complex patterns.
- Method 3: String Method find() . Offers both substring presence and location. Returns -1 if not found, which requires additional check.
- Method 4: String Method index() . Similar to find() with an exception for unfound substrings. Good for control flow with try-except blocks.
- Bonus One-Liner Method 5: Using List Comprehension and __contains__() . More of a Pythonic trick than a practical method. Not recommended for clarity or efficiency.
Handling Wildcard Character Comparisons in Python: A Guide to Matching Strings with SQL-Like Wildcards
In software development, handling wildcard character comparisons is a common challenge, particularly when dealing with string patterns similar to those in SQL's "LIKE" queries. This blog post explores how to implement such comparisons in Python, focusing on a use case involving a list where some entries may contain a wildcard-like symbol '%' representing any series of characters. Our goal is to devise a method that checks a target string against this list, where the presence of '%' influences comparison results.
The Challenge
We have a list of strings, some of which include the '%' character, indicating a wildcard pattern. Our task is to check if a target text does not match any patterns in this list. Specifically, if the target text matches one of these patterns, the function should return False ; otherwise, it should return True .
Example of Expected Behavior:
- Input : newlist = ['test', '%ing', 'osh', '16fg'] , tartext = 'Singing'
- Output : False , since 'Singing' matches with '%ing' where '%' acts as a wildcard.
A Proposed Solution Using Regular Expressions
To solve this problem using regular expressions, we can convert the list's entries containing '%' into RegEx patterns. Here’s a simple approach:
Explanation:
- Each entry with '%' is translated to a regex '.
- Adding r'^' and r'$' ensures that the entire string is matched, not just a substring.
- We use re.search() to find matches of the target string against each converted regex.
- sum() is used to count how many patterns match the target.
Points of Consideration
- Users must handle input strings with regex metacharacters carefully to avoid unwanted matches or crashes.
What if your target string could also contain regex metacharacters? In such scenarios, you'd need to escape these characters in your target string to ensure they are treated literal during matching. The re.escape() method can help:
This updated solution ensures your target text won't inadvertently misbehave as a regex pattern component.
This approach efficiently replicates SQL-like string comparisons in Python using regular expressions, opening the door for complex pattern matching that respects the inclusion of wildcard characters in strings. This method exemplifies Python's capability to handle otherwise complex text processing tasks elegantly.
By embracing Python's rich library support for regular expressions, you can tackle pattern matching challenges with precision and flexibility.
- Python Basics
- Interview Questions
- Python Quiz
- Popular Packages
- Python Projects
- Practice Python
- AI With Python
- Learn Python3
- Python Automation
- Python Web Dev
- DSA with Python
- Python OOPs
- Dictionaries
Pattern matching in Python with Regex
You may be familiar with searching for text by pressing ctrl-F and typing in the words you’re looking for. Regular expressions go one step further: They allow you to specify a pattern of text to search for. In this article, we will see how pattern matching in Python works with Regex.
Regex in Python
Regular expressions , also called regex , are descriptions of a pattern of text. It can detect the presence or absence of a text by matching it with a particular pattern and also can split a pattern into one or more sub-patterns. For example, a \d in a regex stands for a digit character — that is, any single numeral between 0 and 9.
Check Phone Numbers Using Regex In Python
Following regex is used in Python to match a string of three numbers, a hyphen, three more numbers, another hyphen, and four numbers.
Regular expressions can be much more sophisticated. For example, adding a 3 in curly brackets ({3}) after a pattern is like saying, “Match this pattern three times.” So the slightly shorter regex is as follows:
It matches the correct phone number format.
Pattern Matching with Regular Expressions
A Regex object’s search() method searches the string it is passed for any matches to the regex. Match objects have a group() method that will return the actual matched text from the searched string. You can also see Regex cheetsheet for more information.
Example: Import the regex module with import re. Create a Regex object with the re.compile() function. (Remember to use a raw string.) Pass the string you want to search into the Regex object’s search() method. This returns a Match object. Call the Match object’s group() method to return a string of the actual matched text.
Parentheses for Grouping and Capturing with Regex
One of the ways of pattern matching with Regex is by using Parentheses around the patterns. Let us see a few different examples for a better understanding.
Matching Objects
Say you want to separate the area code from the rest of the phone number. Adding parentheses will create groups in the regex: (\d\d\d)-(\d\d\d-\d\d\d\d). Then you can use the group() match object method to grab the matching text from just one group. Python
Retrieve all the Groups at Once
If you would like to retrieve all the groups at once, use the groups(), method—note the plural form for the name. Python
Match a parenthesis
Parentheses have a special meaning in regular expressions, but what do you do if you need to match a parenthesis in your text. For instance, maybe the phone numbers you are trying to match have the area code set in parentheses. In this case, you need to escape the ( and ) characters with a backslash. Enter the following into the interactive shell: Python
The \( and \) escape characters in the raw string passed to re.compile() will match actual parenthesis characters.
Regular Expressions: Grouping and the Pipe Character
The | character is called a pipe. We can use it anywhere we want to match one of many expressions.
Example: The regular expression r’Batman|Tina Fey’ will match either ‘Batman’ or ‘Tina Fey’. When both Batman and Tina Fey occur in the searched string, the first occurrence of matching text will be returned as the Match object.
Understanding Curly Braces in Regex
If we have a group that we want to repeat a specific number of times, follow the group in the regex with a number in curly brackets.
For example, the regex (Ha){3} will match the string ‘HaHaHa’, but it will not match ‘HaHa’, since the latter has only two repeats of the (Ha) group. Instead of just one number, you can specify a range in between the curly brackets. The regex (Ha){3, 5} will match ‘HaHaHa’, ‘HaHaHaHa’, and ‘HaHaHaHaHa’. You can also leave out the first or second number in the curly brackets to leave the minimum or maximum unbounded. (Ha){3, } will match three or more instances of the (Ha) group, while (Ha){, 5} will match zero to five instances. Curly brackets can help make your regular expressions shorter.
Example 1: In this example, we will use curly brackets to specify the occurrence of the pattern which we are looking for.
Example 2: In this example, we will define the occurrence of the pattern using curly brackets and then search for if a specific pattern exists in it or not.
Optional Operator or question mark (?) in Regular Expression
Sometimes there is a pattern that you want to match only optionally. That is, the regex should find a match whether or not that bit of text is there. The “ ?” character flags the group that precedes it as an optional part of the pattern.
Example 1: Here, we will search for a pattern with a pattern ‘Batman’ or ‘Batwoman’. The (wo)? part of the regular expression means that the pattern wo is an optional group. The regex will match text that has zero instances or one instance of wo in it. This is why the regex matches both ‘Batwoman’ and ‘Batman’. You can think of the ? as saying, groups “Match zero or one of the group preceding this question mark.”
If you need to match an actual question mark character, escape it with \?.
Zero or More Pattern Matching with the Star
The * (called the star or asterisk) means “match zero or more” — the group that precedes the star can occur any number of times in the text. It can be completely absent or repeated over and over again. If you need to match an actual star character, prefix the star in the regular expression with a backslash, \*.
Example 1: In this example, we will match the zero occurrences of a pattern in the string. The (wo)* part of the regex matches zero instances of wo in the string.
Example 2: In this example, we will match at least one occurrence of a pattern in the string.
Example 3: In this example, we will match more than one occurrence of a pattern in the string.
One or More Pattern Matching with the Plus
While * means “ match zero or more ,” the + (or plus) means “match one or more.” Unlike the star, which does not require its group to appear in the matched string, the group preceding a plus must appear at least once. It is not optional. If you need to match an actual plus sign character, prefix the plus sign with a backslash to escape it: \+.
Example 1: In this example, we will match at least one occurrence of a pattern in the string.
Example 2: In this example, the regex Bat(wo)+man will not match the string ‘The Adventures of Batman’ because at least one wo is required by the plus sign.
Related Article – Regex Cheetsheet
Similar Reads
Please login to comment..., improve your coding skills with practice.
What kind of Experience do you want to share?
Python Enhancement Proposals
- Python »
- PEP Index »
PEP 636 – Structural Pattern Matching: Tutorial
Matching sequences, matching multiple patterns, matching specific values, matching multiple values, adding a wildcard, composing patterns, or patterns, capturing matched sub-patterns, adding conditions to patterns, adding a ui: matching objects, matching positional attributes, matching against constants and enums, going to the cloud: mappings, matching builtin classes, appendix a – quick intro.
This PEP is a tutorial for the pattern matching introduced by PEP 634 .
PEP 622 proposed syntax for pattern matching, which received detailed discussion both from the community and the Steering Council. A frequent concern was about how easy it would be to explain (and learn) this feature. This PEP addresses that concern providing the kind of document which developers could use to learn about pattern matching in Python.
This is considered supporting material for PEP 634 (the technical specification for pattern matching) and PEP 635 (the motivation and rationale for having pattern matching and design considerations).
For readers who are looking more for a quick review than for a tutorial, see Appendix A .
As an example to motivate this tutorial, you will be writing a text adventure. That is a form of interactive fiction where the user enters text commands to interact with a fictional world and receives text descriptions of what happens. Commands will be simplified forms of natural language like get sword , attack dragon , go north , enter shop or buy cheese .
Your main loop will need to get input from the user and split it into words, let’s say a list of strings like this:
The next step is to interpret the words. Most of our commands will have two words: an action and an object. So you may be tempted to do the following:
The problem with that line of code is that it’s missing something: what if the user types more or fewer than 2 words? To prevent this problem you can either check the length of the list of words, or capture the ValueError that the statement above would raise.
You can use a matching statement instead:
The match statement evaluates the “subject” (the value after the match keyword), and checks it against the pattern (the code next to case ). A pattern is able to do two different things:
- Verify that the subject has certain structure. In your case, the [action, obj] pattern matches any sequence of exactly two elements. This is called matching
- It will bind some names in the pattern to component elements of your subject. In this case, if the list has two elements, it will bind action = subject[0] and obj = subject[1] .
If there’s a match, the statements inside the case block will be executed with the bound variables. If there’s no match, nothing happens and the statement after match is executed next.
Note that, in a similar way to unpacking assignments, you can use either parenthesis, brackets, or just comma separation as synonyms. So you could write case action, obj or case (action, obj) with the same meaning. All forms will match any sequence (for example lists or tuples).
Even if most commands have the action/object form, you might want to have user commands of different lengths. For example, you might want to add single verbs with no object like look or quit . A match statement can (and is likely to) have more than one case :
The match statement will check patterns from top to bottom. If the pattern doesn’t match the subject, the next pattern will be tried. However, once the first matching pattern is found, the body of that case is executed, and all further cases are ignored. This is similar to the way that an if/elif/elif/... statement works.
Your code still needs to look at the specific actions and conditionally execute different logic depending on the specific action (e.g., quit , attack , or buy ). You could do that using a chain of if/elif/elif/... , or using a dictionary of functions, but here we’ll leverage pattern matching to solve that task. Instead of a variable, you can use literal values in patterns (like "quit" , 42 , or None ). This allows you to write:
A pattern like ["get", obj] will match only 2-element sequences that have a first element equal to "get" . It will also bind obj = subject[1] .
As you can see in the go case, we also can use different variable names in different patterns.
Literal values are compared with the == operator except for the constants True , False and None which are compared with the is operator.
A player may be able to drop multiple items by using a series of commands drop key , drop sword , drop cheese . This interface might be cumbersome, and you might like to allow dropping multiple items in a single command, like drop key sword cheese . In this case you don’t know beforehand how many words will be in the command, but you can use extended unpacking in patterns in the same way that they are allowed in assignments:
This will match any sequences having “drop” as its first elements. All remaining elements will be captured in a list object which will be bound to the objects variable.
This syntax has similar restrictions as sequence unpacking: you can not have more than one starred name in a pattern.
You may want to print an error message saying that the command wasn’t recognized when all the patterns fail. You could use the feature we just learned and write case [*ignored_words] as your last pattern. There’s however a much simpler way:
This special pattern which is written _ (and called wildcard) always matches but it doesn’t bind any variables.
Note that this will match any object, not just sequences. As such, it only makes sense to have it by itself as the last pattern (to prevent errors, Python will stop you from using it before).
This is a good moment to step back from the examples and understand how the patterns that you have been using are built. Patterns can be nested within each other, and we have been doing that implicitly in the examples above.
There are some “simple” patterns (“simple” here meaning that they do not contain other patterns) that we’ve seen:
- Capture patterns (stand-alone names like direction , action , objects ). We never discussed these separately, but used them as part of other patterns.
- Literal patterns (string literals, number literals, True , False , and None )
- The wildcard pattern _
Until now, the only non-simple pattern we have experimented with is the sequence pattern. Each element in a sequence pattern can in fact be any other pattern. This means that you could write a pattern like ["first", (left, right), _, *rest] . This will match subjects which are a sequence of at least three elements, where the first one is equal to "first" and the second one is in turn a sequence of two elements. It will also bind left=subject[1][0] , right=subject[1][1] , and rest = subject[3:]
Going back to the adventure game example, you may find that you’d like to have several patterns resulting in the same outcome. For example, you might want the commands north and go north to be equivalent. You may also desire to have aliases for get X , pick up X and pick X up for any X.
The | symbol in patterns combines them as alternatives. You could for example write:
This is called an or pattern and will produce the expected result. Patterns are tried from left to right; this may be relevant to know what is bound if more than one alternative matches. An important restriction when writing or patterns is that all alternatives should bind the same variables. So a pattern [1, x] | [2, y] is not allowed because it would make unclear which variable would be bound after a successful match. [1, x] | [2, x] is perfectly fine and will always bind x if successful.
The first version of our “go” command was written with a ["go", direction] pattern. The change we did in our last version using the pattern ["north"] | ["go", "north"] has some benefits but also some drawbacks in comparison: the latest version allows the alias, but also has the direction hardcoded, which will force us to actually have separate patterns for north/south/east/west. This leads to some code duplication, but at the same time we get better input validation, and we will not be getting into that branch if the command entered by the user is "go figure!" instead of a direction.
We could try to get the best of both worlds doing the following (I’ll omit the aliased version without “go” for brevity):
This code is a single branch, and it verifies that the word after “go” is really a direction. But the code moving the player around needs to know which one was chosen and has no way to do so. What we need is a pattern that behaves like the or pattern but at the same time does a capture. We can do so with an as pattern :
The as-pattern matches whatever pattern is on its left-hand side, but also binds the value to a name.
The patterns we have explored above can do some powerful data filtering, but sometimes you may wish for the full power of a boolean expression. Let’s say that you would actually like to allow a “go” command only in a restricted set of directions based on the possible exits from the current_room. We can achieve that by adding a guard to our case. Guards consist of the if keyword followed by any expression:
The guard is not part of the pattern, it’s part of the case. It’s only checked if the pattern matches, and after all the pattern variables have been bound (that’s why the condition can use the direction variable in the example above). If the pattern matches and the condition is truthy, the body of the case executes normally. If the pattern matches but the condition is falsy, the match statement proceeds to check the next case as if the pattern hadn’t matched (with the possible side-effect of having already bound some variables).
Your adventure is becoming a success and you have been asked to implement a graphical interface. Your UI toolkit of choice allows you to write an event loop where you can get a new event object by calling event.get() . The resulting object can have different type and attributes according to the user action, for example:
- A KeyPress object is generated when the user presses a key. It has a key_name attribute with the name of the key pressed, and some other attributes regarding modifiers.
- A Click object is generated when the user clicks the mouse. It has an attribute position with the coordinates of the pointer.
- A Quit object is generated when the user clicks on the close button for the game window.
Rather than writing multiple isinstance() checks, you can use patterns to recognize different kinds of objects, and also apply patterns to its attributes:
A pattern like Click(position=(x, y)) only matches if the type of the event is a subclass of the Click class. It will also require that the event has a position attribute that matches the (x, y) pattern. If there’s a match, the locals x and y will get the expected values.
A pattern like KeyPress() , with no arguments will match any object which is an instance of the KeyPress class. Only the attributes you specify in the pattern are matched, and any other attributes are ignored.
The previous section described how to match named attributes when doing an object match. For some objects it could be convenient to describe the matched arguments by position (especially if there are only a few attributes and they have a “standard” ordering). If the classes that you are using are named tuples or dataclasses, you can do that by following the same order that you’d use when constructing an object. For example, if the UI framework above defines their class like this:
then you can rewrite your match statement above as:
The (x, y) pattern will be automatically matched against the position attribute, because the first argument in the pattern corresponds to the first attribute in your dataclass definition.
Other classes don’t have a natural ordering of their attributes so you’re required to use explicit names in your pattern to match with their attributes. However, it’s possible to manually specify the ordering of the attributes allowing positional matching, like in this alternative definition:
The __match_args__ special attribute defines an explicit order for your attributes that can be used in patterns like case Click((x,y)) .
Your pattern above treats all mouse buttons the same, and you have decided that you want to accept left-clicks, and ignore other buttons. While doing so, you notice that the button attribute is typed as a Button which is an enumeration built with enum.Enum . You can in fact match against enumeration values like this:
This will work with any dotted name (like math.pi ). However an unqualified name (i.e. a bare name with no dots) will be always interpreted as a capture pattern, so avoid that ambiguity by always using qualified constants in patterns.
You have decided to make an online version of your game. All of your logic will be in a server, and the UI in a client which will communicate using JSON messages. Via the json module, those will be mapped to Python dictionaries, lists and other builtin objects.
Our client will receive a list of dictionaries (parsed from JSON) of actions to take, each element looking for example like these:
- {"text": "The shop keeper says 'Ah! We have Camembert, yes sir'", "color": "blue"}
- If the client should make a pause {"sleep": 3}
- To play a sound {"sound": "filename.ogg", "format": "ogg"}
Until now, our patterns have processed sequences, but there are patterns to match mappings based on their present keys. In this case you could use:
The keys in your mapping pattern need to be literals, but the values can be any pattern. As in sequence patterns, all subpatterns have to match for the general pattern to match.
You can use **rest within a mapping pattern to capture additional keys in the subject. Note that if you omit this, extra keys in the subject will be ignored while matching, i.e. the message {"text": "foo", "color": "red", "style": "bold"} will match the first pattern in the example above.
The code above could use some validation. Given that messages came from an external source, the types of the field could be wrong, leading to bugs or security issues.
Any class is a valid match target, and that includes built-in classes like bool str or int . That allows us to combine the code above with a class pattern. So instead of writing {"text": message, "color": c} we can use {"text": str() as message, "color": str() as c} to ensure that message and c are both strings. For many builtin classes (see PEP 634 for the whole list), you can use a positional parameter as a shorthand, writing str(c) rather than str() as c . The fully rewritten version looks like this:
A match statement takes an expression and compares its value to successive patterns given as one or more case blocks. This is superficially similar to a switch statement in C, Java or JavaScript (and many other languages), but much more powerful.
The simplest form compares a subject value against one or more literals:
Note the last block: the “variable name” _ acts as a wildcard and never fails to match.
You can combine several literals in a single pattern using | (“or”):
Patterns can look like unpacking assignments, and can be used to bind variables:
Study that one carefully! The first pattern has two literals, and can be thought of as an extension of the literal pattern shown above. But the next two patterns combine a literal and a variable, and the variable binds a value from the subject ( point ). The fourth pattern captures two values, which makes it conceptually similar to the unpacking assignment (x, y) = point .
If you are using classes to structure your data you can use the class name followed by an argument list resembling a constructor, but with the ability to capture attributes into variables:
You can use positional parameters with some builtin classes that provide an ordering for their attributes (e.g. dataclasses). You can also define a specific position for attributes in patterns by setting the __match_args__ special attribute in your classes. If it’s set to (“x”, “y”), the following patterns are all equivalent (and all bind the y attribute to the var variable):
Patterns can be arbitrarily nested. For example, if we have a short list of points, we could match it like this:
We can add an if clause to a pattern, known as a “guard”. If the guard is false, match goes on to try the next case block. Note that value capture happens before the guard is evaluated:
Several other key features:
- Like unpacking assignments, tuple and list patterns have exactly the same meaning and actually match arbitrary sequences. An important exception is that they don’t match iterators or strings. (Technically, the subject must be an instance of collections.abc.Sequence .)
- Sequence patterns support wildcards: [x, y, *rest] and (x, y, *rest) work similar to wildcards in unpacking assignments. The name after * may also be _ , so (x, y, *_) matches a sequence of at least two items without binding the remaining items.
- Mapping patterns: {"bandwidth": b, "latency": l} captures the "bandwidth" and "latency" values from a dict. Unlike sequence patterns, extra keys are ignored. A wildcard **rest is also supported. (But **_ would be redundant, so it is not allowed.)
- Subpatterns may be captured using the as keyword: case ( Point ( x1 , y1 ), Point ( x2 , y2 ) as p2 ): ...
- Most literals are compared by equality, however the singletons True , False and None are compared by identity.
- Patterns may use named constants. These must be dotted names to prevent them from being interpreted as capture variable: from enum import Enum class Color ( Enum ): RED = 0 GREEN = 1 BLUE = 2 match color : case Color . RED : print ( "I see red!" ) case Color . GREEN : print ( "Grass is green" ) case Color . BLUE : print ( "I'm feeling the blues :(" )
This document is placed in the public domain or under the CC0-1.0-Universal license, whichever is more permissive.
Source: https://github.com/python/peps/blob/main/peps/pep-0636.rst
Last modified: 2023-09-09 17:39:29 GMT
Powerful Pattern Matching Techniques in Python Revealed
November 11, 2023
Pattern matching is an integral aspect of many programming tasks, from data validation to text extraction. In Python, a language celebrated for its robustness and simplicity, pattern matching takes on a heightened significance due to its extensive applications. When one mentions pattern matching in Python, it immediately brings to mind the use of regular expressions, a powerful tool for identifying and working with specific textual patterns.
Whether you're aiming to validate user input formats, search for specific strings within larger texts, or refactor and reformat large datasets, pattern matching in Python provides the essential functionalities to achieve these tasks efficiently. Through the re module, Python offers a rich set of tools and methods to harness the power of regular expressions, making pattern detection and manipulation both intuitive and effective.
In this tutorial, we will explore the depth and breadth of pattern matching in Python, guiding you through its fundamental concepts, techniques, and real-world applications. As we journey through, you'll discover just how indispensable and versatile pattern matching is in the Python ecosystem.
Python Basics for Pattern Matching
Before diving deep into the intricate world of pattern matching in Python, it's essential to understand the foundational element at its core: strings. Strings form the basis for any pattern matching operation. Knowing how to manipulate and interact with them is the first step towards mastering pattern matching in Python.
Strings in Python:
Strings are sequences of characters and can be thought of as the raw data upon which we apply our pattern matching techniques. In Python, strings are versatile and come with a plethora of built-in methods to aid in text processing. They can be defined using either single (' '), double (" "), or triple (''' ''' or """ """) quotes, providing flexibility in their creation.
Basic String Methods for Pattern Matching in Python:
While dedicated tools and techniques are available for complex pattern matching in Python, understanding basic string methods can often streamline simple text operations, or even complement advanced ones:
- find() : Searches for a specific substring within the string. If found, it returns the starting index of the first occurrence, otherwise -1.
- index() : Similar to find() , but raises an exception if the substring is not found.
- count() : Returns the number of times a substring occurs in the string.
Introduction to Regular Expressions
Regular expressions, often abbreviated as regex or regexp, are sequences of characters that define search patterns. They are a powerful tool in computer science and have vast applications in tasks like text validation, search, extraction, and replacement. When one ventures into the realm of pattern matching in Python, a solid grasp of regular expressions is indispensable.
What are regular expressions?
At their core, regular expressions are a means to describe patterns in text. Instead of searching for a fixed string, regex allows us to specify a pattern, providing flexibility and precision in text processing tasks. For instance, instead of searching for a specific email address, one can use a regex pattern to search for all email addresses in a text.
Basic regex symbols and their meanings:
The following table lists some basic regex symbols, their meanings, and provides a simple example for each:
Python's re Module
Python’s built-in re module provides a consistent interface to work with regular expressions. By utilizing this module, we can effectively conduct pattern matching in Python.
Below is a table summarizing the most common methods provided by the re module:
Flags are modifiers that affect the way in which the regular expression is applied. Some of the commonly used flags include:
This table provides a quick reference for users to understand and effectively use the re module in Python. It offers a concise breakdown of its methods and flags, guiding users in their pattern matching endeavors.
Matching Patterns at the Start or End
When it comes to pattern matching in Python, often there's a need to specifically identify patterns that either start or end a string or line. The re module provides special meta-characters to aid in these scenarios.
1. Match Starting Patterns Using ^
The ^ meta-character is employed to anchor the desired pattern to the beginning of a line or string.
When pattern matching in Python, using the ^ symbol ensures that the regular expression engine searches for matches only at the beginning of the given string or line.
Matching lines that start with a timestamp:
If you're analyzing logs and looking for entries that start with a timestamp pattern such as '2023-10-08 12:34:56', the regex ^2023-10-08 can be used.
Using the regex ^2023-10-08 , the aim is to pinpoint lines that kick off with the date "2023-10-08". The ^ ensures that the match starts at the line's inception, and then the specific date is matched literally. In the supplied Python snippet, if the pattern is located in line_with_timestamp via re.search() , the line's starting timestamp is highlighted; otherwise, it states no timestamp is found at the line's outset.
Identifying lines that commence with a specific word:
To find lines that begin with the word "Error", the pattern ^Error would be apt.
The regex pattern ^Error targets lines initiating with "Error". In this pattern, ^ ensures that the match starts from the beginning of a line, and the word "Error" is looked for verbatim. In the provided Python code, when the re.search() method detects this pattern in the sample string line_with_error , it indicates a match; if not, it specifies that the line doesn't commence with "Error".
2. Match Ending Patterns Using $
The $ meta-character is designated to anchor the desired pattern to the conclusion of a line or string.
While pattern matching in Python, employing the $ symbol ensures that the search is confined to patterns ending a given string or line.
Finding files with specific extensions:
To isolate filenames that conclude with ".pdf", the regex pattern .pdf$ can be utilized.
The regex pattern \.pdf$ is designed to match filenames ending with ".pdf". In this pattern, \. matches a literal dot, since the dot is a special character in regex and needs to be escaped. The string pdf matches the file extension directly, and the $ ensures that this pattern is only matched at the end of a filename.
Locating lines that terminate with punctuation:
If the goal is to detect lines ending with a period or a question mark, the pattern [.?]$ will be effective.
The regex pattern [.?]$ identifies lines that conclude with either a period or a question mark. Here, [.?] is a character class, allowing a match for either of the characters enclosed — in this case, a dot or a question mark. The $ confirms that these characters are positioned at the end of a line.
Searching for Patterns Anywhere in Text
While there are instances where patterns are anchored to the beginning or end of a string, often the requirement is to search for patterns that can appear anywhere within a given text. In such cases, pattern matching in Python provides versatile tools that can spot these patterns, regardless of their position.
1. Using re.search()
The re.search() method is a cornerstone of pattern matching in Python. It scans a string from start to end, looking for any location where the given regex pattern produces a match. If found, it returns a match object; otherwise, it returns None .
Detecting email addresses:
Identifying URLs:
Spotting phone numbers:
2. Using re.findall()
As the name suggests, re.findall() extracts all occurrences of the pattern from the given text. It's a powerful tool when multiple instances of a pattern exist within a string, returning them as a list.
Extracting all hashtags from a tweet:
Retrieving all quoted strings in a text:
Grouping and Capturing Matches
1. basic grouping.
By using parentheses () , pattern matching in Python becomes much more versatile, allowing for the segmentation and extraction of specific portions of a matched pattern.
Separating area codes from phone numbers:
Extracting domain from emails:
2. Named Groups
Named groups, specified by (?P<name>...) , make the pattern matching in Python more readable by providing descriptive names to captured groups.
Parsing log files with named fields:
Suppose we have a log file that follows the format "[TIMESTAMP] - [LOG_LEVEL] - [MESSAGE]" .
In this example of pattern matching in Python, a regular expression (regex) is utilized to parse structured log entries. The given regex pattern, r'\[(?P<timestamp>[\w\s:-]+)\] - \[(?P<log_level>\w+)\] - \[(?P<message>.+)\]' , is a combination of several components tailored to decipher specific segments of the log.
The \[(?P<timestamp>[\w\s:-]+)\] segment of the pattern is crafted to capture timestamps. The square brackets ( [] ) in the log entry are matched literally by using \] and \[ . Inside, (?P<timestamp>[\w\s:-]+) is a named group. The ?P<timestamp> part gives the group a name, "timestamp", which can be later referred to when extracting matched values. The character set [\w\s:-] is designed to match word characters (alphanumeric and underscores with \w ), spaces ( \s ), colons ( : ), and hyphens ( - ). This accommodates common timestamp formats like "2023-10-08 12:34:56".
The next section, \[(?P<log_level>\w+)\] , focuses on matching the log level. Again, literal square brackets are used, and the named group ?P<log_level> will match word characters, capturing log levels like "ERROR", "INFO", or "DEBUG".
Lastly, \[(?P<message>.+)\] is intended to capture the actual log message. The named group ?P<message> utilizes .+ to match one or more of any character, thereby grabbing the entire message, regardless of its specific content.
Using Wildcards and Quantifiers
1. Single Character Wildcard
The dot . is a fundamental tool in pattern matching in Python, as it matches any single character (except for a newline by default). This wildcard can be especially useful when the specific character at a given position is unknown or variable.
Suppose you want to match words like "cat", "cot", "cut", but you're unsure about the middle letter.
2. Specifying Quantity:
Quantifiers help in specifying how many times an element should appear, making pattern matching in Python highly adaptable for a range of scenarios.
Matching repeated characters:
If you want to detect sequences of repeated characters (e.g., "aa", "bbb", "cccc", etc.):
Matching optional segments in patterns:
Suppose you want to match both "color" and "colour":
Using the quantifier ? for pattern matching in Python makes it easy to accommodate variations in spellings or other optional elements.
Character Classes and Sets
1. Using Predefined Classes:
Pattern matching in Python offers predefined character classes, making it easier to match common sets of characters without manually specifying each one.
Matching digits:
The \d class matches any digit from 0 to 9.
Through pattern matching in Python using \d , we can easily extract numbers from a text.
Matching word characters:
The \w class matches alphanumeric characters and underscores.
Using \w for pattern matching in Python is handy for capturing parts of the text containing alphanumeric sequences or usernames.
Matching whitespace:
The \s class matches spaces, tabs, and newlines.
By employing \s in pattern matching in Python, we can detect and count all the whitespace characters in a text.
2. Defining Custom Sets:
With custom sets, pattern matching in Python can be tailored to capture very specific characters.
Matching specific sets of characters, like vowels:
Matching hexadecimal digits:
Advanced Lookaround Techniques
Lookaround assertions in regex do not consume characters in the string but instead assert whether a match is possible at the current position. This capability makes pattern matching in Python more nuanced and context-aware.
1. Lookaheads
Lookaheads allow you to match a pattern only if it is followed (or not followed) by another specific pattern.
1.1 Positive Lookaheads
For instance, if you want to match a dollar amount, but only if it's followed by the word "USD":
1.2 Negative Lookaheads
For example, if you want to match a number not followed by a percent sign:
The regular expression \b\d+\b(?!\s*\%) has been crafted for the specific task of identifying numbers in a text that aren't immediately followed by a percentage sign ( % ). Here's a breakdown:
- \b denotes a word boundary. By placing this on both ends of the \d+ (which matches one or more digits), we ensure that we're capturing complete numbers and not just parts of them. This eliminates scenarios where only a fragment of a number might be captured due to adjacent characters.
- The (?!\s*\%) part is what's called a negative lookahead. This means it checks the subsequent characters after a match, but doesn't actually consume any of them. Specifically, this part of the regex ensures that the number we've matched isn't directly followed by a % sign. The \s* inside the lookahead matches zero or more whitespace characters, which accounts for potential spaces between the number and the percentage sign.
2. Lookbehinds
Lookbehinds work similarly but look behind the current position in the text.
2.1 Positive Lookbehinds
For instance, to extract amounts that are explicitly labeled as "Price:" before them:
2.2 Negative Lookbehinds
For instance, if you want to match numbers that are not preceded by the "#" symbol:
The regular expression (?<!#)\b\d+\b is meticulously designed to pinpoint numbers in a string that aren't directly preceded by the # symbol. Let's dissect its components:
- (?<!#) is termed a negative lookbehind. This component ensures that whatever pattern follows is not directly after a # character in the input string. Specifically, it scans backwards from the current position in the string to check the presence of the specified pattern ( # in this case) and will cause the overall match to fail if it's found.
- \b represents a word boundary. It ensures that the pattern it encloses is seen as a standalone word or entity. In our context, it is used to make certain we capture entire numbers, and not fragments or portions of them.
- \d+ matches one or more digit characters. It's the primary component seeking out sequences of numbers in the string.
Practical Text Manipulation
Pattern matching in Python isn't just about recognizing patterns; it's also a potent tool for text manipulation, enabling tasks like replacement and splitting based on pattern recognition.
1. Text Replacement:
The re.sub() method in Python's re module allows for replacing patterns in strings with specified substitutes.
Reformatting dates:
If you want to change date formats from "MM-DD-YYYY" to "YYYY-MM-DD":
Replacing slang words:
Suppose you want to replace common slang words with their proper forms:
2. Text Splitting:
The re.split() function facilitates breaking down strings based on recognized patterns.
Splitting by multiple delimiters:
To split a string at commas or semicolons:
Breaking a text by sentence end:
To split a paragraph into individual sentences:
Common Pitfalls and Best Practices
Pattern matching in Python, while extremely powerful, can sometimes lead to unexpected results due to nuances in regex syntax and behavior. It's crucial to be aware of these pitfalls and to follow best practices for consistent, accurate results.
Greedy vs Non-Greedy Matching
By default, quantifiers in regex are greedy, meaning they'll match the longest possible string that satisfies the pattern.
Suppose you're trying to extract content between two HTML tags:
This isn't the desired output. To make the matching non-greedy, use ? :
Importance of Escaping in Patterns
Special characters like . or * have specific meanings in regex. If you need to match these characters literally, you should escape them using a backslash ( \ ).
If you're trying to match IP addresses like "192.168.0.1":
Escaping special characters ensures accurate pattern matching in Python, especially when dealing with strings that might contain regex metacharacters.
Pattern matching in Python is a versatile tool that allows users to process and manipulate text data efficiently. We explored foundational concepts, from understanding the basics of strings and the re module to more advanced techniques involving grouping, lookarounds, and practical text manipulation.
Regular expressions provide the backbone for pattern matching, enabling operations like:
- Extracting email addresses, phone numbers, or custom-defined sequences from text.
- Reformatting data for consistency.
- Validating user input, such as checking if a string fits the format of a valid date or URL.
- Advanced textual operations like splitting by multiple delimiters or replacing based on context.
Understanding the intricacies, like greedy vs. non-greedy matching, ensures we avoid common pitfalls and write efficient, performant regex patterns.
For those keen on further expanding their knowledge and proficiency in pattern matching in Python, the following resources come highly recommended:
- Python's Official re Module Documentation : This provides a comprehensive overview of the functions, methods, and intricacies of the re module.
- Regex101 Online Tool : An interactive platform to test and debug regular expressions in real-time. Ensure you select the "Python" flavor for compatibility with the re module.
Deepak Prasad
He is the founder of GoLinuxCloud and brings over a decade of expertise in Linux, Python, Go, Laravel, DevOps, Kubernetes, Git, Shell scripting, OpenShift, AWS, Networking, and Security. With extensive experience, he excels in various domains, from development to DevOps, Networking, and Security, ensuring robust and efficient solutions for diverse projects. You can connect with him on his LinkedIn profile.
Can't find what you're searching for? Let us assist you.
Enter your query below, and we'll provide instant results tailored to your needs.
If my articles on GoLinuxCloud has helped you, kindly consider buying me a coffee as a token of appreciation.
For any other feedbacks or questions you can send mail to [email protected]
Thank You for your support!!
Leave a Comment Cancel reply
Save my name and email in this browser for the next time I comment.
Notify me via e-mail if anyone answers my comment.
We try to offer easy-to-follow guides and tips on various topics such as Linux, Cloud Computing, Programming Languages, Ethical Hacking and much more.
Recent Comments
Popular posts, 7 tools to detect memory leaks with examples, 100+ linux commands cheat sheet & examples, tutorial: beginners guide on linux memory management, top 15 tools to monitor disk io performance with examples, overview on different disk types and disk interface types, 6 ssh authentication methods to secure connection (sshd_config), how to check security updates list & perform linux patch management rhel 6/7/8, 8 ways to prevent brute force ssh attacks in linux (centos/rhel 7).
Privacy Policy
HTML Sitemap
- How it works
- Homework answers
Answer to Question #174129 in Python for CHANDRASENA REDDY CHADA
String Rotation
Given two strings(S1 and S2), write a program to determine if a string S2 is a rotation of another string S1.
The first line of the input will be a string S1.
The second line of the input will be a string S2.Output
If string S2 is a rotation of another string S1, print number of right rotations made by string S1 to match the string S2. Otherwise, print "No Match".
Where right rotation means all elements are moving towards the right side by one place where the last element will be placed in the first place example, one right rotation of "python" is "npytho"
For example, if the given strings S1 and S2 are "python" and "onpyth",
The first right rotation of s1 is "npytho" which is not equal to string S2"onpyth"
The second right rotation of s2 is "onpyth" which is equal to string S2 "onpyth".
So output 2
Sample Input 1
Sample Output 1
Sample Input 2
Sample Output 2
Need a fast expert's response?
and get a quick answer at the best price
for any assignment or question with DETAILED EXPLANATIONS !
Leave a comment
Ask your question, related questions.
- 1. IPL Match DetailsWrite a program that reads all the match outcomes and summarizes the information of
- 2. Smallest Missing NumberGiven a list of numbers, write a program to print the smallest positive integ
- 3. New Year CountdownGiven date-time D, write a program to print the time left for the next New Year.In
- 4. WeekendsGiven two dates D1 and D2, write a program to count the number of Saturdays and Sundays from
- 5. Add two polynomialsGiven two polynomials A and B, write a program that adds the given two polynomial
- 6. Secret Message - 2Given a string, write a program to print a secret message that replaces characters
- 7. Secret Message - 1Given a string, write a program to mirror the characters of the string in alphabet
- Programming
- Engineering
Who Can Help Me with My Assignment
There are three certainties in this world: Death, Taxes and Homework Assignments. No matter where you study, and no matter…
How to Finish Assignments When You Can’t
Crunch time is coming, deadlines need to be met, essays need to be submitted, and tests should be studied for.…
How to Effectively Study for a Math Test
Numbers and figures are an essential part of our world, necessary for almost everything we do every day. As important…
IMAGES
VIDEO
COMMENTS
Reducing Fraction to Lowest TermCreate a Python script that will reduce an input fraction to its low; 4. Kaye Keith C. RudenMachine Problem 3Reducing Fraction to Lowest TermCreate a Python script that will; 5. Create a class in Python called Sorting which takes in a file name as an argument. An object of clas; 6.
Regex: re.search(), re.fullmatch() Regular expressions allow for more flexible string comparisons. Regular expressions with the re module in Python; re.search() Use re.search() for partial, forward, and backward matching. Note that re.match() can also be used for forward matching, but it is not discussed here.. While various metacharacters (special characters) can be used in regular expression ...
Method 2: Regular Expressions with re.search() Python's re module allows for sophisticated string searching using regular expressions. The re.search() function searches the string for the first occurrence of the pattern provided. It is powerful for pattern-based searches and can handle complex string matching scenarios.
This approach efficiently replicates SQL-like string comparisons in Python using regular expressions, opening the door for complex pattern matching that respects the inclusion of wildcard characters in strings. This method exemplifies Python's capability to handle otherwise complex text processing tasks elegantly. By embracing Python's rich ...
In this tutorial, you'll explore regular expressions, also known as regexes, in Python. A regex is a special sequence of characters that defines a pattern for complex string-matching functionality. Earlier in this series, in the tutorial Strings and Character Data in Python, you learned how to define and manipulate string objects.
Following regex is used in Python to match a string of three numbers, a hyphen, three more numbers, another hyphen, and four numbers. Any other string would not match the pattern. \d\d\d-\d\d\d-\d\d\d\d. Regular expressions can be much more sophisticated. For example, adding a 3 in curly brackets ({3}) after a pattern is like saying, "Match ...
On the other hand, re.fullmatch() checks if the entire string is a match, which can again be mimicked by re.search() by prepending \A and appending \Z to whatever pattern used. Below example may help illustrate this point. # prepending \A to pattern makes `search` behave similar to `match`. s1 = '1B10L1'.
The match statement evaluates the "subject" (the value after the match keyword), and checks it against the pattern (the code next to case). A pattern is able to do two different things: Verify that the subject has certain structure. In your case, the [action, obj] pattern matches any sequence of exactly two elements. This is called matching.
Exercise 1B: Create a string made of the middle three characters. Exercise 2: Append new string in the middle of a given string. Exercise 3: Create a new string made of the first, middle, and last characters of each input string. Exercise 4: Arrange string characters such that lowercase letters should come first.
Whether you're aiming to validate user input formats, search for specific strings within larger texts, or refactor and reformat large datasets, pattern matching in Python provides the essential functionalities to achieve these tasks efficiently. Through the re module, Python offers a rich set of tools and methods to harness the power of regular expressions, making pattern detection and ...
Answer to Question #175075 in Python for bhuvanesh. String Rotation. Given two strings (S1 and S2), write a program to determine if a string S2 is a rotation of another string S1. Input. The first line of the input will be a string S1. The second line of the input will be a string S2.Output. If string S2 is a rotation of another string S1 ...
Question #216757. You are given an expression string S which contains expressions that are made of bracket characters {, }, (, ), [, ]. Each expression in the string is separated by space. Two brackets are considered to be a matched pair if an opening bracket (i.e., (, [, or {) occurs to the left of a closing bracket (i.e., ), ], or }) of the ...
This checks to see if the characters in a string match at the start of another string. "abcde".startswith("abc") -> true. "abcde".startswith("bcd") -> false. There is also the endswith() function, for checking at the other end. edited Sep 5, 2013 at 13:30.
Despite the fact that the word secret appears multiple times in the title-case text title_cased_file_content, it never shows up in all lowercase. That's why the check that you perform with the membership operator returns False.Python can't find the all-lowercase string "secret" in the provided text.. Humans have a different approach to language than computers do.
Question #165127. Prefix Suffix. Write a program to check the overlapping of one string's suffix with the prefix of another string.Input. The first line of the input will contain a string A. The second line of the input will contain a string B.Output. The output should contain overlapping word if present else print "No overlapping".Explanation.
16. You are testing against the string minus the last character: >>> '"xxx"'[:-1] '"xxx'. Note how the last character, the ", is not part of the output of the slice. I think you wanted just to test against the last character; use [-1:] to slice for just the last element.
Question #350996. Python. Create a method named check_angles. The sum of a triangle's three angles should return True if the sum is equal to 180, and False otherwise. The method should print whether the angles belong to a triangle or not. 11.1 Write methods to verify if the triangle is an acute triangle or obtuse triangle.
Question #174129. String Rotation. Given two strings (S1 and S2), write a program to determine if a string S2 is a rotation of another string S1. Input. The first line of the input will be a string S1. The second line of the input will be a string S2.Output. If string S2 is a rotation of another string S1, print number of right rotations made ...