python functions advanced

Immutable Objects

Earlier, we made a big deal about the fact that lists are mutable. The reason this is important is because certain objects are immutable – once created, their value cannot be changed.

Strings are a prime example of this. Although we treated strings the same as primitives like integers and booleans earlier, strings are actually objects.

Why did we do this? Think about this: if an object is immutable, it doesn't matter whether two variables are pointing to the same string or two different strings with the same value! Thus, while strings are actually immutable objects, we can treat them as we have before – as primitives. The only new meaning this revelation has is that like lists, strings have member functions.

For strings (and tuples, when we get to them), it’s easiest to think of them like primitives – directly stored in the variable table.


Strings Revisited

Most of the member functions in lists modified the list and had no return value. Strings are immutable, though – how do string member functions work? It turns out that member functions of strings tend to return a new string.

Program Text:

message = "Hello"
print(message)
message.lower()  # no effect
print(message)
message = message.lower()
print(message)

Output:

Hello
Hello
hello

Note: lower() is a function that converts a string into lowercase.

Here is a list of some useful string functions. Don't try to memorize these! Even I don't remember them – instead, when I need to look up a function, I go to the Python Quick Reference website shown in class (and on the website).

A quick reminder before starting: remember that "A" and "a" are completely different characters!

When writing functions that manipulate strings, it’s generally a good idea to deal with a single case (usually lowercase).
Functions that return a new string

    str.capitalize() / str.lower() – Returns a copy of str with all letters converted to uppercase/lowercase.
    str.strip() – Returns a copy of str with all whitespace (spaces/tabs/newlines) from the beginning and end of the string removed.
        Example: " test ".strip() → "test".
    str.replace(old, new) – Returns a copy of str with all instances of old within the string replaced with new.
        Example: "hallo all!".replace("al", "el") → "hello ell!".

Functions that return information about a string

    str.count(substring) – Returns the number of times substring appears within str.
    str.find(substring) / str.rfind(substring) – Returns the position of the first instance of substring within str. rfind returns the position of the last instance of substring.
    str.startswith(substring) / str.endswith(substring) – Returns True if the string starts with / ends with substring.
        Example: "Hello".startswith("he") == False, but "Hello".endswith("lo") == True.

Functions that transform the string into other types

    str.split(separator) – Returns a list of words in str, using separator as the delimiter string.
        Example: "hello world, Mihir here".split(" ") → ["hello", "world,", "Mihir", "here"].
        Example: "mississippi".split("s") → ["mi", "", "i", "", "ippi"].
    separator.join(seq) – Takes a list of strings seq and combines them into a string. Each element in seq is separated by separator in the returned string.
        Example: " ".join(["hello","world"]) → "hello world".

Tuples

Tuples are the immutable counterpart of lists. Unlike a list, tuples cannot be changed.

Why/where are tuples useful? Think of a tuple as multi-dimensional data -- just like you can store an integer 5 in a variable, you can also store a two-dimensional coordinate (6, -3). You'll develop an instinct for when to use tuples versus lists as you continue in programming – just remember that it tends to be much easier to use tuples whenever you can get away with it.

You can create tuples by using parentheses:

(1, 3, 8)  # Creates a tuple with elements 1, 3, 8

As you should expect, tuples are ordered:

(1, 3) != (3, 1)

Singleton Tuples:
If you want to create a singleton tuple (a tuple with one element), use:

(5,)  # Note the comma

Nested Tuples

You can nest tuples inside tuples! Example:

((1, 2), 3) != (1, 2, 3)

Common Sequence Operations

Lists, strings, and tuples are all examples of sequences – a series of ordered items. In the case of strings, you can think of them as a sequence of characters.
Operations

    Indexing: seq[i] – Returns the item at index i.
    Length: len(seq) – Returns the length of seq.
    Slicing: "hello"[0:3] == "hel".
    Membership: "ello" in "hello" → True.
    Concatenation: "hello " + "world" → "hello world".
    Repetition: "Yay! " * 5.
    For loops:

    for char in "hello":
        print(char)

Dictionaries

Dictionaries are mutable objects that store key-value pairs.
Example Dictionary:

example_dict = {"a": 5, "test": [1, 2], 27: "Test"}

Dictionaries are unordered, meaning order doesn’t matter.
Basic Dictionary Operations

    Length: len(d) – Returns the number of key-value pairs in d.
    Accessing a value: example_dict["a"] → 5.
    Modifying a value: example_dict["a"] = 7.
    Removing a key: del example_dict["a"].
    Checking key existence:

    27 in example_dict  # True
    5 in example_dict   # False

Dictionary Member Functions

    d.clear() – Removes all items from d.
    d.copy() – Returns a copy of d.
    d.pop(k) – Removes the entry with key k and returns its value.

For Loops and Dictionaries

You can iterate over dictionary keys using a for loop:

example_dict = {"a": 5, "b": True}
for k in example_dict:
    print(k, ";", example_dict[k])

Output:

a ; 5
b ; True

This loops through all the keys and prints both the key and its corresponding value.

Quiz

To mark this module as complete, you must finish this quiz. Once submitted, you'll need to wait 2 hours before attempting it again.