Reading notes for Python Crash Course (2nd Edition)
Python Basics
Variable rules:
- Can only contain letters, digits, and underscores (unlike JS, which also allows dollar signs in variable names)
- Keywords cannot be used as variable names
- Python has no syntactic concept of constants — only naming conventions
String (Text Sequence Type)
Some Common Methods
Changing Case
title/capitalizeupper/lower
Code Example
name = "ada lovelace"
print(name.title())
print(name.capitalize())
print(name.upper())f-strings (similar to JS template literals)
f-strings are only available in 3.6+. They are equivalent to the older
"{0} {1}".format(f_name, l_name), where {0} represents the index of the argument to be substituted
Code Example
f_name = "ada"
l_name = "lovelace"
full_name = f"{f_name} {l_name}"
print("full_name:", full_name.title())
print("before 3.6: ", "{} {}".format(f_name, l_name).title())Removing Whitespace
- lstrip / rstrip / strip
Code Example
wb_word = " python "
print("rstrip:", wb_word.rstrip())
print("lstrip:", wb_word.lstrip())Code Example
# 小练习:人名quotes
name = "\tRocky\n"
quotes = "Let me tell you something you already know. The world ain't all sunshine and rainbows. It's a very mean and nasty place. And I don't care how tough you are, it will beat you to knees and keep you there permanently if you let it! You, me, or nobody is gonna hit as hard as life. But it ain't about how hard you bit. It's about how hard you can get hit and keep moving forward. How much you can take and keep moving forward. That's how winning is done! Now if you know what you're worth, then go out and get what you're worth. But ya gotta be willing to take the hits, and not pointing fingers saying you ain't where you wanna be because of him, or her, or anybody! Cowards do that and that ain't you! You're better than that!"
print(f'{name.strip().title()} once said: "{quotes}"')Number (Sequence Type)
Unlike JS, Python distinguishes between integers and floats. (Internally in JS, all numbers are represented as floats.)
- Dividing any two numbers always results in a float
- In other operations, if either operand is a float, the result is also a float
pythonallows underscores when writing large numbers for readability.pythonignores them during parsing, so1_0_00,1_000, and1000are identical inpython. (Like f-strings, only available in 3.6+)
List
Similar to JS, but supports negative indexing with -1. In addition to the standard literal declaration list = [0, 1, 2], python also provides the range function for quickly creating Number Lists, and List Comprehension for quickly declaring patterned Lists.
Some Common Methods
Basic Operations
append(x)insert(i, x)extend(t)s += tpop()remove(x)del s[i:j:k]s[i:j] = tsort()sorted()reverse()See the official documentation
Loops
Note that loop variables are global, so they remain accessible after the loop ends. In
Python, Indent Matters!
List Comprehension
List comprehensions provide a concise way to create new Lists based on existing Lists or other iterable objects
Code Example
# mapList = [*map(lambda x: x ** 2, range(1, 11))]
mapList = list(map(lambda x: x**2, range(1, 11)))
resolveList = [value**2 for value in range(1, 11)]
print(mapList)
print(resolveList)Number List
range(x, y, step) => generates an array in the range [x, y) with the given step min max sum
Code Example
testList = ["a", "b", "c", "d", "e"]
for s in testList:
print(s)
for s in range(1, 6, 2):
print(s)
print(f"s can still be used out of loop: {s}")Tuple (Sequence Type)
Pythoncalls values that cannot be modified immutable, and an immutable list is called a tuple. Unliketupleintypescript, aPythontuple is more similar to the concept of a constant array in TS.
Tuples are identified by commas; parentheses just make them look neater and clearer. If you want to define a tuple with only one element, you must include a trailing comma after that element. Creating a single-element tuple is usually not meaningful, but auto-generated tuples may contain only one element.
Code Example
singleTuple = (200,)
testTuple = (200, 50)
print(testTuple[0])Tuple unpacking
Tuple unpacking provides a shortcut to extract elements from a tuple, similar to array destructuring in javascript
tuple = (1, 2, 3)
x, y, z = tuple
print(x, y, z)Due to the nature of Tuple, even if you don't need the preceding elements, you must use placeholders of the same length, otherwise unpacking will raise an error
tuple = (1, 2, 3)
# Wrong - this will assign the entire tuple
x = tuple
# Wrong - this will raise a ValueError
_, x = tuple
# Correct
_, x, _ = tuple
print(x)Conditions
if You can use comparison operators == >= etc. Or use logical keywords and or Use in not in keywords to check whether a specific value is in a list
Code Example
recipes = ["mushrooms", "green peppers", "cheese"]
for m in recipes:
if m == "green peppers":
print("Sorry, out of green peppers right now")
else:
print(f"Adding {m}")
print("finished making pizza")
seqNumList = list(range(1, 10))
for i in range(len(seqNumList)):
if i == 0:
seqNumList[i] = "1st"
elif i == 1:
seqNumList[i] = "2nd"
elif i == 2:
seqNumList[i] = "3rd"
else:
seqNumList[i] = f"{i}th"
print(seqNumList)Dict (Mapping Types)
See the official documentation
Unlike
typescript, in Python 3.7, the order of elements in a dictionary matches the order in which they were defined.
get(key[, default])Return the value for key if key is in the dictionary, else default. If default is not given, it defaults to None, so that this method never raises a KeyError.iter(d)Return an iterator over the keys of the dictionary. This is a shortcut for iter(d.keys()).items()Return a new view of the dictionary’s items ((key, value) pairs)keys()values()Iterating over a dictionary traverses all keys by default, sofor name in studentsis equivalent tofor name in students.keys()
You can use the built-in
set()function to deduplicate, or directly use a pair of curly braces to create aset
languages = {'python', 'ruby', 'python', 'c'}
# languages {'ruby', 'python', 'c'}Code Example
speed_x_increment = {"slow": 1, "medium": 2, "fast": 3}
alien_0 = {"color": "green", "points": 5, "speed": "fast"}
alien_0["x_position"] = 0
alien_0["y_position"] = 25
alien_0["x_position"] += speed_x_increment.get(alien_0["speed"], 5)
# for k in iter(alien_0):
for k, v in alien_0.items():
print(f'alien_0["{k}"]: {alien_0[k]}')Input and While
The
input()function accepts user input and always returns a string. You can use\nfor line breaks.
Compared to node.js, python is clearly much more concise
const { createInterface } = require("node:readline");
const { stdin, stdout } = require("node:process");
const rl = createInterface({
input: stdin,
output: stdout,
});
rl.question("Tell me something, and I will repeat it back 2 u", (answer) => {
console.log("🚀 ~ file: test.js:7 ~ rl.question ~ answer:", answer);
rl.close();
});Code Example
message = "Tell me something, and I will repeat it back 2 u"
message += "\nEnter Q to end the program.\n"
result = ""
flag = True
while flag:
result = input(message)
flag = result.upper() != "Q"
if flag:
print(result)Code Example
# list - append
unconfirmed_users = ["admin", "alice", "jack", "tom"]
confirmed_users = []
while unconfirmed_users:
cur_user = unconfirmed_users.pop(0)
confirmed_users.append(cur_user)
print(f"\nThe following users have been confirmed:")
for confirmed_user in confirmed_users:
print(confirmed_user.title())
# list - remove
pets = ["dog", "cat", "dog", "goldfish", "cat", "rabbit", "cat"]
print(pets)
target = "cat"
while target in pets:
pets.remove(target)
print(pets)Code Example
responses = {}
polling = True
while polling:
name = input("\nWhat's ur name? ")
response = input("Which mountain would you like to climb someday? ")
responses[name] = response
polling = input("Would you like to let another person respond?(yes/no) ") != "no"
print("\n-- Poll Results ---")
for name, response in responses.items():
print(f"{name.title()} would like to climb {response}")Functions
def func_name(*params):
"""
docstring
"""
print("Hello world")There are two ways to pass arguments:
- Positional arguments (based on order)
- Keyword arguments (based on parameter names)
Python's function calling is far more flexible thanjavascript. Injavascript, the calling convention is determined at definition time, which often leads to issues when using multi-parameter formats likefunction foo(arg1, arg2){/* do something */}that are hard to extend later
Code Example
unprinted_designs = ["phone case", "robot pendant", "dodecahedron"]
def print_models(models):
"""打印模型"""
finished_designs = []
sliced_designs = models.copy()
while sliced_designs:
finished_designs.append(sliced_designs.pop())
return finished_designs
def show_completed_models(models):
"""显示已完成的模型"""
print("\nThe following models have been printed:")
for model in models:
print(model)
show_completed_models(print_models(unprinted_designs))When the number of arguments is uncertain, you can use *args syntax to receive them as a Tuple (similar to javascript's ...args syntax), or use **kwargs to receive them as a Dict
Code Example
def make_pizza(size, *toppings):
"""概述当前披萨"""
print(f"\nMaking a {size}-inch pizza with the following toppings:")
for topping in toppings:
print(f"- {topping}")
make_pizza(16, "mushrooms", "green peppers", "extra cheese")
# Python 甚至支持接受任意个数的参数并生成字典
def build_profile(name, age, **user_info):
"""用户信息"""
user_info["name"] = name
user_info["age"] = age
return user_info
user_profile = build_profile("Jack", 22, sex="male")
print(user_profile)import
Any file with a .py extension is inherently a module
There are multiple import syntaxes, and you can use the as keyword to specify an alias:
import module_name # imports the entire module_name file into the current filefrom module_name import func_name as fn # imports func_name from module_name with alias fn
You can use the wildcard * to import all functions: from module_name import *
However, when using large modules written by others, you should avoid this approach because Python will overwrite functions or variables with the same name
Code Example
class Car:
"""一次模拟汽车的简单尝试。"""
def __init__(self, make, model, year):
"""初始化描述汽车的属性。"""
self.make = make
self.model = model
self.year = year
self.odometer_reading = 0
def get_descriptive_name(self):
"""返回整洁的描述性信息。"""
long_name = f"{self.year} {self.make} {self.model}"
return long_name.title()
def read_odometer(self):
"""打印里程信息"""
print(f"This car has {self.odometer_reading} miles on it.")
def update_odometer(self, mileage):
"""设置里程信息"""
if mileage >= self.odometer_reading:
self.odometer_reading = mileage
else:
print("You can't roll back an odometer!")
def increase_odometer(self, miles):
self.update_odometer(self.odometer_reading + miles)
class ElectricCar(Car):
"""电动汽车"""
def __init__(self, *args):
super().__init__(*args)
self.battery_size = 75
def describe_battery(self):
print(f"This car has a {self.battery_size}-kWh battery")
my_tesla = ElectricCar("tesla", "model s", 2019)
print(my_tesla.battery_size)
my_tesla.describe_battery()Python Standard Library
The Python standard library is a set of modules included with every Python installation. Now that you have a general understanding of how functions and classes work, you can start using modules written by other programmers. You can use any function or class from the standard library by simply including an import statement at the beginning of your program.
from random import randint
randint(1, 6)Code Example
from random import randint
test_list = ["A", "B", "C", "D", "E", "F", "G", "H"]
count = 4
winning_list = []
while len(winning_list) != count:
winning_list.append(test_list.pop(randint(0, len(test_list) - 1)))
winning_list.sort()
print(f"You will win if you get: {winning_list}")
print(test_list)Files
- The
withkeyword letsPythonautomatically determine when to close the file open(file_name, mode)close(file_name)keywords canopen/close files. However, ifcloseis not called correctly due to code errors or other reasons, the file may become corrupted. Therefore, you can usewithfor automatic handlingfile.write(content)file.read()
Read/Write Modes
open-mode | r | r+ | w | w+ | a | a+ |
|---|---|---|---|---|---|---|
| Read | √ | √ | √ | √ | ||
| Write | √ | √ | √ | √ | √ | |
| Create | √ | √ | √ | √ | ||
| Overwrite | √ | √ | ||||
| Pointer at start | √ | √ | ||||
| Pointer at end | √ | √ |
Each line in a file ends with \n, so be mindful to use strip or rstrip to remove extra newlines
with open("./README.md") as readme_file:
for line in readme_file:
print(line.rstrip())Storing Data
json
json.dump()json.load()
os
Sometimes when creating a file, the parent directory may not exist
data = {"test": 111}
data_path = "no_exist_dir/data.json"
with open(data_path, "w") as f:
json.dump(data, f, indent=4) # FileNotFoundError: [Errno 2] No such file or directoryIn this case, you can use the os module to add error-handling code
import os
data = {"test": 111}
data_path = "no_exist_dir/data.json"
# Create the directory if it doesn't exist
os.makedirs(os.path.dirname(no_exist_dir), exist_ok=True) # set exist_ok not to override existed dir
with open(data_path, "w") as f:
json.dump(data, f, indent=4)Exceptions
Exceptions are handled using try-except blocks
try:
print(5/0)
except ZeroDivisionError:
print("You can't divide by zero!")Inside the except block, you can use the pass keyword to do nothing
Code Example
print("Give me two numbers, and I'll divide them.")
print("Enter 'q' to quit.")
while True:
first_num = input("\nFirst number: ")
if first_num == "q":
break
sec_num = input("\nSecond number: ")
if sec_num == "q":
break
try:
answer = int(first_num) / int(sec_num)
except ZeroDivisionError:
print("You can't divide by 0!")
except ValueError:
print("value invalid")
else:
print(answer)Code Example
filename = "not_exist.txt"
try:
with open(filename, encoding="utf-8") as f:
contents = f.read()
except FileNotFoundError:
print(f"Sorry, the file {filename} does not exist.")Code Example
# 练习 10-6
def accumulator():
"""加法运算"""
from functools import reduce
print("Give me two numbers, and I'll divide them.")
print("Enter 'q' to quit.")
def trans_2_int(str):
return int(str)
input_str = ""
num_list = []
while input_str != "q":
try:
input_str = input(
"\nPlease input a number to accumulate ('q' to execute): "
)
if input_str != "q":
num = trans_2_int(input_str)
num_list.append(num)
except ValueError:
print("Value invalid! Input should be numbers")
result = reduce(lambda acc, val: acc + val, num_list)
print(f"{' + '.join([*map(str, num_list)])} = {result}")Testing
The
unittestmodule inPython's standard library provides code testing tools
Common Assertion Methods
| Method | Purpose |
|---|---|
| assertEqual(a, b) | a == b |
| assertNotEqual(a, b) | a != b |
| assertTrue(x) | x == True |
| assertFalse(x) | x == False |
| assertIn(item, list) | item in list |
| assertNotIn(item, list) | item not in list |
TIP
Testing classes is similar to testing functions. The difference is that classes often have internal attributes, so test cases tend to have repetitive setup code. You can use the setUp method to preset internal data
Code Example
# 测试函数
# name_func.py
def get_formatted_name(first, last, middle=""):
"""生成格式化姓名"""
if middle:
full_name = f"{first} {middle} {last}"
else:
full_name = f"{first} {last}"
return full_name.title()
# should be in test_name_func.py (not executable in Jupyter book)
# import unittest
# class NamesTestCase(unittest.TestCase):
# def test_first_last_name(self):
# formatted_name = get_formatted_name("janis", "joplin")
# self.assertEqual(formatted_name, "Janis Joplin")
# def test_first_last_middle_name(self):
# formatted_name = get_formatted_name("wolfgang", "mozart", "amadeus")
# self.assertEqual(formatted_name, "Wolfgang Amadeus Mozart")
# if __name__ == "__main__":
# unittest.main()Code Example
# 测试类
# survey.py
class AnonymousSurvey:
def __init__(self, question):
"""存储一个问题,并未存储答案做准备"""
self.question = question
self.responses = []
def show_question(self):
print(self.question)
def store_response(self, new_response):
self.responses.append(new_response)
def show_results(self):
"""显示收集到的所有答卷"""
print("Survey results:")
for response in self.responses:
print(f"- {response}")
# should be in test_survey.py (not executable in Jupyter book)
# import unittest
# from survey import AnonymousSurvey
# class TestAnonymousSurvey(unittest.TestCase):
# def setUp(self):
# """创建一个调查对象和一组答案,供测试方法使用"""
# self.question = "What language did you first learn to speak"
# self.responses = ["English", "Spanish", "Mandarin"]
# self.my_survey = AnonymousSurvey(self.question)
# def test_store_single_response(self):
# first_response = self.responses[0]
# self.my_survey.store_response(first_response)
# self.assertIn(first_response, self.my_survey.responses)
# def test_store_three_response(self):
# for response in self.responses:
# self.my_survey.store_response(response)
# for response in self.responses:
# self.assertIn(response, self.my_survey.responses)
# if __name__ == "__main__":
# unittest.main()See other documents for practical project examples