Python Extras
The previous chapters cover the core features of Python (as expressed in Auto). But Python has many additional features that are useful and worth knowing. This chapter covers a selection of these extras.
Sets
A set is a collection of elements that is unordered and contains no duplicates. Auto provides HashSet from the standard library.
How It Works
In Auto, HashSet is imported from std::collections. You can create a HashSet from a list literal -- duplicate values are automatically removed. The add and remove methods modify the set in place. Set operations like union (|), intersection (&), difference (-), and symmetric difference (^) work the same way in both Auto and Python.
Note for Python Programmers:
Auto uses
HashSet<str>with explicit type parameters, while Python uses the built-insettype. Auto'sHashSetrequires importing fromstd::collections, but the operations are identical.
Sets are useful for removing duplicates from a collection and for checking membership efficiently. The in operator for sets is generally faster than for lists because sets use hash tables internally.
Counters and defaultdict
Python's collections module provides Counter and defaultdict, which are convenient wrappers around dictionaries. In Auto, you can achieve the same results with regular dictionaries and helper functions.
How It Works
Auto does not have list comprehensions. Instead, you use explicit for loops with append. The resulting Python code from the a2p transpiler also uses for loops rather than comprehensions, which some may find more readable.
For counting, Auto uses the HashMap.get(key, default) pattern instead of Python's Counter. For grouping (the defaultdict pattern), you check if the key exists and initialize it if not.
Note for Python Programmers:
Auto uses
HashMapexplicitly rather than Python'sdict. Thea2ptranspiler converts Auto'sHashMap<K, V>to Python'sdict. While Python hasCounteranddefaultdictfor convenience, Auto achieves the same results with a few extra lines of explicit code.
Conditional expressions
Python has a conditional expression, also called a "ternary operator," which allows you to write an if/else in a single expression. Auto supports the same pattern.
let x = 5
let label = if x < 10 { "low" } else { "high" }
print(label) // lowThe equivalent in Python:
x = 5
label = "low" if x < 10 else "high"
print(label) # lowConditional expressions are often shorter than an if statement, but they are not always easier to read. Use them when the logic is simple and the expression is short.
Named tuples
A named tuple is a tuple where each element has a name. Named tuples are useful when you want a simple object with named attributes, but you don't need the full functionality of a class.
In Auto, you achieve the same thing with a type definition, which is more explicit and provides the same benefits.
How It Works
In Auto, a type definition serves the same purpose as Python's namedtuple. Both provide objects with named attributes. Auto's type is more flexible -- you can add methods, use default values, and define custom behavior.
The a2p transpiler converts Auto's type definitions into Python classes with __init__, __eq__, and comparison methods as needed.
Note for Python Programmers:
Python's
namedtupleis lightweight and immutable. Auto'stypeis also lightweight but is mutable by default. If you want immutability, useletfor the fields. Thea2ptranspiler generates Python classes rather thannamedtupleinstances, giving you more control over behavior.
any and all
Python provides built-in functions any and all that take an iterable of boolean values and return a single boolean result.
anyreturnstrueif at least one element is truthy.allreturnstrueif all elements are truthy.
In Auto, you can use these functions from the standard library, or implement the logic yourself with a loop.
How It Works
Auto's conditional expression syntax is if condition { value1 } else { value2 }, which is similar to Python's value1 if condition else value2 but with the condition first (like an if statement). For chained conditions, Auto nests the expressions naturally.
The any and all functions work the same in both Auto and Python. They take an iterable and return a boolean. In Auto, when you need early termination (like break), you use explicit loops instead of generator expressions.
Note for Python Programmers:
Python's conditional expression puts the value first:
x if condition else y. Auto puts the condition first:if condition { x } else { y }. Python's generator expressions (likeany(x > 0 for x in numbers)) don't have a direct Auto equivalent -- use explicit loops instead.
Debugging
When you are working with sets, dictionaries, and other collections, there are a few common sources of errors:
Mutable default arguments: In Python, using a mutable object (like a list or dict) as a default argument can cause unexpected behavior because the same object is shared across all calls. In Auto, default values are evaluated each time, so this is not an issue.
Set/dict key types: Only immutable types can be used as keys in a dictionary or elements in a set. In Python, this means strings, numbers, and tuples of immutables. Auto follows the same rule -- you cannot use a list as a dictionary key.
Modifying while iterating: Modifying a collection while iterating over it can cause errors or unexpected behavior. If you need to modify a collection during iteration, iterate over a copy.
// WRONG: modifying list while iterating
let mut items = [1, 2, 3, 4, 5]
for item in items {
if item == 3 {
items.remove(item) // undefined behavior!
}
}
// CORRECT: collect items to remove, then remove them
let mut items = [1, 2, 3, 4, 5]
let mut to_remove: [int] = []
for item in items {
if item == 3 {
to_remove.append(item)
}
}
for item in to_remove {
items.remove(item)
}Glossary
set: An unordered collection of unique elements. In Auto, represented by HashSet.
HashSet: Auto's set type, imported from std::collections.
set operation: Operations like union (|), intersection (&), difference (-), and symmetric difference (^) that combine sets.
Counter: A dictionary that maps elements to their frequencies. In Python, provided by collections.Counter. In Auto, implemented with a regular HashMap.
defaultdict: A dictionary that provides a default value for missing keys. In Python, provided by collections.defaultdict. In Auto, implemented with explicit key checking.
list comprehension: A Python expression that creates a list by applying an expression to each element of an iterable, optionally filtered by a condition. Auto uses explicit for loops instead.
conditional expression: An expression that returns one of two values depending on a boolean condition. Also called a "ternary operator."
named tuple: A tuple with named elements. In Auto, achieved with a type definition.
any: A function that returns true if at least one element of an iterable is truthy.
all: A function that returns true if all elements of an iterable are truthy.
Exercises
Exercise 1
Write a function called has_duplicates that takes a list and returns true if any element appears more than once. It should not modify the original list.
Exercise 2
Write a function called word_frequency that takes a string and returns a dictionary that maps each word to the number of times it appears. Convert the string to lowercase and remove punctuation before counting.
Exercise 3
Write a function called unique_words that takes a list of words and returns a list of the unique words in alphabetical order, using a HashSet.
Exercise 4
Python's dict has a method called setdefault that sets a value in a dictionary only if the key is not already present. The equivalent in Auto is:
let mut d: HashMap<str, [int]> = {}
// Instead of d.setdefault(key, []).append(value):
if key not in d {
d[key] = []
}
d[key].append(value)Use this pattern to write a function called invert_dict that takes a dictionary and returns a new dictionary where the keys and values are swapped. If the original dictionary has duplicate values, the inverted dictionary should map each value to a list of keys.