Python 基础
变量规则:
- 只能包含字母数字下划线(区分 js 可以以下划线和 dollar 符作为变量名)
- 关键词不能作为变量名
- python 中没有常量的语法概念。只有约定写法
String (Text Sequence Type)
一些常用的方法
修改大小写
title
/capitalize
upper
/lower
Code Example
name = "ada lovelace"
print(name.title())
print(name.capitalize())
print(name.upper())
f 字符串(类比 js 模板字符串)
f 字符串仅适用于 3.6+。等效于之前的
"{0} {1}".format(f_name, l_name)
,其中{0}中的 0 代表需要被替换的 args_idx
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())
删除空白
- 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)
与 js 不同,python 区分整数与浮点数。(js 内部,所有数字都是作为浮点数表示)
- 任意两个数相除,结果总是浮点数
- 其他运算中,其中一方为浮点数,结果也是浮点数
python
表述大数时可以用下划线分割,python
解析时会全部忽略,1_0_00
和1_000
和1000
在python
中没有区别。(与 f 字符串一样,仅 3.6+适用)
List
与 js 基本类似,但可以用 -1
进行访问。与此同时,python
除了使用常规的字面量声明 list = [0, 1, 2]
外,还提供了 range
方法,快速声明 Number List
。以及 列表推导式(List Comprehension)
快速声明有迹可循的 List
。
一些常用方法
基本操作
append(x)
insert(i, x)
extend(t)
s += t
pop()
remove(x)
del s[i:j:k]
s[i:j] = t
sort()
sorted()
reverse()
参考官方文档
循环
注意循环声明的变量是全局的,因此在循环结束后依然可以访问。在
Python
的世界里,Indent Matters!
列表推导式
列表推导式提供了一种简介的方式来基于已存在的 List
或者其他 可迭代对象
声明新的 List
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)
=> 以 step 为间隔生成范围为[xy)的数组 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)
Python
将不能修改的值称为不可变的,而不可变的列表被称为元组。与typescript
中的tuple
不同,Python
中的元组更类似于 ts 中的数组常量的概念
元组是由逗号标识的,圆括号只是让元组看起来更整洁、更清晰。如果你要定义只包含一个元素的元组,必须在这个元素后面加上逗号。创建只包含一个元素的元组通常没有意义,但自动生成的元组有可能只有一个元素。
Code Example
singleTuple = (200,)
testTuple = (200, 50)
print(testTuple[0])
Tuple unpacking
元组解构 (Tuple unpacking) 提供了一种快捷方式从元组中提取元素,与 javascript
中的数组结构类似
tuple = (1, 2, 3)
x, y, z = tuple
print(x, y, z)
由于 元组Tuple
的特性,即使不需要使用到前置元素,也必须使用占位符进行占位相同长度,否则解构将会报错
tuple = (1, 2, 3)
# 错误写法,将会直接赋值
x = tuple
# 错误写法,会报 ValueError 的错误
_, x = tuple
# 正确写法
_, x, _ = tuple
print(x)
Conditions
if
可以使用 comparison operators ==
>=
etc. 或者使用 logical keywords and
or
使用 in
not in
keywords 检查特定值是否在列表中
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)
参考官方网站
与
typescript
不同,在 Python 3.7 中,字典中元素的排列顺序与定义时相同。
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()
遍历字典时会默认遍历所有键,因此for name in students
和for name in students.keys()
是等效的
既可以使用内置方法
set()
进行去重,也可以直接使用一对花括号创建set
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
input()
函数接收用户输入,可以通过\n
总是返回字符串。
对比 node.js
,python
显然要简练很多
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")
传参的方式有两种:
- 位置实参(基于顺序)
- 关键字实参 (基于形参命名)
Python
的函数调用方式比javascript
要灵活太多。javascript
在定义的时候就已经确定了调用方式。因此经常会出现定义的时候使用多形参的格式function foo(arg1, arg2){/* do something */}
,后续扩展不便的问题
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))
当参数个数不确定的时候,可以通过 *args
的语法接收为 Tuple
(类似 javascript
的 ...args
语法),也可以通过 **kwargs
要求将参数接收为一个 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
扩展名为 .py
的文件天生就是一个模块
导入语法有多种,导入时可以通过 as
关键字指定别名:
import module_name # 将 module_name 文件整个导入当前文件
from module_name import func_name as fn # 从 module_name 中导入 func_name 并指定别名 fn
可以通过通配符 *
导入所有函数 from module_name import *
但在使用非自己编写的大型模块时,应避免这种方法,因为 Python
会对多个名称相同的函数或变量进行覆盖操作
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 标准库
Python 标准库是一组模块,我们安装的 Python 都包含它。你现在对函数和类的工作原理已有大致的了解,可以开始使用其他程序员编写好的模块了。可以使用标准库 中的任何函数和类,只需在程序开头包含一条简单的 import 语句即可。
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)
文件
with
关键字可以让Python
自动确认文件的关闭时机open(file_name, mode)
close(file_name)
关键字可以打开/关闭文件
。但实际close
如果因为错误代码等原因没有正确调用或未执行,可能导致文件受损。因此可以使用with
自动确认file.write(content)
file.read()
读写模式
open-mode | r | r+ | w | w+ | a | a+ |
---|---|---|---|---|---|---|
读 | √ | √ | √ | √ | ||
写 | √ | √ | √ | √ | √ | |
创建 | √ | √ | √ | √ | ||
覆盖 | √ | √ | ||||
指针在开始 | √ | √ | ||||
指针在结尾 | √ | √ |
文件每行末尾都有 \n
的存在,因此需要注意用 strip
或者 rstrip
消除多余换行符
with open("./README.md") as readme_file:
for line in readme_file:
print(line.rstrip())
存储数据
json
json.dump()
json.load()
os
有时候我们在创建文件的时候可能会有父级目录不存在的情况
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 directory
这时候可以使用 模块 os
。通过额外的代码进行容错操作
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)
异常
异常是使用 try-except
代码块处理的
try:
print(5/0)
except ZeroDivisionError:
print("You can't divide by zero!")
在 except
代码块内,可以使用 pass
关键字,让代码什么都不做
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}")
测试
Python
标准库中的模块unittest
提供了代码测试工具
常用断言方法
方法 | 用途 |
---|---|
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
测试类与测试函数基本类似,不同点在于测试类时,由于类往往具有内部属性,因此在编写测试用例时往往会有重复语句,可以通过 setUp
方法,预设内部数据
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()
实践项目章节示例可以查看其他文档