python my note 2024-06-28
python3 -m site âuser-base find out which python path
Python Tutor - Python Online Compiler with Visual AI Help pathrise-eng/pathrise-python-tutor: Visualize Python, Java, JavaScript, TypeScript, Ruby, C, and C++ code execution in your Web browser
python math way Introductory Tutorial - SymPy 1.13.3 documentation SageMath - Open-Source Mathematical Software System Basic Algebra and Calculus - Tutorial
-
Software Design by Example_ A Tool-Based I - Wilson, Greg
éèżćšç»ćŻè§ćæ°æźç»æćçźæł
- VisuAlgo
source code
Problem set: 15-110: Principles of Computing CodingBat Java
Notes or short concepts: 15-112: Fundamentals of Programming
Problem set: CS61A
python â to exe or binary file:
nuitka
- it convert python to c , and then compile it to exe lol
- Python programs, usually short, of considerable difficulty, to perfect particular skills.
my py â stoping variable change its type ((linter usage))
x = """test
or tested
"""
"" is alread a list
- for mulit line
.strip
.find (finding order)
.trim (deleting )
.replace
x = input(âx: â)
y = x + 1
In Python, when we talk about handling strings and manipulating them, two useful methods often come up: strip()
and trim()
. However, itâs important to clarify that in Python, there isnât a built-in function or method explicitly named trim()
, as you might find in other programming languages. Instead, what serves the similar purpose of trimming in Python is the strip()
method. Letâs see what these do:
strip()
The strip()
method is used to remove characters from both the beginning and the end of a string. By default, strip()
removes any whitespace characters, such as spaces, tabs, and newlines. You can also specify a set of characters to be removed by passing them as an argument to the method.
Syntax
string.strip([chars])
string
refers to the string you want to strip characters from.[chars]
is an optional parameter specifying the set of characters you want to remove. If not provided, the method removes whitespace.
Examples
-
Removing whitespace by default:
text = " Hello, World! " trimmed_text = text.strip() print(trimmed_text) # Output: "Hello, World!"
-
Removing specific characters:
text = "xxHello, World!xx" trimmed_text = text.strip('x') print(trimmed_text) # Output: "Hello, World!"
Equivalent of âtrimâ in Python
In other programming languages, trim()
might be a function aimed at doing what strip()
does in Python. If youâre looking for such functionality in Python, strip()
, along with its relatives lstrip()
(for left strip) and rstrip()
(for right strip), will be the methods to use.
To summarize, to trim spaces or specific characters from a string in Python, you would use the strip()
method, or lstrip()
and rstrip()
for more directional control (left or right side of the string, respectively). Thereâs no trim()
function in Python, but strip()
provides the needed functionality.
print(xxx in listname)
it will then print t/f
(hex()) (bin()) x = 10 // 3 â integer number
- uppercase variable name for constant
- abs() absoulte
- round() Built-in Functions â Python 3.12.4 documentation
Search all the pyton module in internet
- like math module
Type conversion
- int(x)
- float()
- bool()
- str()
falsy type: "" 0 [] NONE (same as null) x = input(âWhats your favorite TV Showâ) if x: print(âWow I like that too !â) else: print(âYou have entered nothingâ)
This is an example of the truthiness and falsiness
if user enters nothing it will print out nothing
- bool() if is falsy type , output false
A psuedo code example
if some condition is true: do this elif Some other condition is true: Do this else: do something else
and x and y This returns True if both x and y are true or x or y This returns True if either x or y are true not not x Reverses a result, so if something is True , not turns it False
for loop
for x in range(5): print(x)
for x in range(2,5): print(x) 2,3,4 // last number -1
.startwith
key word argument (2, by =3) def increment(number: int, by: int = 1) â int:
def min_max(numbers):
# Assuming 'numbers' is a list of integers
minimum = min(numbers)
maximum = max(numbers)
# Returning a tuple containing the minimum and maximum
return minimum, maximum # Parentheses optional here: return (minimum, maximum)
numbers = [5, 1, 8, 3, 2]
result = min_max(numbers)
print(result) # Output will be something like (1, 8)
# Or, you can unpack the tuple directly into two variables
min_val, max_val = min_max(numbers)
print(f"The minimum is {min_val} and the maximum is {max_val}") # Output: The minimum is 1 and the maximum is 8
def multiply(*list):
print(list)
multiply(2, 3, 4, 5)
Certainly! Here's the formatted code:
```python
def multiply(*args):
total = 1
for number in args:
total *= number
return total
print(multiply(2, 3, 4, 5))
This code defines a function named multiply
which takes any number of arguments, multiplies them all together, and returns the result. When called with the values 2, 3, 4, and 5, it prints out the product of these numbers.
Study Notes on Keyword Arguments and Dictionaries in Python
Key Concepts
- Variable Number of Arguments: Previous session covered how to pass an arbitrary number of arguments to a function using one asterisk (*).
- Keyword Arguments: This session introduces passing an arbitrary number of keyword arguments using two asterisks (**).
Syntax Overview
- Define a function using
def
, for example,save_user
. - To accept a variable number of keyword arguments, use two asterisks before a parameter name, e.g.,
**user
. - Inside the function, you can access these arguments as if they were in a dictionary.
Example
def save_user(**user):
print(user)
- Calling
save_user(id=1, name="admin")
prints a dictionary with the provided keyword arguments:{'id': 1, 'name': 'admin'}
.
Working with Dictionary
- Data is stored in key-value pairs inside curly braces
{}
. - If youâre familiar with JavaScript, this resembles an object. If not, Python dictionaries will be covered in detail later.
- Access dictionary elements using square bracket notation, like
user['id']
.
Conclusion
- Use two asterisks (**kwargs) to collect keyword arguments into a dictionary within a function.
- This allows passing and handling named data conveniently, facilitating functions that can accept a flexible set of named parameters.
This summarizes the essential points on handling keyword arguments in Python and gives a brief introduction to dictionaries.
Here are concise study notes with a small Python code example to illustrate the difference between local and global variables:
Python Variables: Local vs Global
Local Variables
- Scope: Limited to the function in which they are defined.
- Block Scope: Unlike languages like C# or JavaScript, Python does not have block-level scope. Variables defined inside a block (
if
,for
,while
) are accessible outside the block within the function.
Example:
def greet():
if True:
message = "Hello, Python!"
print(message) # Accessible here
greet() # Prints "Hello, Python!"
Global Variables
- Scope: Accessible throughout the file in which they are declared.
- Usage: Can be read from any function within the file.
Example:
message = "Hello, Global!"
def greet():
print(message) # Accessible and prints the global variable
greet() # Prints "Hello, Global!"
Modifying Global Variables Inside a Function
- Default Behavior: Assigning a new value to a global variable within a function creates a new local variable unless explicitly stated.
- Using
global
Keyword: To modify a global variable inside a function, use theglobal
keyword to refer to the variable.
Example:
message = "a" # Global variable
def greet():
global message # Refer to the global variable
message = "b" # Modify the global variable
greet()
print(message) # Prints "b"
Best Practice
- Avoid Global Variables: They can lead to side effects in other parts of the program.
- Avoid Modifying Global Variables in Functions: Itâs considered a bad practice and can cause unpredictability in your programâs behavior.
These notes outline the key aspects of handling local and global variables in Python, emphasizing best practices against modifying global variables within functions.
Study Notes on List Operations
Accessing List Items
- Utilize square brackets to access specific items in a list by their index.
- Example: Printing
letters[0]
returns the first item in the list. - Negative indices can access items from the end of the list (e.g.,
-1
returns the last item).
Modifying List Items
- Square brackets can also be used to modify items in a list.
- Example: Changing the first letter to a capital âAâ.
Slicing Lists
- Similar to strings, lists can be sliced using
[start_index:end_index]
. - Omitting
start_index
assumes0
; omittingend_index
uses the listâs length by default. - Slicing does not alter the original list but returns a new list based on the specified range.
- A step can be included in slicing to skip elements (e.g.,
[::2]
returns every second item).
Advanced Slicing Techniques
- Using a negative step (e.g.,
[::-1]
) reverses the order of the list. - Creating a new list with a range (e.g.,
list(range(20))
) and then slicing it can efficiently generate sequences like even numbers.
Unpacking Lists
- The next topic to explore is unpacking lists, which allows for assigning elements of a list to separate variables directly.
These notes summarize the basics of accessing, modifying, and slicing lists in Python, along with introducing some advanced techniques for list manipulation.
# 03 List Unpacking
numbers = [1, 2, 3]
print(numbers)
# Assigning an item of a list to a variable
# first = numbers[0]
# second = numbers[1]
# third = numbers[3]
# The best way to this is by list unpacking
first, second, third = numbers
print(first)
print(second)
print(third)
# this is the same as the code in lines 6, 7, 8. The number of item in the left side of = most be the same as th number of items in the lis.
# If we have alist with a lot of item and we just want to unpack the first two item and pack the rest os item in another list
numbers_0_19 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
print(numbers_0_19)
first, second, *others = numbers_0_19
print(first)
print(second)
print(others)
# For example if we want the unpack the first and the the last item
first, *others, last = numbers_0_19
print(first)
print(others)
print(last)
looping over lists
# 04 Looping over Lists
letters = ["a", "b", "c", "d"]
for letter in letters:
print(letter)
# to get the index of each item use the built in function enumerate()
for letter in enumerate(letters):
print(letter)
# we get a Tuple with two item the first the index , second the item it self
for index, letter in enumerate(letters):
print(index, letter)
output:
a
b
c
d
(0, 'a')
(1, 'b')
(2, 'c')
(3, 'd')
0 a
1 b
2 c
3 d
05 Adding or Removing Items
# 05 Adding or Removing Items
letters = ["a", "b", "c", "d", "e", "f", "g"]
print(letters)
# Add an item to the end of the list
letters.append("h")
print(letters)
# Add item at a specific position using the method insert()
# first argumet position of the list, second argument iem to add
letters.insert(2, "-")
print(letters)
# Remove an item of a list use the method pop()
# with no argument it removes the last item
letters.pop()
print(letters)
# with a argument it removes the item with that index
letters.pop(2)
print(letters)
# Remove an item for a lsi using the method remove()
# specify the item
letters.remove("c") # this will remove the first "c" in the list
print(letters)
# if there were multiple "c" we need to loop over the list
# Remove item using the del statement
# we this statement we can rmove one item or a range of items by theer index
del letters[0:2]
print(letters)
# to clear the list and delete all the items use the method clear
letters.clear()
print(letters)
- append , adding from the last
- pop, deleting from the last, // could use index way as well
- insert (index, value)
- remove , remove the value(not knowing the index is )
del letters [0:3]
could delete range of itemsletters.clear
clear all letters.count , counting how many times that item occurif "d" in letters: print(letter.index("d"))
sorting
# 07 Sorting Lists
numbers = [5, 51, 2, 15, 6]
print(numbers)
# sort numbers in use the sort() method
numbers.sort()
print(numbers)
numbers.sort(reverse=True)
print(numbers)
# The sort function can be used an it will creat a new list
print(sorted(numbers))
print(sorted(numbers, reverse=True))
# List of complex objects, like a list of tuples, example a list of orders with product name and price
# in situations like this we need to define a function to sort the list, the above methods don't work
items = [
("Product1", 15),
("Product2", 50),
("Product3", 5)
]
print(items)
# In this example we are going to sort the items base in price
def sort_items_price(index):
return index[1]
# if each item in the list is a tuple we are returning the second item in the tuple
items.sort(key=sort_items_price)
print(items)
.sort
- this will change the list order from the original sorted()
- this will not.
# 08 Lambda Functions
# List of complex objects, like a list of tuples, example a list of orders with product name and price
# in situations like this we need to define a function to sort the list, the above methos don't work
items = [
("Product1", 15),
("Product2", 50),
("Product3", 5)
]
print(items)
# In this exeample we are going to sort the items base in price
def sort_items_price(index):
return index[1]
#if each item in the list is a tuple we are returning the second item in the tuple
# items.sort(key=sort_items_price)
# print(items)
# with a lambda or anonymous functions it's short and cleaner way to define a function that we are going to use only once as an argument of another function.
items.sort(key=lambda index: index[1]) # lambda parameter_list: expression
print(items)
Certainly, hereâs a small study note in markdown format that encapsulates the essence of lambda expressions in Python, particularly focusing on their utility in simplifying code blocks that require functions as arguments:
Python Lambda Expressions
Lambda expressions, or lambda functions, are a staple of many programming languages. In Python, they provide a way to create small, one-line anonymous functions. These functions are particularly useful when you need to pass a function as an argument to another function, but wish to avoid the verbosity of traditional function definitions.
Example: Simplifying Sorting
Consider you have a list of items you wish to sort based on one of their properties, such as price. Traditionally, you might define a separate function to express the sorting criterion:
# Traditional function definition
def sort_item(item):
return item[1]
items = [(1, 10), (2, 5), (3, 7)]
items.sort(key=sort_item)
Using Lambda Expressions
Lambda expressions can condense the above code, making it cleaner and more readable. A lambda function can replace the sort_item
function entirely:
# Using a lambda expression
items = [(1, 10), (2, 5), (3, 7)]
items.sort(key=lambda item: item[1])
Syntax
The syntax for lambda expressions in Python is straightforward:
lambda parameters: expression
parameters
is the list of parameters, just like in a standard function definition. These are the inputs to your lambda function.expression
is a single expression that the function evaluates and returns. This expression cannot contain statements or multiple expressions.
Advantages of Lambda
- Conciseness: Lambda expressions allow you to define functions in a single line.
- Anonymity: They are anonymous; you do not need to give them a name.
- No Need for
return
: The expression is automatically returned by the lambda function.
Use Case
Lambda expressions shine in scenarios where you need a simple function for short-term use, particularly as arguments to functions like sort()
, filter()
, map()
, etc., where defining a separate, named function would be cumbersome and unnecessary.
# Sorting items by price using lambda
items.sort(key=lambda item: item[1])
# Output: [(2, 5), (3, 7), (1, 10)]
print(items)
By adopting lambda expressions, Python code can be made more readable and brief, especially for small, single-use functions passed to other functions.
This note should help you quickly grasp what lambda expressions are and how to utilize them to write cleaner and more efficient Python code.
Map
Sure, Iâll condense the information into a concise markdown study note focusing on the use of Lambda expressions with the map()
function in Python for transforming lists.
Transforming Lists with Lambda and map()
Pythonâs versatility is showcased in its ability to transform data structures efficiently. Lambda expressions, combined with the map()
function, offer a robust solution for modifying lists without verbose loops. Letâs explore how to use these tools to transform a list of tuples into a list of prices.
Example: Extracting Prices from Tuples
Consider a list where each element is a tuple representing an item, where the first element is an item ID and the second is its price. The goal is to extract just the prices into a new list.
Traditional Approach
Normally, you might loop through each tuple, extracting the price, and appending it to a new list:
items = [(1, 10), (2, 5), (3, 7)]
prices = []
for item in items:
prices.append(item[1])
print(prices) # Output: [10, 5, 7]
Using map()
and Lambda Expressions
The map()
function offers a more elegant solution. It applies a given function to each item of an iterable and returns a map object.
items = [(1, 10), (2, 5), (3, 7)]
prices = list(map(lambda item: item[1], items))
print(prices) # Output: [10, 5, 7]
Syntax
map()
takes two main arguments:
- A function to apply to each item. This is where lambda expressions shine.
- An iterable (e.g., list, tuple).
Advantages of Using map()
with Lambda
- Conciseness: Achieving the same result in fewer lines of code.
- Readability: Expressing the transformation logic succinctly.
- Efficiency:
map()
is often faster for large datasets.
Example
Transforming a list of tuples into a list of the second elements (prices) in the tuples:
# Transforming a list with map() and lambda
items = [(1, 10), (2, 5), (3, 7)]
prices = list(map(lambda item: item[1], items))
print(prices) # Output: [10, 5, 7]
By combining lambda functions with the map()
function, weâve succinctly transformed our list of tuples into a list of prices.
This note encapsulates how to leverage Pythonâs lambda expressions and the map()
function to efficiently transform lists, demonstrating a practical scenario of extracting prices from a list of tuples.
the code:
# 09 Map Function
items = [
("Product1", 15),
("Product2", 50),
("Product3", 5)
]
print(items)
# Transform this list in a simple list of numbers, with just the price
# prices = []
# for index in items:
# prices.append(index[1])
# print(prices)
# there is a better more cleaner way to achive the same result with the map() function
prices = map(lambda index: index[1], items)
print(prices)
for index in prices: # this way we loop the map function
print(index)
# to create a list with just the prices use the list function
prices = list(map(lambda index: index[1], items))
print(prices)
- map with lambda is still a itterable, so we will have to for loop it , or just use list() function
Question and Answer
Function Definitions [5.9] Write a function named right_justify that takes a string named s as a parameter and prints the string with enough leading spaces so that the last letter of the string is in column 70 of the display.
def right_justify(s): lengthOfs = len(s) remainingSpaces = 70 - lengthOfs print(remainingSpaces * â â + s)
def squareParameter(x): return x*4 # Remember a squareâs sides are all equal
def area(x): print(x**x)
[5.16] Write a function that takes as a parameter the radius of a circle and prints the perimeter of the circle.
This is an example of a function definition:
import math
def perimeterCircle(r): print(2rmath.pi)
[5.17] Write a function that takes as a parameter the radius of a circle and returns the area of the circle.
This is an example of a function definition:
import math
def areaCircle(r): return rrmath.pi
[5.18] Write a function that takes as a parameter the two sides of a rectangle, prints the perimeter of the rectangle, and returns the area of the rectangle.
This is an example of a function definition:
def rectangleFun(w, h): print(w2 + h2) return w*h
[5.19] Write a function dice(n) which simulates a dice roll for a dice with n sides and prints the result. Hint: Using the random library is helpful here! Call the function with 3 different values of n and see the results!
This is an example of a function definition:
import random
def dice(n): roll = random.randint(1, n) # remember randint is inclusive [1,n] return roll
print(dice(6)) # 6 sided die print(dice(12)) # 12 sided die print(dice(22)) # 22 sided die
Short-Circuit Evaluation :
and is use ful for making sure the code isnât crack
def yes(): return True
def no(): return False
def crash(): return 1/0 # crashes!
print(no() and crash()) # Works! print(crash() and no()) # Crashes! print (yes() and crash()) # Never runs (due to crash), but would also crash (without short-circuiting)
def f(w):
return 10*w
def g(x, y):
return f(3*x) + y # f(3*x) must be evaluated before we can return
def h(z):
return f(g(z, f(z+1))) # The innermost f(z+1) must be evaluated first
print(h(1)) # hint: try the "visualize" feature
Test Functions
def onesDigit(n):
return n%10
def testOnesDigit():
print("Testing onesDigit()...", end="")
assert(onesDigit(5) == 5)
assert(onesDigit(123) == 3)
assert(onesDigit(100) == 0)
assert(onesDigit(999) == 9)
print("Passed!")
testOnesDigit() # Passed! Why is this bad?
Letâs dive into Pythonâs iterables and iterators in a way thatâs clear and beginner-friendly, based on the notes you provided. Imagine weâre unpacking these concepts step-by-step, as if youâre seeing them for the first time while learning Python.
What is an Iterable?
An iterable is like a container or a collection of items that you can go through one by one, in order. Think of it as anything you can loop overâlike a list of groceries, a string of letters, or even a range of numbers. In Python, an iterable is any object that knows how to give you an iterator when you ask for it.
- How it Works: You âaskâ an iterable for an iterator by calling the
iter()
function on it. - Examples:
- A list:
[1, 2, 3]
- A string:
"hello"
- A tuple:
(4, 5, 6)
- Even a range:
range(5)
(gives you0, 1, 2, 3, 4
)
- A list:
- Key Idea: An iterable is something you can process sequentially, but it doesnât do the processing itselfâit hands that job to an iterator.
In a for
loop, Python secretly uses iterables. For example:
for x in [1, 2, 3]:
print(x)
Here, [1, 2, 3]
is the iterable. Python calls iter([1, 2, 3])
behind the scenes to get an iterator, which then feeds 1
, 2
, and 3
to the loop one at a time.
What is an Iterator?
An iterator is like a little pointer or tracker that moves through the iterable, keeping its place and giving you the next item each time you ask. Itâs the worker that does the actual stepping through the sequence.
- How it Works:
- You get an iterator from an iterable using
iter()
. - You ask the iterator for the next item using
next()
. - When thereâs nothing left, it raises a
StopIteration
exception to say, âIâm done!â
- You get an iterator from an iterable using
- Key Features:
- It remembers its position in the sequence.
- It gives you one item at a time, moving forward each time you call
next()
.
Letâs see it in action:
my_list = [1, 2, 3]
my_iterator = iter(my_list) # Get the iterator
print(next(my_iterator)) # 1 (moves to first item)
print(next(my_iterator)) # 2 (moves to second item)
print(next(my_iterator)) # 3 (moves to third item)
print(next(my_iterator)) # Raises StopIteration (no more items!)
The Difference: Iterable vs. Iterator
- Iterable: The container or blueprint. It can give you an iterator whenever you want. You can call
iter()
on it multiple times to start fresh each time.- Example: A list
[1, 2, 3]
is an iterable. It doesnât move or track anything itself.
- Example: A list
- Iterator: The worker that walks through the container. Itâs a one-time-use objectâonce itâs gone through everything, itâs exhausted.
- Example:
iter([1, 2, 3])
gives you an iterator. After callingnext()
untilStopIteration
, itâs done.
- Example:
Think of it like a book (iterable) and a bookmark (iterator). The book has all the pages, and you can get a new bookmark anytime to start reading. The bookmark keeps track of where you are and moves forward page by page until the end.
How for
Loops Use Them
A for
loop in Python is just a nice way to handle iterables and iterators without you doing the iter()
and next()
manually. Hereâs what happens under the hood:
for x in [1, 2, 3]:
print(x)
- Python does:
iterator = iter([1, 2, 3])
(gets an iterator from the iterable).x = next(iterator)
(gets1
, prints it).x = next(iterator)
(gets2
, prints it).x = next(iterator)
(gets3
, prints it).next(iterator)
raisesStopIteration
, so the loop stops.
Playing with It
Letâs try some examples to make it click:
Example 1: Manual Iteration
text = "hi"
it = iter(text)
print(next(it)) # h
print(next(it)) # i
# next(it) would raise StopIteration because "hi" has only 2 letters
Example 2: Multiple Iterators
numbers = [10, 20, 30]
it1 = iter(numbers)
it2 = iter(numbers) # Fresh start!
print(next(it1)) # 10
print(next(it2)) # 10 (it2 is independent of it1)
Example 3: Exhausting an Iterator
stuff = range(2) # 0, 1
it = iter(stuff)
print(next(it)) # 0
print(next(it)) # 1
print(next(it)) # StopIteration!
Why Care?
- Iterables let you write loops easily over all kinds of data (lists, strings, files, etc.).
- Iterators save memory because they generate items one at a time instead of holding everything at once (like
range()
or file reading). - Together, they power Pythonâs
for
loops, list comprehensions, and more.
Your Notes, Explained
- Iterable: âContainer that can be processed sequentially by calling
iter
to get an iterator.â- Translation: Itâs anything you can loop over that gives you a tracker when you ask.
- Iterator: âObject that keeps track of position and returns the next value in the sequence when
next
is called.â- Translation: Itâs the tracker that moves forward and hands you items one by one.
- StopIteration: âCalling
next
raises aStopIteration
if the end of the iterator has been reached.â- Translation: When the tracker runs out of items, it says âstopâ with this signal.
Quick Recap
- Iterable: The thing you loop over (e.g.,
[1, 2, 3]
). - Iterator: The thing that does the looping (e.g.,
iter([1, 2, 3])
). - Pythonâs
for
loop hides theiter()
andnext()
dance, but now you know the magic behind it!
Try playing with iter()
and next()
in a Python shellâitâs a fun way to see this in action!
Letâs unpack the concepts of iterables and iterators in Python based on the notes youâve shared. Iâll explain them clearly and practically, as if youâre encountering them for the first time, while tying in the technical details like __iter__()
, __getitem__()
, and __next__()
. Weâll keep it conversational and grounded with examples.
What Are Iterables?
An iterable is anything in Python that you can loop over sequentiallyâlike a list of numbers, a wordâs letters, or even something that generates values on the fly. Itâs a fixed representation of a sequence, meaning itâs something Python knows how to process one item at a time. You get an iterator from it by calling iter()
.
Two Flavors of Iterables
-
Explicit Sequences:
- These store all their values upfront, ready to go.
- Examples:
- Lists:
[1, 2, 3]
âall numbers are right there. - Tuples:
(4, 5, 6)
âsame deal, fixed and stored. - Strings:
"cat"
âlettersc
,a
,t
are explicitly held in memory.
- Lists:
- Think of these as a pre-written shopping list: everythingâs already listed out.
-
Implicit Sequences:
- These donât store everything at onceâthey âlazilyâ calculate values when you ask for them.
- Examples:
- Map:
map(lambda x: x*2, [1, 2, 3])
âdoubles numbers only when needed. - Filter:
filter(lambda x: x > 0, [-1, 2, -3])
âpicks positives on demand. - Generators:
(x**2 for x in range(3))
âyields0
,1
,4
one at a time.
- Map:
- Think of these as a recipe: the values arenât cooked yet, but the instructions are ready.
How Does Python Know Itâs Iterable?
An object is iterable if it has one of these special methods:
__iter__()
: Returns an iterator object wheniter()
is called. This is the preferred way.__getitem__()
: Lets you access items by index (likeobj[0]
,obj[1]
, etc.), and Python can figure out how to iterate over it. This is an older fallback.
For example:
my_list = [1, 2, 3]
it = my_list.__iter__() # Same as iter(my_list)
Lists have __iter__()
, so theyâre iterable. A string like "hi"
has it too. Even a custom class can be iterable if you define __iter__()
or __getitem__()
.
What Are Iterators?
An iterator is the worker that steps through an iterable, one item at a time. Itâs like a cursor or a bookmarkâit knows where it is in the sequence and gives you the next value when you ask. Iterators keep track of their state, so theyâre not âpureâ (they change as you use them).
How Iterators Work
- Get One: Call
iter()
on an iterable to create an iterator. - Use It: Call
next()
on the iterator to get the next value. - End It: When thereâs nothing left,
next()
raisesStopIteration
.
Example:
nums = [1, 2, 3] # Iterable (explicit sequence)
it = iter(nums) # Get iterator
print(next(it)) # 1
print(next(it)) # 2
print(next(it)) # 3
print(next(it)) # Raises StopIteration
Behind the Scenes
An object is an iterator if it implements:
__next__()
: Returns the next value or raisesStopIteration
when done.- (Usually)
__iter__()
: Returns itself (since iterators are often their own iterators).
The iterator from iter([1, 2, 3])
has __next__()
, which is why next()
works on it.
Practical Example: Explicit vs. Implicit
Explicit (List)
lst = [10, 20, 30] # All values stored
it = iter(lst)
print(next(it)) # 10
print(next(it)) # 20
- The list is fully built in memory, and the iterator just walks through it.
Implicit (Generator)
gen = (x * 2 for x in range(3)) # Lazy: values not stored yet
it = iter(gen)
print(next(it)) # 0 (computes 0 * 2)
print(next(it)) # 2 (computes 1 * 2)
print(next(it)) # 4 (computes 2 * 2)
- The generator calculates each value only when
next()
asks for itâsuper memory-efficient!
Why Iterators âStore Stateâ?
Iterators remember where they are. If you call next()
twice on the same iterator, you get different results because it moves forward:
it = iter("abc")
print(next(it)) # a
print(next(it)) # b
This âstateâ makes next()
non-pureâunlike a pure function like abs(-5)
, which always returns 5
, next(it)
depends on whatâs happened before.
Connecting to for
Loops
A for
loop uses this machinery automatically:
for x in [1, 2, 3]: # Iterable
print(x)
- Python:
- Calls
iter([1, 2, 3])
to get an iterator. - Calls
next()
repeatedly untilStopIteration
.
- Calls
- Same with implicit iterables:
for x in map(str, [1, 2, 3]): # "1", "2", "3" computed lazily
print(x)
Your Notes, Explained
Iterables
- âFixed representations that can be processed sequentially by calling
iter
to retrieve an iteratorâ:- Theyâre the source of the sequence, ready to hand off to an iterator.
- Explicit: Pre-stored (e.g.,
[1, 2, 3]
). - Implicit: Computed on demand (e.g.,
map()
). - Practically: Needs
__iter__()
(modern way) or__getitem__()
(old-school way).
Iterators
- âProvide sequential access to an iterableâ:
- Theyâre the movers, stepping through the sequence.
- âCall
iter
on an iterable to get the iteratorâ:iter()
is the bridge from iterable to iterator.
- âCall
next
to get the next valueâ:next()
is how you pull items out.
- âIterators store stateâ:
- They track their position, so each
next()
moves forward.
- They track their position, so each
Fun Experiment
Try this to see the difference:
# Iterable (can restart)
lst = [1, 2]
for x in lst: print(x) # 1, 2
for x in lst: print(x) # 1, 2 again!
# Iterator (one-time use)
it = iter([1, 2])
print(next(it)) # 1
print(next(it)) # 2
print(next(it)) # StopIterationâexhausted!
The iterable (lst
) can give fresh iterators; the iterator (it
) runs out.
Wrap-Up
- Iterable: The container or recipe (has
__iter__()
or__getitem__()
). - Iterator: The walker (has
__next__()
). - Together, they make Pythonâs loops and lazy processing possible. Play with
iter()
andnext()
to feel the flow!
def falling(n, k):
"""Compute the falling factorial of n to depth k.
>>> falling(6, 3) # 6 * 5 * 4
120
>>> falling(4, 3) # 4 * 3 * 2
24
>>> falling(4, 1) # 4
4
>>> falling(4, 0)
1
"""
total, stop = 1, n-k
while n > stop:
total, n = total*n, n-1
return total
def falling(n, k):
"""Compute the falling factorial of n to depth k."""
if k == 0:
return 1
return n * falling(n - 1, k - 1)
def sum_digits(y): """Sum all the digits of y.
>>> sum_digits(10) # 1 + 0 = 1
1
>>> sum_digits(4224) # 4 + 2 + 2 + 4 = 12
12
>>> sum_digits(1234567890)
45
>>> a = sum_digits(123) # make sure that you are using return rather than print
>>> a
6
"""
total = 0
while y > 0:
total, y = total + y % 10, y // 10
return total
def double_eights(n):
"""Return true if n has two eights in a row.
>>> double_eights(8)
False
>>> double_eights(88)
True
>>> double_eights(2882)
True
>>> double_eights(880088)
True
>>> double_eights(12345)
False
>>> double_eights(80808080)
False
"""
prev_eight = False
while n > 0:
last_digit = n % 10
if last_digit == 8 and prev_eight:
return True
elif last_digit == 8:
prev_eight = True
else:
prev_eight = False
n = n // 10
return False
python tools in repl
Using --listfuncs
in Python REPL
The --listfuncs
option in the trace
module is mainly used to list functions without executing them. This is useful for understanding the structure of a script.
Normally, you would use it like this in a terminal:
python -m trace --listfuncs my_script.py
This will list all functions defined in my_script.py
.
However, in REPL mode, the trace
module doesnât directly support --listfuncs
. Instead, you can achieve the same effect using Python introspection tools.
Alternative: Listing Functions in the Current Module (REPL Mode)
If youâre working in Python interactively (REPL), here are better ways to list functions:
1. Using inspect
to List Functions in a Module
import inspect
import my_script # Import the script you want to inspect
functions = [name for name, obj in inspect.getmembers(my_script, inspect.isfunction)]
print(functions)
This will print all functions defined in my_script.py
.
2. Listing Functions in the Current REPL Session
If youâve defined functions interactively in REPL:
import types
functions = [name for name, obj in globals().items() if isinstance(obj, types.FunctionType)]
print(functions)
This lists all functions defined in the REPL session.
Better Alternatives to trace
for Tracing Execution
Python has better tracing tools than trace.Trace()
. Here are a few:
1. Using sys.setprofile()
for Full Function Call Logging
import sys
def trace_calls(frame, event, arg):
if event == "call":
print(f"Calling {frame.f_code.co_name} at {frame.f_lineno}")
return trace_calls
sys.setprofile(trace_calls)
def foo():
print("Inside foo")
bar()
def bar():
print("Inside bar")
foo()
sys.setprofile(None) # Stop tracing
This logs all function calls while the program runs.
2. Using py-spy
for Live Function Tracing (Recommended)
py-spy
is an external tool for better function tracing:
pip install py-spy
py-spy top --pid <your-python-process-id>
It shows real-time function calls and CPU usage.
3. Using pdb
for Step-by-Step Debugging
Pythonâs built-in debugger (pdb
) lets you step through functions interactively:
import pdb
def foo():
print("Inside foo")
bar()
def bar():
print("Inside bar")
pdb.run('foo()') # Start debugging foo()
You can use commands like s
(step), n
(next), and c
(continue).
Conclusion
trace --listfuncs
only works on script files, not REPL.- In REPL, use
inspect
ortypes.FunctionType
to list functions. - For better tracing, use:
sys.setprofile()
for function call tracking.pdb
for debugging.py-spy
for real-time profiling.
Would you like a deeper dive into any of these? đ
graph tools for python
https://github.com/gauge-sh/tach