<jupyter_start><jupyter_text>Strings in (Monty) Python<jupyter_code>import numpy as np<jupyter_output><empty_output><jupyter_text>Strings are just arrays of characters<jupyter_code>my_string = 'spam'

my_string
len(my_string)
my_string[0]
my_string[0:2]
my_string[::-1]<jupyter_output><empty_output><jupyter_text>But unlike numerical arrays, you cannot reassign elements (immutable)<jupyter_code>my_string[0] = "S"<jupyter_output><empty_output><jupyter_text>Or do array-math-like stuff ...<jupyter_code>my_string.sum()<jupyter_output><empty_output><jupyter_text>"Arithmetic" with Strings (concatenate)<jupyter_code>my_string = 'spam'
my_egg = "eggs"

my_string + my_egg
my_string + " " + my_egg
4 * (my_string + " ") + my_egg
print(4 * (my_string + " ") + my_string + " and\n" + my_egg)     # use \n to get a newline with the print function<jupyter_output><empty_output><jupyter_text>String operators and comparisons* String comparison is performed using the characters in both strings.* The characters in both strings are compared one by one (from left to right).* When different characters are found then their [Unicode](https://en.wikipedia.org/wiki/List_of_Unicode_charactersBasic_Latin) value is compared.* The character with lower [Unicode](https://en.wikipedia.org/wiki/List_of_Unicode_charactersBasic_Latin) value is considered to be smaller.<jupyter_code>"spam" == "good"
"spam" != "good"
"spam" == "spam"
"spam" < "eggs"
"sp" < "spam"
"spam_one" < "spam_t"
"sp" in "spam"
"sp" not in "spam"
my_string.isalpha()
my_string.isdigit()
my_string.isspace()<jupyter_output><empty_output><jupyter_text>---- Python supports `Unicode` charactersYou can enter `unicode` characters directly from the keyboard (depends on your operating system), or you can use the `ASCII` encoding. [Unicode - ASCII encoding list](https://en.wikipedia.org/wiki/List_of_Unicode_characters).For example the `ASCII` ecoding for the greek capital omega is `U+03A9`, so you can create the character with `\U000003A9`<jupyter_code>my_resistor = "Spam has an electrical resistance of greater than 100 M\U000003A9"

print(my_resistor)<jupyter_output><empty_output><jupyter_text>These characters can be used as variable names<jupyter_code>Ω = 100e6

Ω * np.pi<jupyter_output><empty_output><jupyter_text>I like to cut and paste from [Symbol Salad](https://symbolsalad.com/)  Python supports (almost) all characters from international keyboards<jupyter_code>movie_title = "Mønti Pythøn ik den <NAME>"

movie_title<jupyter_output><empty_output><jupyter_text>[Emoji](https://en.wikipedia.org/wiki/Emoji) are unicode characters, so you can use them a well (not all OSs will show all characters!)<jupyter_code>radio_active = "\U00002622"
wink = "\U0001F609"

print((radio_active * 5) + " " + (wink * 3))<jupyter_output><empty_output><jupyter_text>Emoji can not be used as variable names (at least not yet ...)<jupyter_code>☢ = 2.345<jupyter_output><empty_output><jupyter_text>Raw strings - `r" "` * Sometime you do not want python to interpret anything in the string * You can do this by adding a "r" to the front of the string<jupyter_code>my_resistor = r"Spam has an electrical resistance of greater than 100 M\U000003A9"

print(my_resistor)<jupyter_output><empty_output><jupyter_text>Watch out for variable types!<jupyter_code>n = 42

print("I would like " + n + " orders of spam")<jupyter_output><empty_output><jupyter_text>---- Python `f-string` formatting<jupyter_code>my_a = 42
my_b = 1.23456
my_c = True
my_d = 'Spam'
type(my_a), type(my_b), type(my_c), type(my_d)
f"I would like {my_a} orders of {my_d}"
my_output = f"I would like {my_a} orders of {my_d}"

print(my_output)<jupyter_output><empty_output><jupyter_text>Format Typesd = Integer decimal                g = Floating point format (Uses exponential format if exponent is less than -4)f = Floating point decimal         x = hexs = String                         o = octale = Floating point exponential     b = binary<jupyter_code>f"The float {my_b} can be printed with only two places after the decimal: {my_b:.3f}"
f"The integer {my_a} can be printed in hex: {my_a:x}, octal: {my_a:o}, or binary: {my_a:b}"
f"The number {my_b} times 1000 in scientific notation: {my_b * 1000 :.2e}"
f"The value {my_c} as a float: {my_c:f}"
f"The value {my_c} as an integer: {my_c:d}"<jupyter_output><empty_output><jupyter_text>---- Who are you who are so wise in the ways of science? Output from `DataFrames - .iterrows()`* A legitimate use of For-Loops<jupyter_code>import pandas as pd
witch_table = pd.read_csv('./Data/Witches.csv')
print(witch_table)
for index, row in witch_table.iterrows():
    my_out_string = (f"The object: {row['Object']} has a density of {row['Density']} g/cc")
    print(my_out_string)<jupyter_output><empty_output><jupyter_text>Padding - `{Variable:N}`* `{row['Object']:8}` - the variable `row['Object']` in 8 spaces* `{row['Density']:5.1f}` - the variable `row['Density']` in 5 spaces with 1 decimal place<jupyter_code>for index, row in witch_table.iterrows():
    my_out_string = (f"The object: {row['Object']:8} has a density of {row['Density']:5.1f} g/cc")
    print(my_out_string)<jupyter_output><empty_output><jupyter_text>Justified Strings - `{Variable:>N}`* By default, the strings are justified to the left, number to the right.* Use the `>` character to right-justify, and `<` to the left justify.* `{row['Object']:>8}` - the variable `row['Object']` right-justified in 8 spaces* `{row['Density']:<5.1f}` - the variable `row['Density']` left-justified in 5 spaces with 1 decimal place.<jupyter_code>for index, row in witch_table.iterrows():
    my_out_string = (f"The object: {row['Object']:>8} has a density of {row['Density']:<5.1f} g/cc")
    print(my_out_string)<jupyter_output><empty_output><jupyter_text>Really long strings* Put everything between `()`* add `\n` for line breaks<jupyter_code>long_string = (
    f"Well, there's egg and bacon; egg sausage and bacon; "
    f"egg and spam; egg bacon and spam; egg bacon sausage and spam; \n"
    f"spam bacon sausage and spam; spam egg spam spam bacon and spam: "
    f"spam sausage spam spam bacon spam tomato and spam; \n"
    f"spam spam spam egg and spam; spam spam spam spam spam spam baked beans spam spam spam \n"
    f"or Lobster Thermidor au Crevette with a Mornay sauce served in a Provencale manner with shallots \n"
    f"and aubergines garnished with truffle pate, brandy and with a fried egg on top and spam."
)
print(long_string)
long_string.count('spam')<jupyter_output><empty_output><jupyter_text>---- Python has lots of built-in [String Methods](https://docs.python.org/3/library/stdtypes.htmlstring-methods).<jupyter_code>my_line = "My hovercraft is full of eels"

my_line<jupyter_output><empty_output><jupyter_text>Find* Returns the index of the first occurrence of the argument in the string* Returns -1 if nothing is found<jupyter_code>my_line.find("r")
my_line[7]
my_line.find("Z")<jupyter_output><empty_output><jupyter_text>Find and Replace<jupyter_code>my_line.replace('is full of eels', 'has no wheels')<jupyter_output><empty_output><jupyter_text>Justification and Cleaning<jupyter_code>my_line.center(100)
my_line.ljust(100)
my_line.rjust(100, "*")
my_line_two = "            My hovercraft is full of eels      "

my_line_two
my_line_two.strip()<jupyter_output><empty_output><jupyter_text>Splitting<jupyter_code>my_line.split()
my_line.split()[1]
my_line.partition('is')
long_string.splitlines()
long_string.splitlines()[2]<jupyter_output><empty_output><jupyter_text>Joining* `string.join(list)`* `string` - the string you want to put between all of the elements of `list`<jupyter_code>'___'.join(my_line.split())
'☢'.join(my_line.partition('is'))
' '.join(my_line.split()[::-1])<jupyter_output><empty_output><jupyter_text>Line Formatting<jupyter_code>my_anotherline = "mY hoVErCRaft iS fUlL oF eEELS"

my_anotherline
my_anotherline.upper()
my_anotherline.lower()
my_anotherline.title()
my_anotherline.capitalize()
my_anotherline.swapcase()
translation = my_anotherline.maketrans("aeiou", "*****")

my_anotherline.translate(translation)<jupyter_output><empty_output><jupyter_text>One last For-Loop thing<jupyter_code>for char in my_anotherline: 
    print(char, end=' ') 
import time
for char in my_anotherline: 
    print(char, end='***')
    time.sleep(.25)       # seconds<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.12648363505574872, 'fraction_numerical': 0.014146984774007913, 'mean_word_length': 6.021885521885522, 'pattern_counts': {'":': 0, '<': 116, '<?xml version=': 0, '>': 114, 'https://': 6, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '27', 'dir': 'jupyter-structured-clean-dedup', 'id': '129377', 'license': 'MIT', 'n_tokens_mistral': 3124, 'n_tokens_neox': 2961, 'n_words': 774, 'path': 'Python_Strings.ipynb', 'repo_name': 'UWashington-Astro300/Astro300-A21', 'size': '8348'}