feat: 第三章全部
@@ -133,6 +133,61 @@ export default defineConfig({
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
text: '3.5git与github',
|
||||||
|
collapsed: true,
|
||||||
|
items: [
|
||||||
|
{ text: '3.5git与github', link: '/3.编程思维体系构建/3.5git与github' },
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '3.6Python(灵巧的胶水)',
|
||||||
|
collapsed: true,
|
||||||
|
items: [
|
||||||
|
{ text: '3.6Python(灵巧的胶水)', link: '/3.编程思维体系构建/3.6Python(灵巧的胶水)' },
|
||||||
|
{ text: '3.6.1从CS61A看编程语言学习', link: '/3.编程思维体系构建/3.6.1从CS61A看编程语言学习' },
|
||||||
|
{ text: '3.6.2环境配置', link: '/3.编程思维体系构建/3.6.2环境配置' },
|
||||||
|
{ text: '3.6.3安装python', link: '/3.编程思维体系构建/3.6.3安装python' },
|
||||||
|
{
|
||||||
|
text: '3.6.4Python for fun',
|
||||||
|
collapsed: true,
|
||||||
|
items: [
|
||||||
|
{ text: '3.6.4Python for fun', link: '/3.编程思维体系构建/3.6.4Python for fun' },
|
||||||
|
{ text: '3.6.4.0阶段零:Python解释器', link: '/3.编程思维体系构建/3.6.4.0阶段零:Python解释器' },
|
||||||
|
{ text: '3.6.4.1阶段一:熟悉语句', link: '/3.编程思维体系构建/3.6.4.1阶段一:熟悉语句' },
|
||||||
|
{ text: '3.6.4.2阶段二:递归操作', link: '/3.编程思维体系构建/3.6.4.2阶段二:递归操作' },
|
||||||
|
{ text: '3.6.4.3阶段三:数据抽象', link: '/3.编程思维体系构建/3.6.4.3阶段三:数据抽象' },
|
||||||
|
{ text: '3.6.4.4阶段四:高阶函数', link: '/3.编程思维体系构建/3.6.4.4阶段四:高阶函数' },
|
||||||
|
{ text: '3.6.4.5阶段五:迭代生成', link: '/3.编程思维体系构建/3.6.4.5阶段五:迭代生成' },
|
||||||
|
{ text: '3.6.4.6结语', link: '/3.编程思维体系构建/3.6.4.6结语' },
|
||||||
|
{ text: '', link: '/3.编程思维体系构建/' },
|
||||||
|
{ text: '', link: '/3.编程思维体系构建/' },
|
||||||
|
{ text: '', link: '/3.编程思维体系构建/' },
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '3.6.5关于CS61A',
|
||||||
|
collapsed: true,
|
||||||
|
items: [
|
||||||
|
{ text: '3.6.5关于CS61A', link: '/3.编程思维体系构建/3.6.5关于CS61A' },
|
||||||
|
{ text: '3.6.5.1lab00:让我们开始吧', link: '/3.编程思维体系构建/3.6.5.1lab00:让我们开始吧' },
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{ text: '3.X 聊聊设计模式和程序设计', link: '/3.编程思维体系构建/3.X 聊聊设计模式和程序设计' },
|
||||||
|
{
|
||||||
|
text: '3.Y 附加模块:Linux',
|
||||||
|
collapsed: true,
|
||||||
|
items: [
|
||||||
|
{ text: '3.Y 附加模块:Linux', link: '/3.编程思维体系构建/3.Y 附加模块:Linux' },
|
||||||
|
{ text: '3.Y.1VMware的安装与安装Ubuntu22.04系统', link: '/3.编程思维体系构建/3.Y.1VMware的安装与安装Ubuntu22.04系统' },
|
||||||
|
{ text: '3.Y.2WSL的安装', link: '/3.编程思维体系构建/3.Y.2WSL的安装' },
|
||||||
|
{ text: '3.Y.3Linux初探索', link: '/3.编程思维体系构建/3.Y.3Linux初探索' },
|
||||||
|
{ text: '3.Y.4Vim初探索', link: '/3.编程思维体系构建/3.Y.4Vim初探索' },
|
||||||
|
{ text: '3.Y.5linux小任务', link: '/3.编程思维体系构建/3.Y.5linux小任务' },
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|||||||
390
3.编程思维体系构建/3.5git与github.md
Normal file
@@ -0,0 +1,390 @@
|
|||||||
|
# 3.5git 与 github
|
||||||
|
|
||||||
|
引自 nju-ics-pa
|
||||||
|
|
||||||
|
## <strong>光玉</strong>
|
||||||
|
|
||||||
|
想象一下你正在玩 Flappy Bird ,你今晚的目标是拿到 100 分,不然就不睡觉。 经过千辛万苦,你拿到了 99 分,就要看到成功的曙光的时候,你竟然失手了!你悲痛欲绝,滴血的心在呼喊着,“为什么上天要这样折磨我?为什么不让我存档?”
|
||||||
|
|
||||||
|
想象一下你正在写代码,你今晚的目标是实现某一个新功能,不然就不睡觉。经过千辛万苦,你终于把代码写好了,保存并编译运行,你看到调试信息一行一行地在终端上输出。就要看到成功的曙光的时候,竟然发生了错误!你仔细思考,发现你之前的构思有着致命的错误,但之前正确运行的代码已经永远离你而去了。你悲痛欲绝,滴血的心在呼喊着,“为什么上天要这样折磨我?”你绝望地倒在屏幕前 ... ... 这时,你发现身边渐渐出现无数的光玉,把你包围起来,耀眼的光芒令你无法睁开眼睛 ... ... 等到你回过神来,你发现屏幕上正是那份之前正确运行的代码!但在你的记忆中,你确实经历过那悲痛欲绝的时刻 ... ... 这一切真是不可思议啊 ... ...
|
||||||
|
|
||||||
|
## <strong>人生如戏</strong><strong>,</strong><strong>戏如人生</strong>
|
||||||
|
|
||||||
|
人生就像不能重玩的 Flappy Bird,但软件工程领域却并非如此,而那不可思议的光玉就是“版本控制系统”。版本控制系统给你的开发流程提供了比朋也收集的更强大的光玉,能够让你在过去和未来中随意穿梭,避免上文中的悲剧降临你的身上。
|
||||||
|
|
||||||
|
没听说过版本控制系统就完成实验,艰辛地排除万难,就像游戏通关之后才知道原来游戏可以存档一样,其实玩游戏的时候进行存档并不是什么丢人的事情。
|
||||||
|
|
||||||
|
在本节,我们使用 `git` 进行版本控制。下面简单介绍如何使用 `git` :
|
||||||
|
|
||||||
|
### <strong>游戏设置</strong>
|
||||||
|
|
||||||
|
首先你得安装 `git` :
|
||||||
|
|
||||||
|
- Linux 下
|
||||||
|
|
||||||
|
```
|
||||||
|
# Debian , Ubuntu
|
||||||
|
sudo apt install git
|
||||||
|
```
|
||||||
|
|
||||||
|
- windows 下
|
||||||
|
|
||||||
|
从这里下载 [https://git-scm.com/download/win](https://git-scm.com/download/win)
|
||||||
|
|
||||||
|
下载完安装一路点 `next` 就行,什么配置也不用动。
|
||||||
|
|
||||||
|
安装好之后,你需要先进行一些配置工作。在终端里输入以下命令:
|
||||||
|
|
||||||
|
```
|
||||||
|
git config --global user.name "Zhang San" # your name
|
||||||
|
git config --global user.email "zhangsan@foo.com" # your email
|
||||||
|
```
|
||||||
|
|
||||||
|
经过这些配置, 你就可以开始使用 `git` 了。
|
||||||
|
|
||||||
|
你会通过 `git clone` 命令来拉取远程仓库的代码,里面已经包含一些 `git` 记录,因此不需要额外进行初始化。如果你想在别的实验、项目中使用 `git` ,你首先需要切换到实验、项目的目录中,然后输入
|
||||||
|
|
||||||
|
```
|
||||||
|
git init
|
||||||
|
```
|
||||||
|
|
||||||
|
进行初始化。初始化后会创建一个隐藏的文件夹名为 `.git` git 会基于这个文件夹来进行版本控制功能。
|
||||||
|
|
||||||
|
### <strong>查看</strong><strong>commit</strong><strong>信息</strong>
|
||||||
|
|
||||||
|
使用
|
||||||
|
|
||||||
|
```
|
||||||
|
git log
|
||||||
|
```
|
||||||
|
|
||||||
|
查看目前为止所有的 commit 记录。
|
||||||
|
|
||||||
|
(commit:提交)
|
||||||
|
|
||||||
|
使用
|
||||||
|
|
||||||
|
```
|
||||||
|
git status
|
||||||
|
```
|
||||||
|
|
||||||
|
可以得知,与当前存档相比,哪些文件发生了变化.
|
||||||
|
|
||||||
|
### 提交
|
||||||
|
|
||||||
|
你可以像以前一样编写代码。等到你的开发取得了一些阶段性成果,你应该马上进行 “ 提交( commit )”。
|
||||||
|
|
||||||
|
首先你需要使用 `git status` 查看是否有新的文件或已修改的文件未被跟踪;若有,则使用 `git add` 将文件加入跟踪列表,例如
|
||||||
|
|
||||||
|
```
|
||||||
|
git add file.c
|
||||||
|
```
|
||||||
|
|
||||||
|
会将 `file.c` 加入跟踪列表。如果需要一次添加所有未被跟踪的文件,你可以使用
|
||||||
|
|
||||||
|
```
|
||||||
|
git add -A
|
||||||
|
# or
|
||||||
|
git add .
|
||||||
|
```
|
||||||
|
|
||||||
|
但这样可能会跟踪了一些不必要的文件(二进制文件),例如编译产生的 `.o` 文件,和最后产生的可执行文件。事实上,我们只需要跟踪代码源文件即可。为了让 `git` 在添加跟踪文件之前作筛选,你可以编辑 `.gitignore` 文件( 没有的话手动创建 文件名就叫这个 ),在里面给出需要被 `git` 忽略的文件和文件类型。
|
||||||
|
|
||||||
|
这个网页可以根据你搜索的语言来给你创建必要的 `.gitignore` 文件
|
||||||
|
|
||||||
|
```
|
||||||
|
# .gitignore文件示例
|
||||||
|
.idea # 编辑器配置
|
||||||
|
__pycache__ # 缓存文件夹
|
||||||
|
node_modules # 某个可以拉取的模块文件夹
|
||||||
|
dist
|
||||||
|
*.local # 以.local为后缀的文件
|
||||||
|
index.html # 一个文件
|
||||||
|
file.o # 一个编译后的文件
|
||||||
|
```
|
||||||
|
|
||||||
|
建议把编译后的文件都加入 `.gitignore` 并在 `README.md` 文件中留下编译的详细操作流程,节省 `.git` 空间、符合提交规范。
|
||||||
|
|
||||||
|
把新文件加入跟踪列表后, 使用 `git status` 再次确认. 确认无误后就可以存档了, 使用
|
||||||
|
|
||||||
|
```
|
||||||
|
git commit -m "...comment..."
|
||||||
|
```
|
||||||
|
|
||||||
|
提交工程当前的状态(注释)。其中 `...comment...` 是你本次提交的注释( 一般在注释中简略写出本次提交干了什么)以下为注释规范,养成良好习惯请遵守:
|
||||||
|
|
||||||
|
```
|
||||||
|
模板:
|
||||||
|
type(scope): subject
|
||||||
|
|
||||||
|
type为commit的类型
|
||||||
|
feat: 新特性
|
||||||
|
fix: 修改问题
|
||||||
|
refactor: 代码重构
|
||||||
|
docs: 文档修改
|
||||||
|
style: 代码格式修改
|
||||||
|
test: 测试用例修改
|
||||||
|
chore: 其他修改, 比如构建流程, 依赖管理.
|
||||||
|
pref: 性能提升的修改
|
||||||
|
build: 对项目构建或者依赖的改动
|
||||||
|
ci: CI 的修改(ci是自动构建 感兴趣可以搜搜 github workflow )
|
||||||
|
revert: revert 前一个 commit ( 撤销前一个commit )
|
||||||
|
|
||||||
|
scope是文件名/模块名/影响的范围
|
||||||
|
例如 schoolSchedule
|
||||||
|
|
||||||
|
subject为commit概述
|
||||||
|
建议符合 50/72 formatting
|
||||||
|
|
||||||
|
例 feat(JoinForm): add success submit tips
|
||||||
|
|
||||||
|
注意 冒号和subject之间要加空格
|
||||||
|
```
|
||||||
|
|
||||||
|
你可以使用 `git log` 查看存档记录,你应该能看到刚才编辑的注释。
|
||||||
|
|
||||||
|
### <strong>读档</strong><strong>( 回溯到某一个 commit )</strong>
|
||||||
|
|
||||||
|
如果你遇到了上文提到的让你悲痛欲绝的情况,现在你可以使用光玉来救你一命了。首先使用 `git log` 来查看已有的存档,并决定你需要回到哪个过去。每一份存档都有一个 `hash code`,例如 `b87c512d10348fd8f1e32ddea8ec95f87215aaa5` , 你需要通过 `hash code` 来告诉 `git` 你希望读哪一个档。使用以下命令进行读档:
|
||||||
|
|
||||||
|
```
|
||||||
|
git reset --hard b87c
|
||||||
|
```
|
||||||
|
|
||||||
|
其中 `b87c` 是上文 `hash code` 的前缀:你不需要输入整个 hash code. 这时你再看看你的代码,你已经成功地回到了过去!
|
||||||
|
|
||||||
|
但事实上, 在使用 `git reset` 的 `hard` 模式之前, 你需要再三确认选择的存档是不是你的真正目标。 如果你读入了一个较早的存档,那么比这个存档新的所有记录都将被删除!这意味着你不能随便回到“将来”了。
|
||||||
|
|
||||||
|
### 分支
|
||||||
|
|
||||||
|
当然还是有办法来避免上文提到的副作用的,这就是 `git` 的分支功能。使用命令:
|
||||||
|
|
||||||
|
```
|
||||||
|
git branch
|
||||||
|
```
|
||||||
|
|
||||||
|
查看所有分支. 其中 `master` 是主分支,使用 `git init` 初始化之后会自动建立主分支。
|
||||||
|
|
||||||
|
读档的时候使用以下命令:
|
||||||
|
|
||||||
|
```
|
||||||
|
git checkout b87c
|
||||||
|
```
|
||||||
|
|
||||||
|
而不是 `git reset` 。这时你将处于一个虚构的分支中,你可以
|
||||||
|
|
||||||
|
- 查看 `b87c` 存档的内容
|
||||||
|
- 使用以下命令切换到其它分支
|
||||||
|
|
||||||
|
```
|
||||||
|
git checkout 分支名
|
||||||
|
```
|
||||||
|
|
||||||
|
- 对代码的内容进行修改,但你不能使用 `git commit` 进行存档,你需要使用
|
||||||
|
|
||||||
|
```
|
||||||
|
git checkout -B 分支名
|
||||||
|
```
|
||||||
|
|
||||||
|
- 把修改结果保存到一个新的分支中,如果分支已存在,其内容将会被覆盖
|
||||||
|
|
||||||
|
不同的分支之间不会相互干扰,这也给项目的分布式开发带来了便利。有了分支功能,你就可以像第三视点那样在一个世界的不同时间 ( 一个分支的多个存档 ),或者是多个平行世界 ( 多个分支 ) 之间来回穿梭了。
|
||||||
|
|
||||||
|
### <strong>更多功能</strong>
|
||||||
|
|
||||||
|
以上介绍的是 `git` 的一些基本功能,`git` 还提供很多强大的功能,例如使用 `git diff` 比较同一个文件在不同版本中的区别,使用 `git bisect` 进行二分搜索来寻找一个 bug 在哪次提交中被引入...
|
||||||
|
|
||||||
|
其它功能的使用请参考 `git help` , `man git` , 或者在网上搜索相关资料。
|
||||||
|
|
||||||
|
## 全球最大男性交友网站 —— Github
|
||||||
|
|
||||||
|
简介
|
||||||
|
|
||||||
|
作为开源代码库以及版本控制系统,Github 拥有超过 900 万开发者用户。随着越来越多的应用程序转移到了云上,Github 已经成为了管理软件开发以及发现已有代码的首选方法。
|
||||||
|
|
||||||
|
页面大概是这样:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### Git 和 Github
|
||||||
|
|
||||||
|
[GitHub](https://github.com/)[ ](https://github.com/)是一个面向开源及私有软件项目的托管平台,因为只支持 Git 作为唯一的版本库格式进行托管,故名 GitHub。
|
||||||
|
|
||||||
|
### Git 绑定 Github
|
||||||
|
|
||||||
|
#### 第一步:注册账号
|
||||||
|
|
||||||
|
([GitHub 官网](https://github.com/))右上角 sign up 会有一个非常酷炫的界面指引你注册 🥳
|
||||||
|
|
||||||
|
#### 第二步:创建 SSH Key 并获取公钥
|
||||||
|
|
||||||
|
先在 C:\Users\用户名\.ssh 下找有没有 `id_rsa` 和 `id_rsa.pub` 文件
|
||||||
|
|
||||||
|
如果有就直接跳过这一步
|
||||||
|
|
||||||
|
如果没有,打开 Shell( Windows 下打开 Git Bash <em>前提是你已经安装好了 git 在桌面右键应该会有 Git bash here 选项 </em>),创建 SSH Key:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
ssh-keygen -t rsa -C "youremail@example.com" # youremail为你注册用的电子邮件地址
|
||||||
|
```
|
||||||
|
|
||||||
|
打开 `id_rsa.pub`,复制里面的内容
|
||||||
|
|
||||||
|
#### 第三步:绑定 Github
|
||||||
|
|
||||||
|
登陆 `GitHub`,打开 `settings`
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
然后打开左侧栏 `SSH and GPG`` keys` 页面
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
然后,点 `New SSH Key`,填上任意 Title,在 Key 文本框里粘贴 `id_rsa.pub` 文件的内容即可
|
||||||
|
|
||||||
|
#### 第四步:创建仓库并和本地绑定
|
||||||
|
|
||||||
|
绑定完 GitHub 然后你可以创建仓库了
|
||||||
|
首先在 GitHub 主页,找到 “New” 按钮,创建一个新的仓库
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
然后填上这个仓库的大名就可以创建了
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
根据之前学习的方法在本地创建完 git 仓库之后
|
||||||
|
|
||||||
|
在 git bash 中输入:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
git remote add origin git@github.com:yourname/gitexample.git
|
||||||
|
# 请将yourname换成自己的id
|
||||||
|
```
|
||||||
|
|
||||||
|
就可以绑定
|
||||||
|
|
||||||
|
或者是直接 git clone 下来
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
git clone git@github.com:yourname/gitexample.git
|
||||||
|
```
|
||||||
|
|
||||||
|
### 下载代码——clone
|
||||||
|
|
||||||
|
拷贝他人存档也未尝不可,而我们如果用他人存档时,次次都需要一样一样的拷贝文件和代码未免太过折磨,下面简单介绍如何使用
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
git clone [url]
|
||||||
|
```
|
||||||
|
|
||||||
|
接下去对着下面这个 GitHub 的代码使用一下
|
||||||
|
|
||||||
|
首先,代码的 url 在下图所示的位置
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
然后复制完代码后切换回我们的命令行
|
||||||
|
|
||||||
|
```bash
|
||||||
|
e: #powershell or cmd
|
||||||
|
# 进入到想要存储该代码的地方
|
||||||
|
git clone https://github.com/camera-2018/git-example.git
|
||||||
|
```
|
||||||
|
|
||||||
|
一阵抽搐过后就下载好了
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
注意:用完之后别忘记给 camera-2018 点个 follow 呃呃 follow 没用 star 有用
|
||||||
|
|
||||||
|
注意:失败就重试吧 还失败建议使用魔法
|
||||||
|
|
||||||
|
### 提交和合并分支
|
||||||
|
|
||||||
|
如图 我在仓库里新建了 `helloworld.c` 并且写了一些代码
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
接下来是提交操作
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git status #看一下文件暂存区
|
||||||
|
```
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
红色表示文件没有提交到暂存区 我们要提交
|
||||||
|
|
||||||
|
接下来
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add . #将没有提交的所有文件加入暂存区
|
||||||
|
```
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
绿色表示所有文件已加入暂存
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git commit -m "feat(helloworld): add helloworld file"
|
||||||
|
```
|
||||||
|
|
||||||
|
将刚才加入暂区的文件发起了一个提交 注释是 `feat(helloworld): add helloworld file`
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
1. 如果这是你自己的仓库有权限 你就可以直接使用
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git push origin main # origin是第四步里remote add起的远程名字
|
||||||
|
# main是分支名
|
||||||
|
```
|
||||||
|
|
||||||
|
上传本次提交
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
1. 如果你没有本仓库的主分支提交权限 可以提交 pr(pull requests)
|
||||||
|
|
||||||
|
这里假设我是协作者 无主分支权限
|
||||||
|
|
||||||
|
首先创建一个新分支 命名为 `yourname-dev`
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
然后按照上面的方法 `git clone` 并切换到你刚创建的分支
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git switch camera-2018-dev
|
||||||
|
```
|
||||||
|
|
||||||
|
然后提交一个文件 这里使用 vscode 自带的 git 工具试试
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
点暂存所有更改 写好 comment 之后点提交
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
最后点同步更改上传
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
如果是你提交 在 github 上会显示这个 快捷创建 pr 的按钮
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
点它创建 pr
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
这样管理本仓库的人看到 pr 请求就可以 merge 合并辣
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
实际合作过程中可能会出现代码冲突无法 merge 的情况 😋 遇到了自己去 STFW 吧
|
||||||
53
3.编程思维体系构建/3.6.1从CS61A看编程语言学习.md
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
# 从 CS61A 看编程语言学习
|
||||||
|
|
||||||
|
author:ou_e47643905a4829d86c75c884fffc988d
|
||||||
|
|
||||||
|
# 什么是 CS61A
|
||||||
|
|
||||||
|
首先声明,本教程的 python 部分很多内容摘自 CS61A
|
||||||
|
|
||||||
|
如果你看过 CS 自学指南,想必你在第一页就看过这样的描述
|
||||||
|
|
||||||
|
> 大一入学时我是一个对计算机一无所知的小白,装了几十个 G 的 Visual Studio 天天和 OJ 你死我活。凭着高中的数学底子我数学课学得还不错,但在专业课上对竞赛大佬只有仰望。提到编程我只会打开那笨重的 IDE,新建一个我也不知道具体是干啥的命令行项目,然后就是 `cin`, `cout`, `for` 循环,然后 CE, RE, WA 循环。当时的我就处在一种拼命想学好但不知道怎么学,课上认真听讲但题还不会做,课后做作业完全是用时间和它硬耗的痛苦状态。我至今电脑里还存着自己大一上学期计算概论大作业的源代码 —— 一个 1200 行的 C++ 文件,没有头文件、没有类、没有封装、没有 unit test、没有 Makefile、没有 Git,唯一的优点是它确实能跑,缺点是“能跑”的补集。我一度怀疑我是不是不适合学计算机,因为童年对于极客的所有想象,已经被我第一个学期的体验彻底粉碎了。<br/>这一切的转机发生在我大一的寒假,我心血来潮想学习 Python。无意间看到知乎有人推荐了 CS61A 这门课,说是 UC Berkeley 的大一入门课程,讲的就是 Python。我永远不会忘记那一天,打开 [CS61A](https://cs61a.org/) 课程网站的那个瞬间,就像哥伦布发现了新大陆一样,我开启了新世界的大门。<br/>我一口气 3 个星期上完了这门课,它让我第一次感觉到原来 CS 可以学得如此充实而有趣,原来这世上竟有如此精华的课程。<br/>为避免有崇洋媚外之嫌,我单纯从一个学生的视角来讲讲自学 CS61A 的体验:<br/>- 独立搭建的课程网站: 一个网站将所有课程资源整合一体,条理分明的课程 schedule、所有 slides, hw, discussion 的文件链接、详细明确的课程给分说明、历年的考试题与答案。这样一个网站抛开美观程度不谈,既方便学生,也让资源公正透明。<br/>- 课程教授亲自编写的教材:CS61A 这门课的开课老师将 MIT 的经典教材 Structure and Interpretation of Computer Programs (SICP) 用 Python 这门语言进行改编(原教材基于 Scheme 语言),保证了课堂内容与教材内容的一致性,同时补充了更多细节,可以说诚意满满。而且全书开源,可以直接线上阅读。<br/>- 丰富到让人眼花缭乱的课程作业:14 个 lab 巩固随堂知识点,10 个 homework,还有 4 个代码量均上千行的 project。与大家熟悉的 OJ 和 Word 文档式的作业不同,所有作业均有完善的代码框架,保姆级的作业说明。每个 Project 都有详尽的 handout 文档、全自动的评分脚本。CS61A 甚至专门开发了一个[自动化的作业提交评分系统](https://okpy.org/)(据说还发了论文)。当然,有人会说“一个 project 几千行代码大部分都是助教帮你写好的,你还能学到啥?”。此言差矣,作为一个刚刚接触计算机,连安装 Python 都磕磕绊绊的小白来说,这样完善的代码框架既可以让你专注于巩固课堂上学习到的核心知识点,又能有“我才学了一个月就能做一个小游戏了!”的成就感,还能有机会阅读学习别人高质量的代码,从而为自己所用。我觉得在低年级,这种代码框架可以说百利而无一害。唯一的害也许是苦了老师和助教,因为开发这样的作业可想而知需要相当的时间投入。<br/>- 每周 Discussion 讨论课,助教会讲解知识难点和考试例题:类似于北京大学 ICS 的小班研讨,但习题全部用 LaTeX 撰写,相当规范且会明确给出 solution。<br/>这样的课程,你完全不需要任何计算机的基础,你只需要努力、认真、花时间就够了。此前那种有劲没处使的感觉,那种付出再多时间却得不到回报的感觉,从此烟消云散。这太适合我了,我从此爱上了自学。<br/>试想如果有人能把艰深的知识点嚼碎嚼烂,用生动直白的方式呈现给你,还有那么多听起来就很 fancy,种类繁多的 project 来巩固你的理论知识,你会觉得他们真的是在倾尽全力想方设法地让你完全掌握这门课,你会觉得不学好它简直是对这些课程建设者的侮辱。<br/>如果你觉得我在夸大其词,那么不妨从 [CS61A](https://cs61a.org/) 开始,因为它是我的梦开始的地方。
|
||||||
|
|
||||||
|
如果看完了这些,你可能会震惊,会怀疑并且试着打开它并且去尝试这门课程,但是也有可能你会被纯英文的视频或者油管劝退,也有可能你会怀疑我在使用别人的课程体系的前提下仍然要把它放到自己的内容里面的目的,That's all right,我会在下面对她讲的东西进行一定的补充,并且附着上自己的学习建议以及学习思考。
|
||||||
|
|
||||||
|
# 错误的学习方式
|
||||||
|
|
||||||
|
很多人看到要自学 python 之后,第一时间想到的是,我要去 B 站/百度搜一搜,然后一般搜出来就是菜鸟教程,然后就是一连串枯燥乏味的知识堆叠,或者说是培训班的网课,给我们一种知识好像就是这么枯燥乏味以及自己好像学到了很多但是真的用起来却一无所知痛苦万分的感觉。
|
||||||
|
|
||||||
|
我觉得在这个时候大伙可以思考的是,是否我们停留在舒适区的学习方法是错误的呢?
|
||||||
|
|
||||||
|
当然这个时候会出现勇敢的人,尝试这个推荐,但是根据我目前的发现来说,杭电百分之九十五的学生学习一两章之后就荒废了。
|
||||||
|
|
||||||
|
课好吗?
|
||||||
|
|
||||||
|
是很好。
|
||||||
|
|
||||||
|
但是为什么坚持不下来呢?
|
||||||
|
|
||||||
|
根据我的统计,原因无外乎是以下几点:英语太难太劝退了!课程设置太难,好像听懂了但是写起东西来却还是推行不下去!我不知道学了这个能干什么,所以没有动力!学了一两章虽然好像学到了东西,但是感觉有很多东西学了却记不住,导致难度曲线陡增了!<del>游戏太好玩了!</del>
|
||||||
|
|
||||||
|
舒适区看起来很难打破!
|
||||||
|
|
||||||
|
# 正确的思考方式
|
||||||
|
|
||||||
|
面对英语,我们前文有过一而再再而三的提醒过使用正确的工具,但是不得不说的是,在翻译的过程中可能难免丢失了一定的信息,使得我们在困惑中可能变得没有了前进的动力,或者从另一个角度来说我们没有动力是因为没有足够的原因来告诉我们的意识,我们到底应该在做这个超过看菜鸟教程所需精力好多倍的工作,到底能得到除了一点新奇感以外的什么东西,以此来给我们更为充分的理由支撑自己学习完成。
|
||||||
|
|
||||||
|
# 建立正确的认知论
|
||||||
|
|
||||||
|
编程思想本身远比学习某一门编程语言的具体内容更为重要,我们很多的同学在进行这方面内容的时候总是只想着记忆某一门语言的某些内容,然后学的非常的痛苦。
|
||||||
|
|
||||||
|
但不得不提到的是,你学到的语言,技术框架等等在信息化发展如此迅速的现在,可能随时都会过时,诸如早些年间的 B 语言,PHP 等等,到现在都是很少有些人在用的东西了,如果你只扣着一些编程的具体语法,那你学的东西很有可能在某一天就扔进了历史的垃圾堆。
|
||||||
|
|
||||||
|
但是编程语言的设计思想一般不会出现太大的波动,并且就算是发展也有其适配的场景和知识脉络的,如果你乐于去发掘这个知识脉络和思想,那么你就可以优雅的掌握一种思维方式而不是简单的拧螺丝一样的机械化工作。而好的思考方式往往是可以应用在同类的所有语言甚至是在所有的更多的
|
||||||
|
|
||||||
|
# 更有趣的练习方式
|
||||||
|
|
||||||
|
我不得不承认的一点是,越痛苦的练习往往可以让你获得更大的提升模拟的成长往往与你面对苦难以及解决他的时间是成正比的。
|
||||||
|
|
||||||
|
不过遗憾的是,我们大多数的同学是在面对跳起来都够不到的反馈的时候,会选择放弃。(除非你有 M 的倾向)
|
||||||
|
|
||||||
|
因此,有时候我们说大道至简。好的东西往往是能让人们快速理解的东西,我觉得 61A 的难度梯度设计,就是兼具了趣味性和间接性的,并且全面优于互联网上的非常多的教程,比硬啃要给我们更多的正反馈(当然,改变思维和学习方式是很重要的。
|
||||||
|
|
||||||
|
#
|
||||||
51
3.编程思维体系构建/3.6.2环境配置.md
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
# 环境配置
|
||||||
|
|
||||||
|
当你开始制作大型项目或者复现论文时,环境配置就开始变得至关重要。
|
||||||
|
|
||||||
|
# 什么是环境?
|
||||||
|
|
||||||
|
环境是<strong>包的集合</strong>,我们一般用 Anaconda 来配置虚拟环境。
|
||||||
|
|
||||||
|
[戳这里安装](https://www.anaconda.com/)
|
||||||
|
|
||||||
|
装下来之后具体操作可以看[安装教程](https://blog.csdn.net/in546/article/details/117400839),如果自动配置环境变量的选项是灰色的话,请按照下面的教程把下面的几个文件路径加入环境变量。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
在里面添加并写入文件路径加入就好了~
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
然后打开 Pycharm,创建新项目,设置按照以下方式操作,记得挂梯子。
|
||||||
|
|
||||||
|
如果不挂梯子,请按照教程配置清华源。[我是教程](https://blog.csdn.net/jasneik/article/details/114227716)
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
然后一个新的环境就创建好辣~
|
||||||
|
|
||||||
|
# 如何配置环境
|
||||||
|
|
||||||
|
## 1.配置你自己的环境
|
||||||
|
|
||||||
|
你可以尝试命令 `pip install <包的名字>` 或者 `conda install <包的名字>`
|
||||||
|
|
||||||
|
```
|
||||||
|
在下载某个包失败的时候可以查一查有没有人写相关攻略~
|
||||||
|
```
|
||||||
|
|
||||||
|
你可以用 `conda list` 查看你这个环境已有的包。你也可以在包的名字后面加上 `==版本号` 来指定版本。
|
||||||
|
|
||||||
|
```
|
||||||
|
请注意各个包之间的依赖关系,否则容易导致无法运行或效果变差!
|
||||||
|
```
|
||||||
|
|
||||||
|
## 2.复现论文代码时配置环境
|
||||||
|
|
||||||
|
```
|
||||||
|
一般我们可以在Github的README中找到环境的配置方法,遇到难以下载的特殊版本包时可以考虑下载它的源码手动编译,具体流程不展开了,可以自行搜索
|
||||||
|
```
|
||||||
55
3.编程思维体系构建/3.6.3安装python.md
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
# 安装 python
|
||||||
|
|
||||||
|
教程
|
||||||
|
|
||||||
|
[Python 小白必看,非常生动的 Pycharm 与 Anaconda 安装教学,干货!_哔哩哔哩_bilibili](https://www.bilibili.com/video/BV1Bp4y117UW?p=1&share_medium=android&share_plat=android&share_source=COPY&share_tag=s_i×tamp=1623240637&unique_k=vHC5Wg)
|
||||||
|
|
||||||
|
[Win10 下 Conda-Pycharm-Pytorch 的安装_哔哩哔哩_bilibili](https://www.bilibili.com/video/BV15U4y1J7Ss?from=search&seid=1987861827719523712&spm_id_from=333.337.0.0)
|
||||||
|
|
||||||
|
# 巧妇难为无米之炊
|
||||||
|
|
||||||
|
你可以在终端上用 Python 解释器
|
||||||
|
|
||||||
|
也可以尝试使用 VSC,Pycharm 等集成开发环境
|
||||||
|
|
||||||
|
同样我们也推荐你使用 Jupyter Notebook
|
||||||
|
|
||||||
|
我们推荐你都进行一波尝试,同样这也会作为一个任务
|
||||||
|
|
||||||
|
# 解释器
|
||||||
|
|
||||||
|
# Windows 用户
|
||||||
|
|
||||||
|
打开 [Python 官方网站](https://www.python.org/),找到“Download”里的“Latest: Python 3.x.y”。
|
||||||
|
|
||||||
|
<strong>下载完成后,请大家按照下图的示意,务必勾选“Add Python 3.x to PATH”,然后再点击“Install Now”,等待安装完成后关闭安装程序。</strong>
|
||||||
|
|
||||||
|
<strong>注意:windows11 安装好后 命令行输入 python 可能会跳到 Microsoft 应用商店 可在 customize installation(自定义安装)next 勾选 install for all users</strong>
|
||||||
|
|
||||||
|
## GNU/Linux 系统
|
||||||
|
|
||||||
|
在终端输入 `sudo apt install python3` 即可完成 Python3 的全部安装流程
|
||||||
|
|
||||||
|
可以输入 `python3 --version` 检验是否成功。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
# Jupyter Notebook
|
||||||
|
|
||||||
|
[官方网站](https://jupyter.org/) Jupyter Notebook 是基于网页的用于交互计算的应用程序。其可被应用于全过程计算:开发、文档编写、运行代码和展示结果。——[Jupyter ](https://link.zhihu.com/?target=https%3A//jupyter-notebook.readthedocs.io/en/stable/notebook.html)
|
||||||
|
|
||||||
|
你在一个框框中直接输入代码,运行,它立马就在下面给你输出。怎么样,是不是很酷?
|
||||||
|
|
||||||
|
[Notebook 官方介绍](https://link.zhihu.com/?target=https%3A//jupyter-notebook.readthedocs.io/en/stable/notebook.html)
|
||||||
|
|
||||||
|
可能需要你安装 anaconda,如果你不知道这是什么,请去阅读这篇文章并进行相关配置 [Anaconda](https://zhuanlan.zhihu.com/p/32925500)(STFW)
|
||||||
|
|
||||||
|
安装完 jupyer 后,可以在终端直接输入
|
||||||
|
|
||||||
|
jupyter notebook
|
||||||
|
|
||||||
|
进行使用
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
[Pycharm](https://www.jetbrains.com/zh-cn/pycharm/):可能很多同学已经用上了,我在这里不做更多解释
|
||||||
81
3.编程思维体系构建/3.6.4.0阶段零:Python解释器.md
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
# 阶段零:Python 解释器
|
||||||
|
|
||||||
|
可参考资料
|
||||||
|
|
||||||
|
[官方文档](https://wiki.python.org/moin/BeginnersGuide)
|
||||||
|
|
||||||
|
[菜鸟教程](https://www.runoob.com/python3/python3-interpreter.html)
|
||||||
|
|
||||||
|
你可以在终端与解释器进行交互
|
||||||
|
|
||||||
|
在终端中输入 python 即可进入解释器
|
||||||
|
|
||||||
|
解释器可以进行简单的表达式和语句操作
|
||||||
|
|
||||||
|
你可以自己把玩一下
|
||||||
|
|
||||||
|
```
|
||||||
|
>>> 1 + 2
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
3
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
>>> 3 - 2
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
1
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
>>> 5 * 6
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
30
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
>>> 7 / 4
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
1.75
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
>>> 7 // 4
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
1
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
>>> 7 % 4
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
3
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
>>> 4**3
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
64
|
||||||
|
```
|
||||||
|
|
||||||
|
同时可以输入 `exit``()` 或按 Ctrl+D 退出交互
|
||||||
|
|
||||||
|
同学们可能已经发现 python 这门编程语言的神奇之处了
|
||||||
|
|
||||||
|
在这里留一个思考题
|
||||||
|
|
||||||
|
为什么 python 可以做出不需要任何语句的神奇操作呢?
|
||||||
|
|
||||||
|
别的语言可以这样吗?
|
||||||
73
3.编程思维体系构建/3.6.4.1阶段一:熟悉语句.md
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
# 阶段一:熟悉语句
|
||||||
|
|
||||||
|
在进行本章之前,请你谨记一个原则:基本所有的功能都被人提前实现好了
|
||||||
|
|
||||||
|
你需要关心的仅仅是逻辑该如何设立
|
||||||
|
|
||||||
|
在做本章任务前,请熟悉 python 的函数,循环和判断语句即可
|
||||||
|
|
||||||
|
P1:请仅使用一行语句求出三个数的最小平方和
|
||||||
|
|
||||||
|
```python
|
||||||
|
def two_of_three(x, y, z):
|
||||||
|
"""Return a*a + b*b, where a and b are the two smallest members of the
|
||||||
|
positive numbers x, y, and z.
|
||||||
|
|
||||||
|
>>> two_of_three(1, 2, 3)
|
||||||
|
5
|
||||||
|
>>> two_of_three(5, 3, 1)
|
||||||
|
10
|
||||||
|
>>> two_of_three(10, 2, 8)
|
||||||
|
68
|
||||||
|
>>> two_of_three(5, 5, 5)
|
||||||
|
50
|
||||||
|
>>> # check that your code consists of nothing but an expression (this docstring)
|
||||||
|
>>> # and a return statement
|
||||||
|
>>> import inspect, ast
|
||||||
|
>>> [type(x).__name__ for x in ast.parse(inspect.getsource(two_of_three)).body[0].body]
|
||||||
|
['Expr', 'Return']
|
||||||
|
"""
|
||||||
|
return _____
|
||||||
|
```
|
||||||
|
|
||||||
|
提示:可以使用 max()函数哦
|
||||||
|
|
||||||
|
P2:下降阶乘
|
||||||
|
|
||||||
|
```python
|
||||||
|
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
|
||||||
|
"""
|
||||||
|
"*** YOUR CODE HERE ***"
|
||||||
|
```
|
||||||
|
|
||||||
|
P3:判断一个函数是否有两个或者两个连续的 8
|
||||||
|
|
||||||
|
```python
|
||||||
|
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
|
||||||
|
"""
|
||||||
|
"*** YOUR CODE HERE ***"
|
||||||
|
```
|
||||||
145
3.编程思维体系构建/3.6.4.2阶段二:递归操作.md
Normal file
@@ -0,0 +1,145 @@
|
|||||||
|
# 阶段二:递归操作
|
||||||
|
|
||||||
|
什么是递归呢?
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
#
|
||||||
|
|
||||||
|
# 释义
|
||||||
|
|
||||||
|
递归是在函数主体中重复调用函数的基本方案
|
||||||
|
|
||||||
|
让我们来看一个经典的例子
|
||||||
|
|
||||||
|
> 阶乘,即 n!=n*(n-1)*......*2*1<br/>例如: `5! = 5 * 4 * 3 * 2 * 1 = 120`.
|
||||||
|
|
||||||
|
而阶乘的代码如下编辑
|
||||||
|
|
||||||
|
```python
|
||||||
|
def factorial(n):
|
||||||
|
if n == 0:
|
||||||
|
return 1
|
||||||
|
return n * factorial(n - 1)
|
||||||
|
```
|
||||||
|
|
||||||
|
编写递归函数的一些小 tips:
|
||||||
|
|
||||||
|
- 你必须假设之前的所有功能都是正确的,这种被称为:the recursive leap of faith
|
||||||
|
- 想想在最简单的情况下函数将如何跳转
|
||||||
|
- 考虑使用问题的更简单版本来进行解决问题
|
||||||
|
|
||||||
|
# 任务
|
||||||
|
|
||||||
|
P4:编写一个递归函数 `skip_add`,它接受一个参数 n 并返回 `n + n-2 + n-4 + n-6 + ... + 0`。假设 n 是非负数。
|
||||||
|
|
||||||
|
```python
|
||||||
|
def skip_add(n):
|
||||||
|
""" Takes a number n and returns n + n-2 + n-4 + n-6 + ... + 0.
|
||||||
|
|
||||||
|
>>> skip_add(5) # 5 + 3 + 1 + 0
|
||||||
|
9
|
||||||
|
>>> skip_add(10) # 10 + 8 + 6 + 4 + 2 + 0
|
||||||
|
30
|
||||||
|
|
||||||
|
"""
|
||||||
|
"*** YOUR CODE HERE ***"
|
||||||
|
```
|
||||||
|
|
||||||
|
P5:GCD,给出两个正整数,求出两个正整数的最大公约数
|
||||||
|
|
||||||
|
Euclid, a Greek mathematician in 300 B.C., realized that the greatest common divisor of `a` and `b` is one of the following:
|
||||||
|
|
||||||
|
- the smaller value if it evenly divides the larger value, or
|
||||||
|
- the greatest common divisor of the smaller value and the remainder of the larger value divided by the smaller value.
|
||||||
|
|
||||||
|
提示:gcd(a, b) = gcd(b, a % b)
|
||||||
|
|
||||||
|
```python
|
||||||
|
def gcd(a, b):
|
||||||
|
"""Returns the greatest common divisor of a and b.
|
||||||
|
Should be implemented using recursion.
|
||||||
|
|
||||||
|
>>> gcd(34, 19)
|
||||||
|
1
|
||||||
|
>>> gcd(39, 91)
|
||||||
|
13
|
||||||
|
>>> gcd(20, 30)
|
||||||
|
10
|
||||||
|
>>> gcd(40, 40)
|
||||||
|
40
|
||||||
|
"""
|
||||||
|
"*** YOUR CODE HERE ***"7
|
||||||
|
```
|
||||||
|
|
||||||
|
P6:汉诺塔问题(选做)
|
||||||
|
|
||||||
|
汉诺塔:汉诺塔(又称河内塔)问题是源于印度一个古老传说的益智玩具。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着 64 片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。
|
||||||
|
|
||||||
|
汉诺塔有递归和非递归两种方法,你最好选择递归的方法进行书写
|
||||||
|
|
||||||
|
```python
|
||||||
|
def print_move(origin, destination):
|
||||||
|
"""Print instructions to move a disk."""
|
||||||
|
print("Move the top disk from rod", origin, "to rod", destination)
|
||||||
|
|
||||||
|
def move_stack(n, start, end):
|
||||||
|
"""Print the moves required to move n disks on the start pole to the end
|
||||||
|
pole without violating the rules of Towers of Hanoi.
|
||||||
|
|
||||||
|
n -- number of disks
|
||||||
|
start -- a pole position, either 1, 2, or 3
|
||||||
|
end -- a pole position, either 1, 2, or 3
|
||||||
|
|
||||||
|
There are exactly three poles, and start and end must be different. Assume
|
||||||
|
that the start pole has at least n disks of increasing size, and the end
|
||||||
|
pole is either empty or has a top disk larger than the top n start disks.
|
||||||
|
|
||||||
|
>>> move_stack(1, 1, 3)
|
||||||
|
Move the top disk from rod 1 to rod 3
|
||||||
|
>>> move_stack(2, 1, 3)
|
||||||
|
Move the top disk from rod 1 to rod 2
|
||||||
|
Move the top disk from rod 1 to rod 3
|
||||||
|
Move the top disk from rod 2 to rod 3
|
||||||
|
>>> move_stack(3, 1, 3)
|
||||||
|
Move the top disk from rod 1 to rod 3
|
||||||
|
Move the top disk from rod 1 to rod 2
|
||||||
|
Move the top disk from rod 3 to rod 2
|
||||||
|
Move the top disk from rod 1 to rod 3
|
||||||
|
Move the top disk from rod 2 to rod 1
|
||||||
|
Move the top disk from rod 2 to rod 3
|
||||||
|
Move the top disk from rod 1 to rod 3
|
||||||
|
"""
|
||||||
|
assert 1 <= start <= 3 and 1 <= end <= 3 and start != end, "Bad start/end"
|
||||||
|
"*** YOUR CODE HERE ***"
|
||||||
|
```
|
||||||
|
|
||||||
|
ZZM 在这里恶意提升亿下难度,你能不能尝试理解下面这个用 C 语言写的汉诺塔呢
|
||||||
|
|
||||||
|
当然,是非递归!
|
||||||
|
|
||||||
|
```c
|
||||||
|
typedef struct {
|
||||||
|
int pc, n;
|
||||||
|
char from, to, via;
|
||||||
|
} Frame;
|
||||||
|
|
||||||
|
#define call(...) ({ *(++top) = (Frame) { .pc = 0, __VA_ARGS__ }; })
|
||||||
|
#define ret() ({ top--; })
|
||||||
|
#define goto(loc) ({ f->pc = (loc) - 1; })
|
||||||
|
|
||||||
|
void hanoi(int n, char from, char to, char via) {
|
||||||
|
Frame stk[64], *top = stk - 1;
|
||||||
|
call(n, from, to, via);
|
||||||
|
for (Frame *f; (f = top) >= stk; f->pc++) {
|
||||||
|
switch (f->pc) {
|
||||||
|
case 0: if (f->n == 1) { printf("%c -> %c\n", f->from, f->to); goto(4); } break;
|
||||||
|
case 1: call(f->n - 1, f->from, f->via, f->to); break;
|
||||||
|
case 2: call( 1, f->from, f->to, f->via); break;
|
||||||
|
case 3: call(f->n - 1, f->via, f->to, f->from); break;
|
||||||
|
case 4: ret(); break;
|
||||||
|
default: assert(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
311
3.编程思维体系构建/3.6.4.3阶段三:数据抽象.md
Normal file
@@ -0,0 +1,311 @@
|
|||||||
|
# 阶段三:数据抽象
|
||||||
|
|
||||||
|
数据抽象(Data Abstraction)
|
||||||
|
|
||||||
|
[可参考教程](https://zhuanlan.zhihu.com/p/343133774)
|
||||||
|
|
||||||
|
各位需要认真了解以下内容,他们是构建任何大厦的基石
|
||||||
|
|
||||||
|
# Data Abstraction
|
||||||
|
|
||||||
|
数据抽象是一个伟大的概念,它允许程序员将代码以对象的形式进行看待,并且从更高的层面去审视问题。
|
||||||
|
|
||||||
|
简单来说,它可以帮助程序员不用具体去了解程序做了什么,而是更去重视它有什么用。
|
||||||
|
|
||||||
|
举个例子:你在开车时,如果要控制发动机的活塞怎么动,对你来说是否有些太过于困难了。因此将其抽象成了离合器,油门,刹车这些较为简单的操作。
|
||||||
|
|
||||||
|
# 组成
|
||||||
|
|
||||||
|
一个抽象的数据类型(ADT)由两个主要部分组成
|
||||||
|
|
||||||
|
- Constructors:架构抽象数据类型的主要函数
|
||||||
|
- Selectors:操作数据类型的各式方法
|
||||||
|
|
||||||
|
# 列表与元组
|
||||||
|
|
||||||
|
列表是可以存储多个元素的 Python 数据结构。每个元素可以是任何类型,甚至可以是另一个列表!
|
||||||
|
|
||||||
|
```python
|
||||||
|
>>> list_of_nums = [1, 2, 3, 4]
|
||||||
|
>>> list_of_bools = [True, True, False, False]
|
||||||
|
>>> nested_lists = [1, [2, 3], [4, [5]]]
|
||||||
|
```
|
||||||
|
|
||||||
|
其可以随意的增加删除或改动元素
|
||||||
|
|
||||||
|
元组何其差不多,但是最大的差距在于,元组是静态的,不可随意更改的,要想改动,必须重新开启一片内存空间
|
||||||
|
|
||||||
|
```python
|
||||||
|
tup = (1, 2, 3, 4)
|
||||||
|
new_tup = tup + (5, ) # 创建新的元组new_tup,并依次填充原元组的值
|
||||||
|
new _tup
|
||||||
|
(1, 2, 3, 4, 5)
|
||||||
|
|
||||||
|
l = [1, 2, 3, 4]
|
||||||
|
l.append(5) # 添加元素5到原列表的末尾
|
||||||
|
l
|
||||||
|
[1, 2, 3, 4, 5]
|
||||||
|
```
|
||||||
|
|
||||||
|
同时,你可以对列表和元组进行索引,甚至使用:进行切片操作,这部分内容在以后的任务会有体现
|
||||||
|
|
||||||
|
```python
|
||||||
|
>>> lst = [True, False, True, True, False]
|
||||||
|
>>> lst[1:4]
|
||||||
|
[False, True, True]
|
||||||
|
>>> lst[:3] # Start index defaults to 0
|
||||||
|
[True, False, True]
|
||||||
|
>>> lst[3:] # End index defaults to len(lst)
|
||||||
|
[True, False]
|
||||||
|
>>> lst[:] # Creates a copy of the whole list
|
||||||
|
[True, False, True, True, False]
|
||||||
|
```
|
||||||
|
|
||||||
|
```python
|
||||||
|
>>> lst = [6, 5, 4, 3, 2, 1]
|
||||||
|
>>> lst[0]
|
||||||
|
6
|
||||||
|
>>> lst[3]
|
||||||
|
3
|
||||||
|
```
|
||||||
|
|
||||||
|
思考题:
|
||||||
|
|
||||||
|
列表和元组在性能上有什么差异呢?
|
||||||
|
|
||||||
|
他们对应的使用场景有哪些呢?
|
||||||
|
|
||||||
|
# 字典与集合
|
||||||
|
|
||||||
|
字典是一系列由键(key)和值(value)配对组成的元素的集合,在 Python3.7+,字典被确定为有序
|
||||||
|
|
||||||
|
相比于列表和元组,字典的性能更优,特别是对于查找、添加和删除操作,字典都能在常数时间复杂度内完成。
|
||||||
|
|
||||||
|
而集合和字典基本相同,唯一的区别,就是集合没有键和值的配对,是一系列无序的、唯一的元素组合。
|
||||||
|
|
||||||
|
```python
|
||||||
|
d1 = {'name': 'jason', 'age': 20, 'gender': 'male'}
|
||||||
|
d2 = dict({'name': 'jason', 'age': 20, 'gender': 'male'})
|
||||||
|
d3 = dict([('name', 'jason'), ('age', 20), ('gender', 'male')])
|
||||||
|
d4 = dict(name='jason', age=20, gender='male')
|
||||||
|
d1 == d2 == d3 ==d4
|
||||||
|
True
|
||||||
|
|
||||||
|
s1 = {1, 2, 3}
|
||||||
|
s2 = set([1, 2, 3])
|
||||||
|
s1 == s2
|
||||||
|
True
|
||||||
|
```
|
||||||
|
|
||||||
|
当然,除了创建和访问,字典和集合也同样支持增加、删除、更新等操作。
|
||||||
|
|
||||||
|
```python
|
||||||
|
d = {'name': 'jason', 'age': 20}
|
||||||
|
d['gender'] = 'male' # 增加元素对'gender': 'male'
|
||||||
|
d['dob'] = '1999-02-01' # 增加元素对'dob': '1999-02-01'
|
||||||
|
d
|
||||||
|
{'name': 'jason', 'age': 20, 'gender': 'male', 'dob': '1999-02-01'}
|
||||||
|
d['dob'] = '1998-01-01' # 更新键'dob'对应的值
|
||||||
|
d.pop('dob') # 删除键为'dob'的元素对
|
||||||
|
'1998-01-01'
|
||||||
|
d
|
||||||
|
{'name': 'jason', 'age': 20, 'gender': 'male'}
|
||||||
|
|
||||||
|
s = {1, 2, 3}
|
||||||
|
s.add(4) # 增加元素4到集合
|
||||||
|
s
|
||||||
|
{1, 2, 3, 4}
|
||||||
|
s.remove(4) # 从集合中删除元素4
|
||||||
|
s
|
||||||
|
{1, 2, 3}
|
||||||
|
```
|
||||||
|
|
||||||
|
思考题:
|
||||||
|
|
||||||
|
字典和集合分别是什么原理呢?
|
||||||
|
|
||||||
|
字典可以是一个列表吗?为什么?
|
||||||
|
|
||||||
|
# 可变性
|
||||||
|
|
||||||
|
我们说如果一个对象可以由代码进行操作而改变那么我们称其具有可变性。
|
||||||
|
|
||||||
|
可变对象的示例包括列表和字典。不可变对象的示例包括元组和函数。
|
||||||
|
|
||||||
|
我们假定已经知道了如何使用 `==` 运算符来检查两个表达式的计算结果是否<strong>相同</strong>。
|
||||||
|
|
||||||
|
我们现在引入一个新的比较运算符 `is`,它检查两个表达式的计算结果是否<strong>相同</strong>。
|
||||||
|
|
||||||
|
```python
|
||||||
|
>>> 2 + 2 == 3 + 1
|
||||||
|
True
|
||||||
|
>>> 2 + 2 is 3 + 1
|
||||||
|
True
|
||||||
|
```
|
||||||
|
|
||||||
|
有什么不同呢?
|
||||||
|
|
||||||
|
```python
|
||||||
|
>>> large_num1 = 23333333333333333333
|
||||||
|
>>> large_num2 = 23333333333333333333
|
||||||
|
>>> large_num1 == large_num2
|
||||||
|
True
|
||||||
|
>>> large_num1 is large_num2
|
||||||
|
False
|
||||||
|
>>> lst1 = [1, 2, 3, 4]
|
||||||
|
>>> lst2 = [1, 2, 3, 4]
|
||||||
|
>>> lst1 == lst2
|
||||||
|
True
|
||||||
|
>>> lst1 is lst2
|
||||||
|
False
|
||||||
|
```
|
||||||
|
|
||||||
|
欸?为什么最后一个不一样了?
|
||||||
|
|
||||||
|
其实原因是,你创建的两个列表虽然内容相同,但是毕竟是两个不同的列表,其在内存空间上并不一样。
|
||||||
|
|
||||||
|
这在讨论可变性的时候非常重要,当我们改变一个数的值的时候这非常重要
|
||||||
|
|
||||||
|
```python
|
||||||
|
>>> lst1 = [1, 2, 3, 4]
|
||||||
|
>>> lst2 = lst1
|
||||||
|
>>> lst1.append(5)
|
||||||
|
>>> lst2
|
||||||
|
[1, 2, 3, 4, 5]
|
||||||
|
>>> lst1 is lst2
|
||||||
|
True
|
||||||
|
```
|
||||||
|
|
||||||
|
思考题,你能否从指针的角度去理解可变性呢?
|
||||||
|
|
||||||
|
# 任务
|
||||||
|
|
||||||
|
P7:9*9 乘法表
|
||||||
|
|
||||||
|
可能现在对你来说,构建像下图这样的 99 乘法表已经是非常容易的一件事了,可是如果我要求你使用 python 的列表生成器,在两行以内完成呢?
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
P8:couple 情侣
|
||||||
|
|
||||||
|
实现函数 `couple`,它接受两个列表并返回一个列表,其中包含两个序列的第 i 个元素耦合在一起的列表。您可以假设两个序列的长度相同。
|
||||||
|
|
||||||
|
```python
|
||||||
|
def couple(lst1, lst2):
|
||||||
|
"""Return a list that contains lists with i-th elements of two sequences
|
||||||
|
coupled together.
|
||||||
|
>>> lst1 = [1, 2, 3]
|
||||||
|
>>> lst2 = [4, 5, 6]
|
||||||
|
>>> couple(lst1, lst2)
|
||||||
|
[[1, 4], [2, 5], [3, 6]]
|
||||||
|
>>> lst3 = ['c', 6]
|
||||||
|
>>> lst4 = ['s', '1']
|
||||||
|
>>> couple(lst3, lst4)
|
||||||
|
[['c', 's'], [6, '1']]
|
||||||
|
"""
|
||||||
|
assert len(lst1) == len(lst2)
|
||||||
|
"*** YOUR CODE HERE ***"
|
||||||
|
```
|
||||||
|
|
||||||
|
P 8.5:对城市数据抽象
|
||||||
|
|
||||||
|
假设我们有一个城市的抽象数据类型。城市有名称、纬度坐标和经度坐标。
|
||||||
|
|
||||||
|
这是我们构造城市的函数
|
||||||
|
|
||||||
|
make_city(name, lat, lon)
|
||||||
|
|
||||||
|
构建一个城市对象有经纬度和名字
|
||||||
|
|
||||||
|
- `get_name(city)`:返回城市名称
|
||||||
|
- `get_lat(city)`:返回城市的纬度
|
||||||
|
- `get_lon(city)`:返回城市的经度
|
||||||
|
|
||||||
|
```python
|
||||||
|
>>> nanjing = make_city('Nanjing', 31, 118)
|
||||||
|
>>> get_name(nanjing)
|
||||||
|
'Nanjing'
|
||||||
|
>>> get_lat(nanjing)
|
||||||
|
31
|
||||||
|
>>> beijing = make_city('Beijing', 39, 116)
|
||||||
|
>>> get_lon(beijing)
|
||||||
|
116
|
||||||
|
```
|
||||||
|
|
||||||
|
```python
|
||||||
|
def make_city(name, lat, lon):
|
||||||
|
<em>"""</em>
|
||||||
|
<em> >>> city = make_city('Berkeley', 0, 1)</em>
|
||||||
|
<em> >>> get_name(city)</em>
|
||||||
|
<em> 'Berkeley'</em>
|
||||||
|
<em> >>> get_lat(city)</em>
|
||||||
|
<em> 0</em>
|
||||||
|
<em> >>> get_lon(city)</em>
|
||||||
|
<em> 1</em>
|
||||||
|
<em> """</em>
|
||||||
|
<em> </em>return [name, lat, lon]
|
||||||
|
|
||||||
|
def get_name(city):
|
||||||
|
<em>"""</em>
|
||||||
|
<em> >>> city = make_city('Berkeley', 0, 1)</em>
|
||||||
|
<em> >>> get_name(city)</em>
|
||||||
|
<em> 'Berkeley'</em>
|
||||||
|
<em> """</em>
|
||||||
|
<em> </em>return city[0]
|
||||||
|
|
||||||
|
def get_lat(city):
|
||||||
|
<em>"""</em>
|
||||||
|
<em> >>> city = make_city('Berkeley', 0, 1)</em>
|
||||||
|
<em> >>> get_lat(city)</em>
|
||||||
|
<em> 0</em>
|
||||||
|
<em> """</em>
|
||||||
|
<em> </em>return city[1]
|
||||||
|
|
||||||
|
def get_lon(city):
|
||||||
|
<em>"""</em>
|
||||||
|
<em> >>> city = make_city('Berkeley', 0, 1)</em>
|
||||||
|
<em> >>> get_lon(city)</em>
|
||||||
|
<em> 1</em>
|
||||||
|
<em> """</em>
|
||||||
|
<em> </em>return city[2]
|
||||||
|
```
|
||||||
|
|
||||||
|
首先你试试求出两个地方的距离。
|
||||||
|
|
||||||
|
`(x2, y2)` 可以通过计算 的 sqrt 来找到 `(x1 - x2)**2 + (y1 - y2)**2`。`sqrt` 我们引用了
|
||||||
|
|
||||||
|
```python
|
||||||
|
from math import sqrt
|
||||||
|
def distance(city1, city2):
|
||||||
|
"""
|
||||||
|
>>> city1 = make_city('city1', 0, 1)
|
||||||
|
>>> city2 = make_city('city2', 0, 2)
|
||||||
|
>>> distance(city1, city2)
|
||||||
|
1.0
|
||||||
|
>>> city3 = make_city('city3', 6.5, 12)
|
||||||
|
>>> city4 = make_city('city4', 2.5, 15)
|
||||||
|
>>> distance(city3, city4)
|
||||||
|
5.0
|
||||||
|
"""
|
||||||
|
"*** YOUR CODE HERE ***"
|
||||||
|
```
|
||||||
|
|
||||||
|
实现 `closer_city` 一个函数,该函数接受一个纬度、经度和两个城市,并返回与提供的经纬度相对较近的城市名称。
|
||||||
|
|
||||||
|
```python
|
||||||
|
def closer_city(lat, lon, city1, city2):
|
||||||
|
"""
|
||||||
|
Returns the name of either city1 or city2, whichever is closest to
|
||||||
|
coordinate (lat, lon).
|
||||||
|
|
||||||
|
>>> berkeley = make_city('Berkeley', 37.87, 112.26)
|
||||||
|
>>> stanford = make_city('Stanford', 34.05, 118.25)
|
||||||
|
>>> closer_city(38.33, 121.44, berkeley, stanford)
|
||||||
|
'Stanford'
|
||||||
|
>>> bucharest = make_city('Bucharest', 44.43, 26.10)
|
||||||
|
>>> vienna = make_city('Vienna', 48.20, 16.37)
|
||||||
|
>>> closer_city(41.29, 174.78, bucharest, vienna)
|
||||||
|
'Bucharest'
|
||||||
|
"""
|
||||||
|
"*** YOUR CODE HERE ***"
|
||||||
|
```
|
||||||
147
3.编程思维体系构建/3.6.4.4阶段四:高阶函数.md
Normal file
@@ -0,0 +1,147 @@
|
|||||||
|
# 阶段四:高阶函数
|
||||||
|
|
||||||
|
阅读以及完成本部分内容可以帮助你有效减少代码冗余。
|
||||||
|
|
||||||
|
让你完成更为优雅的代码
|
||||||
|
|
||||||
|
各位要记住的是
|
||||||
|
|
||||||
|
# 代码首先是给人看的
|
||||||
|
|
||||||
|
机器看的永远只是你的机器码。
|
||||||
|
|
||||||
|
可参考教程 [Lambda](https://zhuanlan.zhihu.com/p/80960485)
|
||||||
|
|
||||||
|
# Lambda 介绍
|
||||||
|
|
||||||
|
Lambda 表达式是通过指定两件事来评估函数的表达式:参数和返回表达式。
|
||||||
|
|
||||||
|
请尝试阅读以下英文表格,对比函数与 lambda 表达式的不同
|
||||||
|
|
||||||
|
# Lambda 实验
|
||||||
|
|
||||||
|
以下代码 python 会显示什么?通过对这些代码的实验,加深你对代码的学习
|
||||||
|
|
||||||
|
提示:当你对解释器输入 x 或 x=none 时什么都没有
|
||||||
|
|
||||||
|
```python
|
||||||
|
>>> lambda x: x # A lambda expression with one parameter x
|
||||||
|
______
|
||||||
|
|
||||||
|
>>> a = lambda x: x # Assigning the lambda function to the name a
|
||||||
|
>>> a(5)
|
||||||
|
______
|
||||||
|
|
||||||
|
>>> (lambda: 3)() # Using a lambda expression as an operator in a call exp.
|
||||||
|
______
|
||||||
|
|
||||||
|
>>> b = lambda x: lambda: x # Lambdas can return other lambdas!
|
||||||
|
>>> c = b(88)
|
||||||
|
>>> c
|
||||||
|
______
|
||||||
|
|
||||||
|
>>> c()
|
||||||
|
______
|
||||||
|
|
||||||
|
>>> d = lambda f: f(4) # They can have functions as arguments as well.
|
||||||
|
>>> def square(x):
|
||||||
|
... return x * x
|
||||||
|
>>> d(square)
|
||||||
|
______
|
||||||
|
```
|
||||||
|
|
||||||
|
```python
|
||||||
|
>>> higher_order_lambda = lambda f: lambda x: f(x)
|
||||||
|
>>> g = lambda x: x * x
|
||||||
|
>>> higher_order_lambda(2)(g) # Which argument belongs to which function call?
|
||||||
|
______
|
||||||
|
|
||||||
|
>>> higher_order_lambda(g)(2)
|
||||||
|
______
|
||||||
|
|
||||||
|
>>> call_thrice = lambda f: lambda x: f(f(f(x)))
|
||||||
|
>>> call_thrice(lambda y: y + 1)(0)
|
||||||
|
______
|
||||||
|
|
||||||
|
>>> print_lambda = lambda z: print(z) # When is the return expression of a lambda expression executed?
|
||||||
|
>>> print_lambda
|
||||||
|
______
|
||||||
|
|
||||||
|
>>> one_thousand = print_lambda(1000)
|
||||||
|
______
|
||||||
|
|
||||||
|
>>> one_thousand
|
||||||
|
______
|
||||||
|
```
|
||||||
|
|
||||||
|
# 任务
|
||||||
|
|
||||||
|
P9:我们发现以下两个函数看起来实现的非常相似
|
||||||
|
|
||||||
|
```python
|
||||||
|
def count_factors(n):
|
||||||
|
"""Return the number of positive factors that n has.
|
||||||
|
>>> count_factors(6)
|
||||||
|
4 # 1, 2, 3, 6
|
||||||
|
>>> count_factors(4)
|
||||||
|
3 # 1, 2, 4
|
||||||
|
"""
|
||||||
|
i, count = 1, 0
|
||||||
|
while i <= n:
|
||||||
|
if n % i == 0:
|
||||||
|
count += 1
|
||||||
|
i += 1
|
||||||
|
return count
|
||||||
|
|
||||||
|
def count_primes(n):
|
||||||
|
"""Return the number of prime numbers up to and including n.
|
||||||
|
>>> count_primes(6)
|
||||||
|
3 # 2, 3, 5
|
||||||
|
>>> count_primes(13)
|
||||||
|
6 # 2, 3, 5, 7, 11, 13
|
||||||
|
"""
|
||||||
|
i, count = 1, 0
|
||||||
|
while i <= n:
|
||||||
|
if is_prime(i):
|
||||||
|
count += 1
|
||||||
|
i += 1
|
||||||
|
return count
|
||||||
|
|
||||||
|
def is_prime(n):
|
||||||
|
return count_factors(n) == 2 # only factors are 1 and n
|
||||||
|
```
|
||||||
|
|
||||||
|
你可以通过一个函数 count_cond 来接受一个含有两个参数的函数 condition(n, i)
|
||||||
|
|
||||||
|
`count_cond` 返回一个单参数函数,它在调用时 `n` 计算从 1 到 `n` 满足的所有数字 `condition`。
|
||||||
|
|
||||||
|
```python
|
||||||
|
def count_cond(condition):
|
||||||
|
"""Returns a function with one parameter N that counts all the numbers from
|
||||||
|
1 to N that satisfy the two-argument predicate function Condition, where
|
||||||
|
the first argument for Condition is N and the second argument is the
|
||||||
|
number from 1 to N.
|
||||||
|
|
||||||
|
>>> count_factors = count_cond(lambda n, i: n % i == 0)
|
||||||
|
>>> count_factors(2) # 1, 2
|
||||||
|
2
|
||||||
|
>>> count_factors(4) # 1, 2, 4
|
||||||
|
3
|
||||||
|
>>> count_factors(12) # 1, 2, 3, 4, 6, 12
|
||||||
|
6
|
||||||
|
|
||||||
|
>>> is_prime = lambda n, i: count_factors(i) == 2
|
||||||
|
>>> count_primes = count_cond(is_prime)
|
||||||
|
>>> count_primes(2) # 2
|
||||||
|
1
|
||||||
|
>>> count_primes(3) # 2, 3
|
||||||
|
2
|
||||||
|
>>> count_primes(4) # 2, 3
|
||||||
|
2
|
||||||
|
>>> count_primes(5) # 2, 3, 5
|
||||||
|
3
|
||||||
|
>>> count_primes(20) # 2, 3, 5, 7, 11, 13, 17, 19
|
||||||
|
8
|
||||||
|
"""
|
||||||
|
"*** YOUR CODE HERE ***"
|
||||||
|
```
|
||||||
240
3.编程思维体系构建/3.6.4.5阶段五:迭代生成.md
Normal file
@@ -0,0 +1,240 @@
|
|||||||
|
# 阶段五:迭代生成
|
||||||
|
|
||||||
|
# 前言
|
||||||
|
|
||||||
|
在写乘法表的时候,你可能写过类似
|
||||||
|
|
||||||
|
```python
|
||||||
|
for i in [2, 3, 5, 7, 11, 13]: print(i)
|
||||||
|
```
|
||||||
|
|
||||||
|
这样的语句。for in 语句理解起来很直观形象,比起 C++ 和 java 早期的
|
||||||
|
|
||||||
|
```c
|
||||||
|
for (int i = 0; i < n; i ++)
|
||||||
|
```
|
||||||
|
|
||||||
|
这样的语句,不知道简洁清晰到哪里去了。
|
||||||
|
|
||||||
|
但是,你想过 Python 在处理 for in 语句的时候,具体发生了什么吗?什么样的对象可以被 for in 来枚举呢?
|
||||||
|
|
||||||
|
# 容器迭代
|
||||||
|
|
||||||
|
容器这个概念非常好理解。
|
||||||
|
|
||||||
|
在 Python 中一切皆对象,对象的抽象就是类,而对象的集合就是容器。
|
||||||
|
|
||||||
|
列表(list: [0, 1, 2]),元组(tuple: (0, 1, 2)),字典(dict: {0:0, 1:1, 2:2}),集合(set: set([0, 1, 2]))都是容器。
|
||||||
|
|
||||||
|
对于容器,你可以很直观地想象成多个元素在一起的单元;而不同容器的区别,正是在于内部数据结构的实现方法。
|
||||||
|
|
||||||
|
然后,你就可以针对不同场景,选择不同时间和空间复杂度的容器。所有的容器都是可迭代的(iterable)。
|
||||||
|
|
||||||
|
```python
|
||||||
|
iterator = iter(iterable)
|
||||||
|
while True:
|
||||||
|
elem = next(iterator)
|
||||||
|
# do something
|
||||||
|
```
|
||||||
|
|
||||||
|
- 首先,在可迭代对象上调用内置 `iter` 函数以创建对应的<em>迭代器</em>。
|
||||||
|
- 要获取序列中的下一个元素,在此迭代器上调用内置 `next` 函数。
|
||||||
|
|
||||||
|
如果没有下一个元素了,怎么办?
|
||||||
|
|
||||||
|
我们需要对这种异常进行处理。
|
||||||
|
|
||||||
|
思考题:什么是异常处理,为什么要进行异常处理?有什么好处?
|
||||||
|
|
||||||
|
多次调用 `iter` 可迭代对象每次都会返回一个具有不同状态的新迭代器
|
||||||
|
|
||||||
|
你也可以调用 `iter` 迭代器本身,它只会返回相同的迭代器而不改变它的状态。但是,请注意,您不能直接在可迭代对象上调用 next。
|
||||||
|
|
||||||
|
```python
|
||||||
|
>>> lst = [1, 2, 3, 4]
|
||||||
|
>>> next(lst) # Calling next on an iterable
|
||||||
|
TypeError: 'list' object is not an iterator
|
||||||
|
>>> list_iter = iter(lst) # Creates an iterator for the list
|
||||||
|
>>> list_iter
|
||||||
|
<list_iterator object ...>
|
||||||
|
>>> next(list_iter) # Calling next on an iterator
|
||||||
|
1
|
||||||
|
>>> next(list_iter) # Calling next on the same iterator
|
||||||
|
2
|
||||||
|
>>> next(iter(list_iter)) # Calling iter on an iterator returns itself
|
||||||
|
3
|
||||||
|
>>> list_iter2 = iter(lst)
|
||||||
|
>>> next(list_iter2) # Second iterator has new state
|
||||||
|
1
|
||||||
|
>>> next(list_iter) # First iterator is unaffected by second iterator
|
||||||
|
4
|
||||||
|
>>> next(list_iter) # No elements left!
|
||||||
|
StopIteration
|
||||||
|
>>> lst # Original iterable is unaffected
|
||||||
|
[1, 2, 3, 4]
|
||||||
|
```
|
||||||
|
|
||||||
|
# 英语练习,对迭代器的类比
|
||||||
|
|
||||||
|
<strong>Analogy</strong>: An iterable is like a book (one can flip through the pages) and an iterator for a book would be a bookmark (saves the position and can locate the next page). Calling `iter` on a book gives you a new bookmark independent of other bookmarks, but calling `iter` on a bookmark gives you the bookmark itself, without changing its position at all. Calling `next` on the bookmark moves it to the next page, but does not change the pages in the book. Calling `next` on the book wouldn't make sense semantically. We can also have multiple bookmarks, all independent of each other.
|
||||||
|
|
||||||
|
# 生成器:懒人迭代器!
|
||||||
|
|
||||||
|
```python
|
||||||
|
def test_iterator():
|
||||||
|
show_memory_info('initing iterator')
|
||||||
|
list_1 = [i for i in range(100000000)]
|
||||||
|
show_memory_info('after iterator initiated')
|
||||||
|
print(sum(list_1))
|
||||||
|
show_memory_info('after sum called')
|
||||||
|
|
||||||
|
def test_generator():
|
||||||
|
show_memory_info('initing generator')
|
||||||
|
list_2 = (i for i in range(100000000))
|
||||||
|
show_memory_info('after generator initiated')
|
||||||
|
print(sum(list_2))
|
||||||
|
show_memory_info('after sum called')
|
||||||
|
|
||||||
|
%time test_iterator()
|
||||||
|
%time test_generator()
|
||||||
|
|
||||||
|
########## 输出 ##########
|
||||||
|
|
||||||
|
initing iterator memory used: 48.9765625 MB
|
||||||
|
after iterator initiated memory used: 3920.30078125 MB
|
||||||
|
4999999950000000
|
||||||
|
after sum called memory used: 3920.3046875 MB
|
||||||
|
Wall time: 17 s
|
||||||
|
initing generator memory used: 50.359375 MB
|
||||||
|
after generator initiated memory used: 50.359375 MB
|
||||||
|
4999999950000000
|
||||||
|
after sum called memory used: 50.109375 MB
|
||||||
|
Wall time: 12.5 s
|
||||||
|
```
|
||||||
|
|
||||||
|
声明一个迭代器很简单,[i for i in range(100000000)]就可以生成一个包含一亿元素的列表。每个元素在生成后都会保存到内存中,你通过代码可以看到,它们占用了巨量的内存,内存不够的话就会出现 OOM 错误。
|
||||||
|
|
||||||
|
了解下 yield()函数吧,他可以返回一个生成器对象,试试看懂这个
|
||||||
|
|
||||||
|
```python
|
||||||
|
>>> def gen_list(lst):
|
||||||
|
... yield from lst
|
||||||
|
...
|
||||||
|
>>> g = gen_list([1, 2, 3, 4])
|
||||||
|
>>> next(g)
|
||||||
|
1
|
||||||
|
>>> next(g)
|
||||||
|
2
|
||||||
|
>>> next(g)
|
||||||
|
3
|
||||||
|
>>> next(g)
|
||||||
|
4
|
||||||
|
>>> next(g)
|
||||||
|
StopIteration
|
||||||
|
```
|
||||||
|
|
||||||
|
# 思考题:python 会显示什么?为什么?
|
||||||
|
|
||||||
|
```python
|
||||||
|
>>> s = [1, 2, 3, 4]
|
||||||
|
>>> t = iter(s)
|
||||||
|
>>> next(s)
|
||||||
|
______
|
||||||
|
|
||||||
|
>>> next(t)
|
||||||
|
______
|
||||||
|
|
||||||
|
>>> next(t)
|
||||||
|
______
|
||||||
|
|
||||||
|
>>> iter(s)
|
||||||
|
______
|
||||||
|
|
||||||
|
>>> next(iter(s))
|
||||||
|
______
|
||||||
|
|
||||||
|
>>> next(iter(t))
|
||||||
|
______
|
||||||
|
|
||||||
|
>>> next(iter(s))
|
||||||
|
______
|
||||||
|
|
||||||
|
>>> next(iter(t))
|
||||||
|
______
|
||||||
|
|
||||||
|
>>> next(t)
|
||||||
|
______
|
||||||
|
```
|
||||||
|
|
||||||
|
```python
|
||||||
|
>>> r = range(6)
|
||||||
|
>>> r_iter = iter(r)
|
||||||
|
>>> next(r_iter)
|
||||||
|
______
|
||||||
|
|
||||||
|
>>> [x + 1 for x in r]
|
||||||
|
______
|
||||||
|
|
||||||
|
>>> [x + 1 for x in r_iter]
|
||||||
|
______
|
||||||
|
|
||||||
|
>>> next(r_iter)
|
||||||
|
______
|
||||||
|
|
||||||
|
>>> list(range(-2, 4)) # Converts an iterable into a list
|
||||||
|
______
|
||||||
|
```
|
||||||
|
|
||||||
|
# 任务
|
||||||
|
|
||||||
|
P10:实现 `count`,它接受一个迭代器 `t` 并返回该值 `x` 出现在 的第一个 n 个元素中的次数 `t`
|
||||||
|
|
||||||
|
```python
|
||||||
|
def count(t, n, x):
|
||||||
|
"""Return the number of times that x appears in the first n elements of iterator t.
|
||||||
|
|
||||||
|
>>> s = iter([10, 9, 10, 9, 9, 10, 8, 8, 8, 7])
|
||||||
|
>>> count(s, 10, 9)
|
||||||
|
3
|
||||||
|
>>> s2 = iter([10, 9, 10, 9, 9, 10, 8, 8, 8, 7])
|
||||||
|
>>> count(s2, 3, 10)
|
||||||
|
2
|
||||||
|
>>> s = iter([3, 2, 2, 2, 1, 2, 1, 4, 4, 5, 5, 5])
|
||||||
|
>>> count(s, 1, 3)
|
||||||
|
1
|
||||||
|
>>> count(s, 4, 2)
|
||||||
|
3
|
||||||
|
>>> next(s)
|
||||||
|
2
|
||||||
|
>>> s2 = iter([4, 1, 6, 6, 7, 7, 8, 8, 2, 2, 2, 5])
|
||||||
|
>>> count(s2, 6, 6)
|
||||||
|
2
|
||||||
|
"""
|
||||||
|
"*** YOUR CODE HERE ***"
|
||||||
|
```
|
||||||
|
|
||||||
|
P11:实现生成器函数 `scale(it, multiplier)`,它产生给定迭代的元素 `it`,按 `multiplier`.
|
||||||
|
|
||||||
|
同时也希望你尝试使用 `yield from` 语句编写这个函数!
|
||||||
|
|
||||||
|
```python
|
||||||
|
def scale(it, multiplier):
|
||||||
|
"""Yield elements of the iterable it scaled by a number multiplier.
|
||||||
|
|
||||||
|
>>> m = scale(iter([1, 5, 2]), 5)
|
||||||
|
>>> type(m)
|
||||||
|
<class 'generator'>
|
||||||
|
>>> list(m)
|
||||||
|
[5, 25, 10]
|
||||||
|
>>> # generators allow us to represent infinite sequences!!!
|
||||||
|
>>> def naturals():
|
||||||
|
... i = 0
|
||||||
|
... while True:
|
||||||
|
... yield i
|
||||||
|
... i += 1
|
||||||
|
>>> m = scale(naturals(), 2)
|
||||||
|
>>> [next(m) for _ in range(5)]
|
||||||
|
[0, 2, 4, 6, 8]
|
||||||
|
"""
|
||||||
|
"*** YOUR CODE HERE ***"
|
||||||
|
```
|
||||||
41
3.编程思维体系构建/3.6.4.6结语.md
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
# 结语
|
||||||
|
|
||||||
|
# 感觉学了不少内容,又感觉什么都没学?
|
||||||
|
|
||||||
|
确实,这也是学习过程中一个非常普遍存在的状态,你学了五个非常重要的 python 语言的特性,但是在你用他们真正来优化代码解决代码之前,你都无法真正的掌握他们。
|
||||||
|
|
||||||
|
那为什么要学呢?
|
||||||
|
|
||||||
|
非常核心的一点在于,你以后面对困难的问题的时候,将他不断分解,成为一个个独立的小问题的时候,你也许会想起你之前在某文档内,有一个简单的教程曾经将某种神奇的方法一笔带过,这也许会提供给你意想不到的解决问题的思路和方法。
|
||||||
|
|
||||||
|
同时,python 的核心特性就这些吗?远远不止呢,这些只是你入手其的敲门砖,我在下面会列举一些别的特性,你可以自行前去了解,也可以等到你真正遇到问题的时候去思考?
|
||||||
|
|
||||||
|
# 为什么没有突出面向对象
|
||||||
|
|
||||||
|
因为代码量实在是太少了,当你去理解面向对象的时候的伟大意义时,最好与 C 语言这种面向过程的语言进行对比,不过,如果你完成了我们的文字冒险小游戏的时候,你可能会有非常深刻的体验。
|
||||||
|
|
||||||
|
# 还有什么是我值得注意的?
|
||||||
|
|
||||||
|
这些内容值得你去学习与思考,但是碍于各种因素,我暂时没有详细介绍
|
||||||
|
|
||||||
|
- 面向对象编程
|
||||||
|
- 深浅拷贝
|
||||||
|
- 值传递
|
||||||
|
- 装饰器
|
||||||
|
- metaclass
|
||||||
|
- GIL
|
||||||
|
- 垃圾回收机制
|
||||||
|
- 协程
|
||||||
|
- 数不清的各种框架和包!!!
|
||||||
|
|
||||||
|
如果有机会,我会继续补充相关内容
|
||||||
|
|
||||||
|
值得一提的是:后面人工智能模块,我们将以 python 为主去进行编程,这对完成了所有任务的你一定是 a piece of cake!
|
||||||
|
|
||||||
|
# 一些不错的补充
|
||||||
|
|
||||||
|
[WTF for python](https://github.com/robertparley/wtfpython-cn)
|
||||||
|
|
||||||
|
[真正的 python 教程](https://realpython.com/)
|
||||||
|
|
||||||
|
[python100 天](https://github.com/jackfrued/Python-100-Days)
|
||||||
9
3.编程思维体系构建/3.6.4Python for fun.md
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
# Python for fun
|
||||||
|
|
||||||
|
值得一提的是,Python 是面向对象的编程语言,与你之前书写的 C 语言(面向过程)有非常多的不同。
|
||||||
|
|
||||||
|
我们为什么要选择要使用 Python 来首先讲解面向对象这个概念?
|
||||||
|
|
||||||
|
究竟什么是面向对象?为什么面向对象?
|
||||||
|
|
||||||
|
这值得你在书写 Python 代码中思考并尝试将其思想融会贯通到编码风格中去。
|
||||||
625
3.编程思维体系构建/3.6.5.1lab00:让我们开始吧.md
Normal file
@@ -0,0 +1,625 @@
|
|||||||
|
# lab00:让我们开始吧
|
||||||
|
|
||||||
|
# 介绍
|
||||||
|
|
||||||
|
本 lab 将介绍如何设置计算机以完成作业,并介绍 Python 的一些基础知识。
|
||||||
|
|
||||||
|
这个 lab 是必需的。这个设置对于完全课程中的所有其他作业是必要的。
|
||||||
|
|
||||||
|
这个 lab 看起来非常长,但它主要是设置和学习如何使用这个课程的基本工具。这些现在看起来有点困难,但随着我们进一步进入课程,很快就会变得熟悉起来。
|
||||||
|
|
||||||
|
以下是实验室的主要部分:
|
||||||
|
|
||||||
|
- <strong>设置</strong>:设置课程的基本软件。这将需要几个组件,如下所列。
|
||||||
|
|
||||||
|
- <strong>安装终端</strong>:安装终端,以便你可以与本课程中的文件进行交互并运行 OK 命令。如果你的计算机上有终端并且使用起来很舒服,则可以跳过这一部分。
|
||||||
|
- <strong>安装 Python 3</strong>:将 Python 编程语言安装到你的计算机上。如果你已经安装了 Python 3.7 或更高版本(最好是 Python 3.9),则可以跳过这部分。
|
||||||
|
- <strong>安装文本编辑器</strong>:安装软件来编辑 `.py` 本课程的文件(例如 VSCode、Atom 等)。如果你已经有了自己喜欢的文本编辑器,则可以跳过这一部分。
|
||||||
|
- <strong>演练:使用终端</strong>:本节将引导你完成如何使用终端和 Python 解释器。如果你已经能熟练使用这两者并感到轻松,则无需阅读本节。
|
||||||
|
- <strong>演练:组织文件</strong>:本节将指导你完成如何使用终端来组织和导航本课程的文件。<strong>每个人都应该至少浏览一下这一部分</strong>,因为它包含特定于此类的重要信息,但是如果你已经习惯使用终端浏览目录结构,那么其中的大部分内容都会很熟悉。
|
||||||
|
- <strong>复习:Python 基础知识</strong>:这是对讲座中介绍的 Python 的许多基本组件的复习。你应该已经看过此材料,但我们希望在每个 lab 中包含对相关内容的简要回顾,以备你需要复习任何内容。
|
||||||
|
- <strong>要求:完成作业</strong>:你必须完成此部分才能获得作业分数。在这里,你将练习本课程的 lab、hw 和 proj 中要求你完成的不同类型的问题。本作业的主要目的是让你练习使用我们的软件。
|
||||||
|
- <strong>要求:提交作业</strong>:你必须完成此部分才能获得作业分数。这将引导你了解如何在完成上一节后上交作业,以及如何验证你的作业是否已在 OKPY 上上交。(即使我们没有注册账户,也可以在本地运行 ok)
|
||||||
|
- <strong>附录:有用的 Python 命令行选项</strong>:这些命令对调试你的工作很有用,但不是完成本实验所必需的。我们将它们包括在内是因为我们认为它们可能会在整个课程中对你有所帮助。
|
||||||
|
|
||||||
|
## 设置
|
||||||
|
|
||||||
|
### 安装终端
|
||||||
|
|
||||||
|
终端是一个程序,允许你通过输入命令与你的计算机进行交互。
|
||||||
|
|
||||||
|
#### macOS/Linux
|
||||||
|
|
||||||
|
如果你使用的是 Mac 或正在使用某种形式的 Linux(例如 Ubuntu),则你 `Terminal` 的计算机上已经有一个名为或类似名称的程序。打开它,你应该可以开始了。
|
||||||
|
|
||||||
|
#### 视窗
|
||||||
|
|
||||||
|
<strong>选项 1 (WSL):</strong>你可以使用适用于 Linux 的 Windows 子系统或 WSL 在 Windows 上获得终端。这可以通过终端程序访问 `Ubuntu`,该程序模拟 Windows 计算机上的 Ubuntu 操作系统 (OS)。这将使我们的大部分作业在你的设备上顺利进行。
|
||||||
|
|
||||||
|
要安装适用于 Windows 的 Ubuntu,请单击开始并搜索 PowerShell。右键单击并选择“以管理员身份运行”。然后,在 PowerShell 窗口中,键入 `wsl --install` 并按 Enter。该命令必须按照准确的顺序输入。这应该会自动完成设置过程(按照屏幕上可能给出的任何说明进行操作)。
|
||||||
|
|
||||||
|
接下来, [从 Windows 商店下载 Ubuntu](https://apps.microsoft.com/store/detail/ubuntu/9PDXGNCFSCZV?hl=en-us&gl=US),或者你可以运行:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
wsl --install -d ubuntu
|
||||||
|
```
|
||||||
|
|
||||||
|
你可能还会发现访问 [Ubuntu 的下载指南](https://ubuntu.com/tutorials/install-ubuntu-on-wsl2-on-windows-10#1-overview)很有帮助。
|
||||||
|
|
||||||
|
安装完成后,在开始菜单中搜索 Ubuntu。第一次启动可能需要几分钟,但后续启动应该很快。
|
||||||
|
|
||||||
|
<strong>替代选项:</strong>如果你在安装 WSL 时遇到问题,你可以跳过此步骤并使用 Windows PowerShell 代替 61A。PowerShell 预装在 Windows 上,无需额外设置。你可以简单地从“开始”菜单启动它。`cd` 像和 这样的简单命令 `ls` 将起作用(`python` 将在设置后起作用),其中包含本课程所需的大部分 Bash 命令。
|
||||||
|
|
||||||
|
### 安装 Python 3
|
||||||
|
|
||||||
|
Python 3 是本课程中使用的主要编程语言。使用下面的说明安装 Python 3。(这些说明可能适用于旧版本的 Python 3,但步骤相似。)
|
||||||
|
|
||||||
|
<strong>重要提示:</strong>如果你已经安装了旧版本的 Python,请确保下载并安装 Python 3.9。你可以使用 来检查你的 Python 版本 `python3 ––version`。
|
||||||
|
|
||||||
|
#### macOs
|
||||||
|
|
||||||
|
下载并安装 [Python 3(64 位)](https://www.python.org/ftp/python/3.9.6/python-3.9.6-macosx10.9.pkg)。你可能需要右键单击下载图标并选择“打开”。安装后,请关闭并重新打开你的终端。
|
||||||
|
|
||||||
|
如果你安装了 Homebrew,你也可以通过运行安装 Python3 `brew install python3`。
|
||||||
|
|
||||||
|
#### Windows
|
||||||
|
|
||||||
|
<strong>如果你将使用 PowerShell 而不是 WSL,请打开 Microsoft Store 并搜索“python”。</strong>安装 Python Software Foundation 提供的 Python 3.9(这应该是第一个结果)。然后你可以跳过本节的其余部分。(重要提示:如果你以后决定以不同方式重新安装 Python,<strong>请先从 Microsoft Store 卸载它。)</strong>
|
||||||
|
|
||||||
|
否则,如果你使用的是 WSL,请在 Ubuntu 中键入 `sudo apt install python3` 并点击 `enter`. 安装完成后,你可以通过键入来测试它是否安装正确 `python3 --version`。你应该会在响应中看到一条消息,显示你的 python3 版本: `Python 3.9.6`。
|
||||||
|
|
||||||
|
#### Linux
|
||||||
|
|
||||||
|
运行 `sudo apt install python3`(Ubuntu)、`sudo pacman -S python3`(Arch) 或适用于你的发行版的命令。
|
||||||
|
|
||||||
|
#### 其他
|
||||||
|
|
||||||
|
[从下载页面下载 Python](https://www.python.org/downloads/)。
|
||||||
|
|
||||||
|
### 安装文本编辑器
|
||||||
|
|
||||||
|
<strong>你刚刚安装的 Python 解释器</strong>允许你<em>运行</em>Python 代码。你还需要一个<strong>文本编辑器</strong>,你将在其中<em>编写</em>Python 代码。
|
||||||
|
|
||||||
|
[Visual Studio Code (VS Code)](https://code.visualstudio.com/)是这门课程编写 Python 的最流行的选择。下面还列出了员工使用的其他一些编辑器。
|
||||||
|
|
||||||
|
<strong>如果你使用的是 Windows</strong>并遵循我们的 Python 设置过程,VS Code 将最适合你(因为它具有 WSL 支持)。安装 VS Code 后,安装 [Remote Development 扩展包](https://aka.ms/vscode-remote/download/extension)。[然后,你可以使用 VS Code 文档这一部分](https://code.visualstudio.com/docs/remote/wsl#_open-a-remote-folder-or-workspace)中的说明在 VS Code 中打开 WSL 文件夹。
|
||||||
|
|
||||||
|
<strong>我们强烈建议在本课程中使用 VS Code。</strong>这将帮助我们为你提供最好的支持,因为大多数员工也使用 VS Code。
|
||||||
|
|
||||||
|
VS Code 的另一个不错的功能是它具有“嵌入式终端”。因此,在为此类运行终端命令时,你可以在 VS Code 中管理所有内容,而不是在 VS Code 和单独的终端应用程序之间来回导航。`Terminal > New Terminal` 你可以通过转到 VS Code 的导航栏中打开嵌入式终端 。
|
||||||
|
|
||||||
|
> 警告:请不要使用 Microsoft Word 等文字处理器来编辑程序。文字处理器可以向文档添加额外的内容,这会使解释器感到困惑。
|
||||||
|
|
||||||
|
为了你的参考,我们还编写了一些使用流行的文本编辑器的指南。完成实验室后,如果你有兴趣,可以看看:
|
||||||
|
|
||||||
|
- [Visual Studio Code](https://inst.eecs.berkeley.edu/~cs61a/fa22/articles/vscode):一个功能齐全的桌面编辑器,具有许多可用于支持不同语言的扩展。
|
||||||
|
- [Atom](https://inst.eecs.berkeley.edu/~cs61a/fa22/articles/atom):一个更轻量级的桌面编辑器。
|
||||||
|
- [Vim](https://inst.eecs.berkeley.edu/~cs61a/fa22/articles/vim):命令行编辑器。
|
||||||
|
- [Emacs](https://inst.eecs.berkeley.edu/~cs61a/fa22/articles/emacs):命令行编辑器。
|
||||||
|
|
||||||
|
其他编译器:
|
||||||
|
|
||||||
|
- [PyCharm](https://www.jetbrains.com/pycharm/):专为 Python 设计的桌面编辑器。
|
||||||
|
- [Sublime Text](https://www.sublimetext.com/):一个使用代码的文本编辑器。
|
||||||
|
|
||||||
|
### 结对编程
|
||||||
|
|
||||||
|
在整个课程中,你将有很多机会在实验室和项目中与其他人协作编码。我们建议你现在下载这些结对编程扩展以备将来使用。
|
||||||
|
|
||||||
|
要共享代码,你可以按照你选择的编辑器的说明进行操作:
|
||||||
|
|
||||||
|
- [VS Code](https://inst.eecs.berkeley.edu/~cs61a/fa22/articles/vscode#pair-programming)
|
||||||
|
- [Atom](https://inst.eecs.berkeley.edu/~cs61a/fa22/articles/atom#pair-programming)
|
||||||
|
|
||||||
|
### 备份设置
|
||||||
|
|
||||||
|
如你你在安装 Python 解释器、文本编辑器和终端时遇到问题,或者如果你使用的东西不允许你安装软件,比如 iPad,你可以作为临时措施使用以下一些来完成作业在你获得更合适的硬件时执行的步骤。
|
||||||
|
|
||||||
|
#### Soda 实验室计算机
|
||||||
|
|
||||||
|
你将需要一个指导帐户,该帐户允许你登录并使用 Soda 中的任何实验室计算机。你可以访问以下网址查看你现有的教学帐户并为适用的课程创建新的教学帐户:https: [//inst.eecs.berkeley.edu/connecting.html](https://inst.eecs.berkeley.edu/connecting.html)。
|
||||||
|
|
||||||
|
你可以通过你的 CalNet ID 登录该站点。要创建本课程的教学帐户,请单击以“cs61a”为目的的行的“获取新帐户”。
|
||||||
|
|
||||||
|
创建帐户后,你可以使用它登录 Soda 实验室计算机,并使用该计算机完成课程作业。
|
||||||
|
|
||||||
|
#### 在线编辑器作为备份
|
||||||
|
|
||||||
|
> 重要提示: 下面列出的两种替代方法都不适合在本课程中使用。我们建议能够使用您自己的本地设置或使用 Soda 中的实验室计算机(您可以使用您的课程教学帐户访问)。
|
||||||
|
|
||||||
|
<strong>61A 代码:</strong>
|
||||||
|
|
||||||
|
您可以使用 [61A 代码](https://code.cs61a.org/),这是一个在线课程环境,您可以在其中编辑、运行、调试、可视化程序并与教职员工共享程序。可在此处找到 61A 代码的文档: [61A 代码文档](https://cs61a.org/articles/61a-code-docs/)。
|
||||||
|
|
||||||
|
> 注意: 您将无法 `ok` 在 61A 代码中运行命令,解锁测试、运行测试和提交作业需要执行这些命令。
|
||||||
|
|
||||||
|
在 61A Code 上完成此作业的步骤:
|
||||||
|
|
||||||
|
1. 访问 [61A 代码](https://code.cs61a.org/)。
|
||||||
|
2. 打开现有文件:进入您的 `cs61a` 文件夹,然后是作业文件夹 ( `lab00`),您可以在其中找到该作业的文件。
|
||||||
|
3. 系统将提示您授权编辑器。您可以点击“确认”。回到编辑器本身,然后您可以打开要编辑的文件。
|
||||||
|
4. 要打开终端,请单击“控制台”。
|
||||||
|
5. 您可以使用编辑器编写代码,使用控制台运行代码。
|
||||||
|
|
||||||
|
<strong>数据中心:</strong>
|
||||||
|
|
||||||
|
在本地工作的另一种选择是使用加州大学伯克利分校的 Datahub。
|
||||||
|
|
||||||
|
在 Datahub 上完成作业的步骤:
|
||||||
|
|
||||||
|
1. 访问[数据中心](https://datahub.berkeley.edu/)。
|
||||||
|
2. 将作业 zip 文件上传到数据中心。
|
||||||
|
3. 通过按左上角的“新建”并选择终端来打开终端。
|
||||||
|
4. 导航到 zip 文件所在的位置并运行 `unzip lab00.zip`。
|
||||||
|
5. 打开代码文件 ( `lab00.py`) 并在其中键入,然后保存。
|
||||||
|
6. 现在您可以提交实验。
|
||||||
|
|
||||||
|
## 演练:使用终端
|
||||||
|
|
||||||
|
首先,打开一个终端窗口。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
#### 主目录
|
||||||
|
|
||||||
|
当您第一次打开终端时,您将从“主目录”开始。主<strong>目录</strong>由 `~` 符号表示,您可能会在提示符处看到它。
|
||||||
|
|
||||||
|
> 如果您的终端窗口看起来不完全相同,请不要担心。重要的部分是提示符显示 `$`(表示 Bash)或 `%` (表示 zsh)。
|
||||||
|
|
||||||
|
尝试跑步 `echo "$HOME"`。该命令应显示您的主目录的完整路径。它应该看起来像这样:
|
||||||
|
|
||||||
|
`/Users/OskiBear`
|
||||||
|
|
||||||
|
#### 小路
|
||||||
|
|
||||||
|
PATH 就像一个地址:它告诉您和计算机到某个文件夹的完整路径(或路由)。请记住,您可以通过两种不同的方式访问计算机上的文件和目录(文件夹)。您可以使用终端(这是一个<strong>命令行</strong>界面或 CLI),也可以使用 Finder <strong>。</strong>Finder 是<strong>图形</strong>用户<strong>界面</strong>(或 GUI)的一个 例子<strong>。</strong>导航技术不同,但文件相同。例如,这是我的 CS 61A 实验室文件夹在我的 GUI 中的样子:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
这是完全相同的文件夹在终端中的外观:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
请注意,在这两种情况下,黄色框都显示了 PATH,紫色椭圆显示了“labs”文件夹的内容。
|
||||||
|
|
||||||
|
#### 终端与 Python 解释器
|
||||||
|
|
||||||
|
让我们停下来思考一下终端和 Python 解释器之间的区别。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
1. 哪个是终端?
|
||||||
|
2. 哪个是 Python 解释器?
|
||||||
|
3. 哪个是我的代码编辑器?
|
||||||
|
4. 你怎么知道?
|
||||||
|
|
||||||
|
A 和 D 都是我的终端。在这里您可以运行 bash 命令,例如 `cd` 和 `ls`。D 是 VS Code 内置的终端。
|
||||||
|
|
||||||
|
B 是 Python 解释器。你可以从 >>> 提示中看出这意味着你已经启动了一个 Python 解释器。您还可以判断,因为启动它的命令是可见的:`python3`。该 `python3` 命令启动 Python 解释器。如果您在 Python 解释器中键入 bash 命令,您可能会遇到语法错误!这是一个例子:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
C 是我的代码编辑器。这是我可以编写 Python 代码以通过我的终端执行的地方。
|
||||||
|
|
||||||
|
## 演练:组织文件
|
||||||
|
|
||||||
|
在本节中,您将学习如何使用终端命令管理文件。
|
||||||
|
|
||||||
|
> 确保您的提示包含 `$` 其中的某处并且不以 `>>>`. 如果它以 `>>>` 您仍在 Python shell 中开头,您需要退出。见上文了解如何。
|
||||||
|
|
||||||
|
### 目录
|
||||||
|
|
||||||
|
您将使用的第一个命令是 `ls`. 尝试在您的终端中输入:
|
||||||
|
|
||||||
|
```
|
||||||
|
ls
|
||||||
|
```
|
||||||
|
|
||||||
|
该 `ls` 命令<strong>列出</strong>了当前目录中<strong>的</strong>所有文件和文件夹。目录是文件夹(如文件夹)的另一个 <strong>名称</strong>`Documents`。
|
||||||
|
|
||||||
|
#### macOS/Linux
|
||||||
|
|
||||||
|
由于您现在位于主目录中,因此在您键入后 `ls` 您应该会看到主目录的内容。
|
||||||
|
|
||||||
|
#### 视窗
|
||||||
|
|
||||||
|
`~` 在 Ubuntu 中,当您键入 时,您将看不到任何文件 `ls`。相反,您首先需要更改目录(见下文)。
|
||||||
|
|
||||||
|
### 更改目录
|
||||||
|
|
||||||
|
要移动到另一个目录,请使用 `cd` 命令 ( <strong>c</strong> hange <strong>directory</strong> )。
|
||||||
|
|
||||||
|
#### macOS/Linux
|
||||||
|
|
||||||
|
让我们尝试进入您的 `Desktop` 目录。首先,确保您位于主目录中(检查 `~` 命令行中的 )并使用 `ls` 查看该 `Desktop` 目录是否存在。
|
||||||
|
|
||||||
|
尝试在您的终端中键入以下命令,这应该会将您移至该目录:
|
||||||
|
|
||||||
|
```
|
||||||
|
cd Desktop
|
||||||
|
```
|
||||||
|
|
||||||
|
如果您<em>不在</em>您的主目录中,请尝试 `cd ~/Desktop`. 这是告诉终端你想去的路径。
|
||||||
|
|
||||||
|
#### Windows
|
||||||
|
|
||||||
|
在 Windows 上,首先切换到您的主目录。
|
||||||
|
|
||||||
|
```
|
||||||
|
cd /mnt/c/Users/
|
||||||
|
```
|
||||||
|
|
||||||
|
现在尝试 `ls` 之前的命令。您应该会看到一些文件夹。其中一个文件夹应与您的用户名匹配。例如,假设您的用户名是 `OskiBear`,您应该会看到一个名为 的文件夹 `OskiBear`。(请注意,您的 Windows 用户名可能与您的 Ubuntu 用户名不同)让我们切换到该文件夹:
|
||||||
|
|
||||||
|
```
|
||||||
|
cd /mnt/c/Users/OskiBear/Desktop
|
||||||
|
```
|
||||||
|
|
||||||
|
如果仍然找不到桌面目录,请在 Piazza 或办公时间寻求帮助。
|
||||||
|
|
||||||
|
### 制作新目录
|
||||||
|
|
||||||
|
下一个命令称为 `mkdir`,<strong>它</strong>创建<strong>一个</strong>新 <strong>目录</strong>。让我们在您的目录中创建一个名为的目录来存储此类的所有作业:`cs61aDesktop`
|
||||||
|
|
||||||
|
```
|
||||||
|
mkdir cs61a
|
||||||
|
```
|
||||||
|
|
||||||
|
名为的文件夹 `cs61a` 将出现在您的桌面上。`ls` 您可以通过再次使用该命令或使用资源管理器 (Windows) 或 Finder (Mac) 检查您的桌面来验证这一点。
|
||||||
|
|
||||||
|
在这一点上,让我们创建更多的目录。首先,确保您位于 `cs61a` 目录中(mac: `~/Desktop/cs61a`, Windows: `/mnt/c/Users/Desktop/cs61a`)。然后,创建两个新文件夹,一个名为 `projects`,另一个名为 `lab`. 两者都应该在您的 `cs61a` 文件夹中:
|
||||||
|
|
||||||
|
#### macOS/Linux
|
||||||
|
|
||||||
|
```
|
||||||
|
cd ~/Desktop/cs61a
|
||||||
|
mkdir projects
|
||||||
|
mkdir lab
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Windows
|
||||||
|
|
||||||
|
```
|
||||||
|
cd /mnt/c/Users/OskiBear/Desktop/cs61a
|
||||||
|
mkdir projects
|
||||||
|
mkdir lab
|
||||||
|
```
|
||||||
|
|
||||||
|
现在,如果您列出目录的内容(使用 `ls`),您将看到两个文件夹,`projects` 和 `lab`.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### 更多目录更改
|
||||||
|
|
||||||
|
有几种方法可以返回主目录:
|
||||||
|
|
||||||
|
- `cd ..`(两个点)。意思 `..` 是“父目录”,或当前目录之上的一个目录。
|
||||||
|
- `cd ~`(代字号)。请记住,这 `~` 意味着主目录,因此此命令将始终更改为您的主目录。
|
||||||
|
- `cd`(只有 `cd`)。只输入 `cd` 是输入 `cd ~` 的捷径。
|
||||||
|
|
||||||
|
> 如果您愿意,您不必将文件保留在桌面上。您将文件保存在本地的位置不会影响您的成绩。做对您来说最简单、最方便的事情!
|
||||||
|
|
||||||
|
### 下载作业
|
||||||
|
|
||||||
|
如果您还没有,请下载 zip 存档 [lab00.zip](https://inst.eecs.berkeley.edu/~cs61a/fa22/lab/lab00/lab00.zip),其中包含本 lab 所需的所有文件。完成后,让我们找到下载的文件。在大多数计算机上,`lab00.zip` 它可能位于一个名为 `Downloads` 您的主目录的目录中。使用 `ls` 命令检查:
|
||||||
|
|
||||||
|
```
|
||||||
|
ls ~/Downloads
|
||||||
|
```
|
||||||
|
|
||||||
|
如果您没有看到 `lab00.zip`,请在 Piazza 或办公时间寻求帮助。在某些版本的 Safari 上,文件可能会为您解压缩,在这种情况下,您只会看到一个名为 `lab00`.
|
||||||
|
|
||||||
|
### 提取启动文件
|
||||||
|
|
||||||
|
您必须先展开 zip 存档,然后才能处理实验室文件。不同的操作系统和不同的浏览器有不同的解压方式。在 Mac 中单击 .zip 文件将自动解压缩。在 Windows 上,您需要先单击 .zip 文件,然后选择“全部解压”。如果遇到麻烦,可以在线搜索如何解压缩文件。
|
||||||
|
|
||||||
|
这是使用终端解压缩的一种方法:
|
||||||
|
|
||||||
|
> 使用终端,您可以从命令行解压缩 zip 文件。首先,`cd` 进入包含 zip 文件的目录:<br/>``<br/>cd ~/Downloads<br/>`` 现在,`unzip` 使用 zip 文件的名称运行命令:<br/>``<br/>unzip lab00.zip<br/>``
|
||||||
|
|
||||||
|
您只需要解压缩文件一次。
|
||||||
|
|
||||||
|
解压缩后 `lab00.zip`,您将拥有一个名为的新文件夹 `lab00`,其中包含以下文件(使用 `cd lab00` 和检查 `ls`):
|
||||||
|
|
||||||
|
- `lab00.py`:您要将代码添加到的模板文件
|
||||||
|
- `ok`: 用于测试和提交作业的程序
|
||||||
|
- `lab00.ok`: 配置文件 `ok`
|
||||||
|
|
||||||
|
### 移动文件
|
||||||
|
|
||||||
|
将实验室文件移动到您之前创建的实验室文件夹中:
|
||||||
|
|
||||||
|
<strong>macOS/Linux</strong>
|
||||||
|
|
||||||
|
```
|
||||||
|
mv ~/Downloads/lab00 ~/Desktop/cs61a/lab
|
||||||
|
```
|
||||||
|
|
||||||
|
Windows
|
||||||
|
|
||||||
|
```
|
||||||
|
mv /mnt/c/Users/Desktop/lab00 /mnt/c/Users/Desktop/cs61a/lab
|
||||||
|
```
|
||||||
|
|
||||||
|
该 `mv` 命令会将文件夹移动到<strong>文件</strong>夹<strong>中</strong>。如果您愿意,还可以通过将文件拖放到图形文件资源管理器中的正确文件夹中来移动文件,这可能更常见,并且会产生完全相同的结果。`~/Downloads/lab00~/Desktop/cs61a/lab`
|
||||||
|
|
||||||
|
现在,转到 `lab00` 您刚刚移动的文件夹。尝试使用 `cd` 自己的方式导航!如果卡住了,可以使用以下命令:
|
||||||
|
|
||||||
|
<strong>macOS/Linux</strong>
|
||||||
|
|
||||||
|
```
|
||||||
|
cd ~/Desktop/cs61a/lab/lab00
|
||||||
|
```
|
||||||
|
|
||||||
|
Windows
|
||||||
|
|
||||||
|
```
|
||||||
|
cd /mnt/c/Users/Desktop/cs61a/lab/lab00
|
||||||
|
```
|
||||||
|
|
||||||
|
### 概括
|
||||||
|
|
||||||
|
以下是我们刚刚完成的命令摘要,供您参考:
|
||||||
|
|
||||||
|
- `ls`: 列出当前目录下的所有文件
|
||||||
|
- `cd <path to directory>`: 改变进入指定目录
|
||||||
|
- `mkdir <directory name>`: 使用给定名称创建一个新目录
|
||||||
|
- `mv <source path> <destination path>`: 将给定地址的文件移动到给定的目录
|
||||||
|
|
||||||
|
最后,您可以开始编辑实验室文件了!如果这看起来很复杂,请不要担心——随着时间的推移,它会变得容易得多。只要继续练习!您还可以查看我们的 [UNIX 教程](https://inst.eecs.berkeley.edu/~cs61a/fa22/articles/unix),了解有关终端命令的更详细说明。
|
||||||
|
|
||||||
|
## 回顾:Python 基础知识
|
||||||
|
|
||||||
|
程序由表达式和语句组成。表达式是一段计算出某个值的代码,而<em>语句是使程序</em>中发生某事的一行或多行代码。
|
||||||
|
|
||||||
|
当您将 Python 表达式输入交互式 Python 解释器时,将显示其值。当您阅读以下示例时,请在您自己的 Python 解释器上尝试一些类似的表达式,您可以通过在终端中输入以下内容来启动它:
|
||||||
|
|
||||||
|
```
|
||||||
|
python3
|
||||||
|
```
|
||||||
|
|
||||||
|
您将在本课程中学习各种类型的表达式和语句。现在,让我们看一下完成本实验所需的内容。
|
||||||
|
|
||||||
|
#### 原始表达式
|
||||||
|
|
||||||
|
原始表达式只需要一步来计算。这些包括数字和布尔值,它们只是对自己求值。
|
||||||
|
|
||||||
|
```python
|
||||||
|
>>> 3
|
||||||
|
3
|
||||||
|
>>> 12.5
|
||||||
|
12.5
|
||||||
|
>>> True
|
||||||
|
True
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 算术表达式
|
||||||
|
|
||||||
|
数字可以与数学运算符组合以形成复合表达式。除了 `+` 运算符(加法)、`-` 运算符(减法)、`*` 运算符(乘法)和 `**` 运算符(求幂)之外,还有三个类似除法的运算符需要记住:
|
||||||
|
|
||||||
|
- 浮点数除法 ( `/`):将第一个数字除以第二个数字,计算结果为带小数点的数字,<em>即使数字被整除也是如此</em>。
|
||||||
|
- 整除 ( `//`):用第一个数字除以第二个数字,然后向下舍入,计算结果为整数。
|
||||||
|
- 模 ( `%`):计算除法剩余的正余数。
|
||||||
|
|
||||||
|
括号可用于将子表达式组合在一起;整个表达式按 PEMDAS(括号、求幂、乘法/除法、加法/减法)顺序求值。
|
||||||
|
|
||||||
|
```python
|
||||||
|
>>> 7 / 4
|
||||||
|
1.75
|
||||||
|
>>> (2 + 6) / 4
|
||||||
|
2.0
|
||||||
|
>>> 7 // 4 # Floor division (rounding down)
|
||||||
|
1
|
||||||
|
>>> 7 % 4 # Modulus (remainder of 7 // 4)
|
||||||
|
3
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 字符串
|
||||||
|
|
||||||
|
字符串由用单引号 ( `''`) 或双引号 ( `""`) 包裹的一个或多个字符组成。字符串实际上与原始表达式略有不同,但出于此赋值的目的,可以将其视为对自身求值的表达式。在接下来的几周中,您将在本课程中了解更多关于字符串的复杂性!
|
||||||
|
|
||||||
|
```python
|
||||||
|
>>> "hello" # Both single and double quotes work!'hello'>>> 'world!''world'
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 赋值语句
|
||||||
|
|
||||||
|
赋值语句由名称和表达式组成。它通过计算符号右侧的表达式 `=` 并将其值<em>绑定</em>到左侧的名称来更改程序的状态。
|
||||||
|
|
||||||
|
```python
|
||||||
|
>>> a = (100 + 50) // 2
|
||||||
|
```
|
||||||
|
|
||||||
|
现在,如果我们计算 `a`,解释器将显示值 75。
|
||||||
|
|
||||||
|
```python
|
||||||
|
>>> a
|
||||||
|
75
|
||||||
|
```
|
||||||
|
|
||||||
|
## 要求:完成作业
|
||||||
|
|
||||||
|
> 在处理作业时,请确保您终端的工作目录是正确的(这个目录可能是您解压缩作业的位置)。
|
||||||
|
|
||||||
|
### Python 会做什么?(WWPD)
|
||||||
|
|
||||||
|
实验室作业的一个组成部分是预测 Python 解释器的行为方式。
|
||||||
|
|
||||||
|
> 在您的终端中输入以下内容以开始此部分:<br/>``<br/>python3 ok -q python-basics -u<br/>`` 系统将提示您输入各种语句/表达式的输出。您必须正确输入它们才能继续,但错误答案不会受到惩罚。<br/>第一次运行 Ok 时,系统将提示您输入 bCourses 电子邮件。请遵循[这些指示](https://inst.eecs.berkeley.edu/~cs61a/fa22/articles/using-ok/#signing-in-with-ok)。我们在评分时使用此信息将您的代码与您相关联。
|
||||||
|
|
||||||
|
```python
|
||||||
|
>>> 10 + 2
|
||||||
|
______
|
||||||
|
>>> 7 / 2
|
||||||
|
______
|
||||||
|
>>> 7 // 2
|
||||||
|
______
|
||||||
|
>>> 7 % 2 # 7 modulo 2, the remainder when dividing 7 by 2.
|
||||||
|
______
|
||||||
|
```
|
||||||
|
|
||||||
|
```python
|
||||||
|
>>> x = 20>>> x + 2
|
||||||
|
______
|
||||||
|
>>> x
|
||||||
|
______
|
||||||
|
>>> y = 5>>> y = y + 3>>> y * 2
|
||||||
|
______
|
||||||
|
>>> y = y // 4>>> y + x
|
||||||
|
______
|
||||||
|
```
|
||||||
|
|
||||||
|
### 代码编写题
|
||||||
|
|
||||||
|
#### 理解问题
|
||||||
|
|
||||||
|
实验室还将包括函数编写问题。在你的文本编辑器中打开 `lab00.py`。您可以 `open .` 在 MacOS 或 `start .` Windows 上键入以在 Finder/文件资源管理器中打开当前目录。然后双击或右键单击以在文本编辑器中打开文件。你应该看到这样的东西:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
三引号中的行 `"""` 称为<strong>文档字符串(Docstring)</strong>,它描述了函数应该做什么。在 61A 中编写代码时,您应该始终阅读文档字符串!
|
||||||
|
|
||||||
|
开头的行 `>>>` 称为<strong>文档测试模块(Doctest)</strong>。回想一下,当使用 Python 解释器时,您在旁边编写 Python 表达式 `>>>`,输出打印在该行下方。文档测试模块通过显示实际的 Python 代码来解释函数的作用。它回答了这个问题:“如果我们输入这段 Python 代码,预期的输出应该是什么?”
|
||||||
|
|
||||||
|
在这里,我们圈出了文档字符串和文档测试,以便于查看:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
在 `twenty_twenty_two`,
|
||||||
|
|
||||||
|
- 文档字符串告诉你“想出最有创意的表达式,计算到 2022 年”,但你只能使用数字和算术运算符 `+`(add)、`*`(multiply) 和 `-`(subtract)。
|
||||||
|
- doctest 检查函数调用 `twenty_twenty_two()` 是否应返回数字 2022。
|
||||||
|
|
||||||
|
> 你不应该修改文档字符串,除非你想添加你自己的测试!除非另有说明,否则您需要编辑的唯一部分是代码。
|
||||||
|
|
||||||
|
#### 编写代码
|
||||||
|
|
||||||
|
了解问题的含义后,您就可以开始编写代码了!您应该将中的下划线替换 `return ______` 为计算结果为 2022 的表达式。您能想出的最有创意的表达式是什么?
|
||||||
|
|
||||||
|
> 编辑后不要忘记保存您的作业!在大多数文本编辑器中,您可以通过导航到“文件”>“保存”或在 MacOS 上按 Command-S 或在 Windows 上按 Ctrl-S 来保存。
|
||||||
|
|
||||||
|
### 运行测试
|
||||||
|
|
||||||
|
在 CS 61A 中,我们将使用一个名为 的程序 `ok` 来测试我们的代码。`ok` 将包含在本课程的每项作业中。
|
||||||
|
|
||||||
|
> 为了快速生成 ok 命令,您现在可以使用 [ok 命令生成器](https://go.cs61a.org/ok-help)。
|
||||||
|
|
||||||
|
返回终端——确保您位于 `lab00` 我们之前创建的目录中(请记住,该 `cd` 命令允许您[更改目录](https://inst.eecs.berkeley.edu/~cs61a/fa22/lab/lab00/#changing-directories))。
|
||||||
|
|
||||||
|
在该目录中,您可以键入 `ls` 以验证是否存在以下三个文件:
|
||||||
|
|
||||||
|
- `lab00.py`:您刚刚编辑的起始文件
|
||||||
|
- `ok`: 我们的测试程序
|
||||||
|
- `lab00.ok`: Ok 的配置文件
|
||||||
|
|
||||||
|
现在,让我们测试我们的代码以确保它能正常工作。您可以 `ok` 使用此命令运行:
|
||||||
|
|
||||||
|
```
|
||||||
|
python3 ok
|
||||||
|
```
|
||||||
|
|
||||||
|
> 请记住,如果您使用的是 Windows 而该 `python3` 命令不起作用,请尝试仅使用 `python` 或 `py`。有关详细信息,请参阅[安装 Python 3](https://inst.eecs.berkeley.edu/~cs61a/fa22/lab/lab00/#install-python-3) 部分,如果遇到困难,请寻求帮助!
|
||||||
|
|
||||||
|
如果您正确编写了代码并完成了测试解锁,您应该会看到一个成功的测试:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
=====================================================================
|
||||||
|
Assignment: Lab 0
|
||||||
|
Ok, version v1.18.1
|
||||||
|
=====================================================================
|
||||||
|
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
Running tests
|
||||||
|
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
Test summary
|
||||||
|
3 test cases passed! No cases failed.
|
||||||
|
```
|
||||||
|
|
||||||
|
如果您没有通过测试,`ok` 则会向您显示如下内容:
|
||||||
|
|
||||||
|
```python
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
Doctests for twenty_twenty_two
|
||||||
|
|
||||||
|
>>> from lab00 import *
|
||||||
|
>>> twenty_twenty_two()
|
||||||
|
2013
|
||||||
|
|
||||||
|
# Error: expected
|
||||||
|
# 2022
|
||||||
|
# but got
|
||||||
|
# 2013
|
||||||
|
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
Test summary
|
||||||
|
0 test cases passed before encountering first failed test case
|
||||||
|
```
|
||||||
|
|
||||||
|
在您的文本编辑器中修复您的代码,直到测试通过。
|
||||||
|
|
||||||
|
> 每次运行 Ok 时,Ok 都会尝试备份您的工作。如果它说“连接超时”,请不要担心。我们不会使用您的备份进行评分。<br/>虽然是 CS 61A 中的主要作业“autograder”,但有时您可能会发现以[文档测试模块](https://inst.eecs.berkeley.edu/~cs61a/fa22/lab/lab00/#understanding-problems)的形式编写一些您自己的测试很有用。然后,您可以使用 `-m doctest` 命令来测试代码。[Python 命令](https://inst.eecs.berkeley.edu/~cs61a/fa22/lab/lab00/#appendix-useful-python-command-line-options))。
|
||||||
|
|
||||||
|
## 要求:提交作业
|
||||||
|
|
||||||
|
现在您已经完成了第一个 CS 61A 作业,是时候上交了。您可以按照以下后续步骤提交您的作业并获得分数。
|
||||||
|
|
||||||
|
### 第 1 步:提交 `ok`
|
||||||
|
|
||||||
|
在您的终端中,确保您位于包含 `ok`. 如果你还没有,你可以使用这个命令:
|
||||||
|
|
||||||
|
```
|
||||||
|
cd ~/Desktop/cs61a/lab/lab00
|
||||||
|
```
|
||||||
|
|
||||||
|
接下来,使用 `ok` 选项 `--submit`:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
python3 ok --submit
|
||||||
|
```
|
||||||
|
|
||||||
|
如果您之前没有运行过,这将提示您输入电子邮件地址。请按照[这些说明](https://inst.eecs.berkeley.edu/~cs61a/fa22/articles/using-ok/#signing-in-with-ok)进行操作,如果遇到问题,请参阅该页面上的故障排除步骤。之后,Ok 将打印出如下消息:
|
||||||
|
|
||||||
|
```
|
||||||
|
Submitting... 100% complete
|
||||||
|
Submission successful for user: ...
|
||||||
|
URL: https://okpy.org/...
|
||||||
|
```
|
||||||
|
|
||||||
|
### 第 2 步:验证您的提交
|
||||||
|
|
||||||
|
您可以点击 Ok 打印出来的链接来查看您的最终提交,或者您可以转到 [okpy.org](https://okpy.org/)。您将能够在登录后查看您提交的内容。
|
||||||
|
|
||||||
|
> 请确保你用你在终端运行 `ok` 时提供的相同电子邮件登录!
|
||||||
|
|
||||||
|
您应该会看到 Lab 0 的成功提交。
|
||||||
|
|
||||||
|
<strong>恭喜</strong>,您刚刚提交了第一份 CS 61A 作业!
|
||||||
|
|
||||||
|
> 有关 Ok 的更多信息,请参见[此处](https://inst.eecs.berkeley.edu/~cs61a/fa22/articles/using-ok/)。您还可以使用 `--help` 标志:<br/>``sql<br/>python3 ok --help<br/>`` 这个标志的作用就像我们之前使用的 UNIX 命令一样。
|
||||||
|
|
||||||
|
## 附录:有用的 Python 命令行选项
|
||||||
|
|
||||||
|
运行 Python 文件时,您可以使用命令行选项进一步检查代码。这里有一些会派上用场。如果您想了解有关其他 Python 命令行选项的更多信息,请查看[文档](https://docs.python.org/3.9/using/cmdline.html)。
|
||||||
|
|
||||||
|
- 不使用命令行选项将运行您提供的文件中的代码并返回到命令行。例如,如果我们想以 `lab00.py` 这种方式运行,我们将在终端中写入:
|
||||||
|
|
||||||
|
```
|
||||||
|
python3 lab00.py
|
||||||
|
```
|
||||||
|
|
||||||
|
- <strong>-i</strong>:该 `-i` 选项运行您的 Python 脚本,然后打开交互式会话。在交互式会话中,您逐行运行 Python 代码并获得即时反馈,而不是一次运行整个文件。要退出,请 `exit()` 在解释器提示符中键入。`Ctrl-D` 您还可以在 Linux/Mac 计算机或 Windows 上使用键盘快捷键 `Ctrl-Z Enter`。
|
||||||
|
- 如果您在交互式运行 Python 文件时对其进行编辑,则需要退出并重新启动解释器才能使这些更改生效。
|
||||||
|
- 以下是我们如何以交互方式运行 `lab00.py`:
|
||||||
|
|
||||||
|
```
|
||||||
|
python3 -i lab00.py
|
||||||
|
```
|
||||||
|
|
||||||
|
- <strong>-m doctest</strong>:在特定文件中运行 doctests。Doctests 在函数中被三重引号 ( `"""`) 包围。
|
||||||
|
- 文件中的每个测试都包含 `>>>` 一些 Python 代码和预期的输出(尽管 `>>>` 在 doctest 命令的输出中看不到)。
|
||||||
|
- 要为 运行 doctests `lab00.py`,我们可以运行:
|
||||||
|
|
||||||
|
```
|
||||||
|
python3 -m doctest lab00.py
|
||||||
|
```
|
||||||
19
3.编程思维体系构建/3.6.5关于CS61A.md
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
# 关于 CS61A
|
||||||
|
|
||||||
|
这是 CS 61A Fall 2022 的网站:
|
||||||
|
|
||||||
|
[https://inst.eecs.berkeley.edu/~cs61a/fa22/](https://inst.eecs.berkeley.edu/~cs61a/fa22/)
|
||||||
|
|
||||||
|
在这个目录下的文章上传的 pdf 基本都是英文的,还请做好准备。
|
||||||
|
|
||||||
|
在每个 disc、lab、hw 和 proj 下,都会有相对应的.zip 文件,文件里装的是在学习过程中所需要的代码。
|
||||||
|
|
||||||
|
在文章的最后会附上 sol。
|
||||||
|
|
||||||
|
当然,在没有头绪的时候,你可以选择参考 sol,也可以重新学习视频和教科书,也可以改变做题的顺序。
|
||||||
|
|
||||||
|
ps:哪怕是 cs61a 这样优秀的课程,给出的解决方案里也会有不是那么正确的代码(它并不能处理所有的情况)
|
||||||
|
|
||||||
|
pps:如果你找到了 sol 里不是那么正确的代码,请联系我们,我们将新建一个文档来记录 sol 中这些“错误”的代码
|
||||||
|
|
||||||
|
ppps:当然存在“错误”的代码的概率很小,你发现它们的概率就更小了
|
||||||
7
3.编程思维体系构建/3.6Python(灵巧的胶水).md
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
# 3.6Python(灵巧的胶水)
|
||||||
|
|
||||||
|
Python 是一门简单易学的脚本语言学会,其能做的事情也很多,常见的就有网络爬虫,数据分析,前端开发,[机器学习](https://www.zhihu.com/search?q=%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0&search_source=Entity&hybrid_search_source=Entity&hybrid_search_extra=%7B%22sourceType%22%3A%22answer%22%2C%22sourceId%22%3A%222550582151%22%7D),都能很好地提高工作效率。
|
||||||
|
|
||||||
|
对于计算机科学的学生来说,python 不会设置专门的课程教你而是会要求你在假期内自学,因为其丰富的库函数和简洁的语法让 python 可以轻松完成一些本来非常难做到的事情。
|
||||||
|
|
||||||
|
[如果各位想要以查阅字典或者线性的方式了解一下不要看菜鸟教程!来看看这个](https://docs.python.org/zh-cn/3/tutorial/index.html),手册的是第一手资料正确性很高,或者说他基本不会出错!
|
||||||
80
3.编程思维体系构建/3.X 聊聊设计模式和程序设计.md
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
# 3.X 聊聊设计模式和程序设计
|
||||||
|
|
||||||
|
<em>Author: </em>ou_3840181b7c52ab34d2aa31f288fc7bc3<em> Last revised 2022/08/07</em>
|
||||||
|
|
||||||
|
## 前言
|
||||||
|
|
||||||
|
在开始讲内容之前,我觉得我得首先聊一聊到底为什么我们需要这些东西。为什么我们会需要设计模式呢?
|
||||||
|
|
||||||
|
这个问题并不可笑,也不幼稚,事实上,很多东西红极一时,最终却被历史证明是不被需要的。类似的事情太多了,可以是一种理念,比如日心说,可以是一种产品,比如软驱、RAMBUS 内存,等等。历史已经丢弃了太多不被需要的东西了。
|
||||||
|
|
||||||
|
学习本身是有成本的事情,如果在开始之前能够理解为什么要开始就更好,尽管很多时候我们做不到这件事,但也不能忘了这件事。
|
||||||
|
|
||||||
|
上个世纪 80~90 年代的时候,人们试图通过“设计模式”这一工具,抽象总结所有的软件设计方法,构建一个无敌的知识库。最终使得软件工程就像堆积木一样简单,避免软件随时间变得杂乱的熵增问题,但毫无疑问这是失败的,你永远无法抽象总结所有东西,设计模式的巅峰,可能是在 JDK 之中。在阅读 Java 自身提供的诸多 API 时,你会发现其中蕴藏了大量的设计模式,而且是赤裸裸地把使用了的设计模式写在了类名中,如“XXXListener”,很少有另一个语言也是这样的。
|
||||||
|
|
||||||
|
设计模式并没有完全成功,但也没有完全失败。他现在以一种“术语”的形式存在,帮助人们理解常见的编程范式。——这是什么意思呢?举个例子,如果你尝试和同事说明你的一个设计时,你说,它首先有两个类,一个类提供了一个通用的接口,可以被另一个类注册,另一个类则负责把所有的动作通知给已经注册的类。这种说法显然非常繁琐,对方也未必能理解你的意思。但如果你说,这里使用了监听者模式,如果你的同事碰巧学习过一些设计模式,他就能立即理解你的意思。即使他没有学习过相关知识,只要简单百度一下也能理解个大概。这是当今设计模式的一个重要作用。
|
||||||
|
|
||||||
|
另一个重要作用则是它的本源了,用于总结抽象程序设计的范式。但并不是说要你写的所有代码能用设计模式的就都用设计模式,这更多是提供给你一种选项,让你能够充分权衡。关于这部分,下文还会有说明。
|
||||||
|
|
||||||
|
目前的设计模式,主要集中在如何避免程序复杂度上。
|
||||||
|
|
||||||
|
什么是程序复杂度呢?就是说你今天写了个软件,明天给他加功能的时候发现这个程序不怎么可维护,于是直接在之前的逻辑上加了个 if,你的一个 if 通常不会有什么大问题,程序复杂性问题是日积月累的。随着大家都在不同的地方写自己的 if,整个程序最终会变得不可维护。可能一个微小的改动会导致很多地方的 if 出现不符合预期的判断,可能终有一天有一个需求无法再用 if 来实现,等等。
|
||||||
|
|
||||||
|
为了解决这个问题,设计模式使用的方法是原则,通过制定一系列的原则,并确保大家都遵守,来避免代码腐烂。
|
||||||
|
|
||||||
|
## 拿个锤子,见什么都是钉子
|
||||||
|
|
||||||
|
设计模式,或者说广义的程序设计架构的初学者,很多都会想去设计一个“完美的架构”。
|
||||||
|
|
||||||
|
当就像计算机程序设计本身是关于权衡的艺术一样,学习程序架构也不能看见什么都上架构。下面举例子具体说明。
|
||||||
|
|
||||||
|
你要设计一个小程序给自己用,这个程序的作用是定时读取一边本地硬盘上的全部文件,通过 sha256 算法生成每个文件的文件摘要,比对文件是否遭到篡改,如果遭到了篡改就报个警。
|
||||||
|
|
||||||
|
如果你没有学习过这些乱七八糟的设计模式,我想你大概会这么做:
|
||||||
|
|
||||||
|
main():
|
||||||
|
|
||||||
|
walk("/");
|
||||||
|
|
||||||
|
walk(String path):
|
||||||
|
|
||||||
|
For file : os.listfile(path):
|
||||||
|
|
||||||
|
// 检查文件摘要
|
||||||
|
|
||||||
|
For dir : os.listdir(path):
|
||||||
|
|
||||||
|
walk(dir);
|
||||||
|
|
||||||
|
但如果你很不幸,学习过一些设计模式,或者说有一些程序设计经验,你会开始考虑一下问题:
|
||||||
|
|
||||||
|
1. 我用什么语言实现?这个语言的代码文件组织有没有推荐的架构?(比如,第三方包引用了放在哪里?文件加密的 util 是放在内部还是封装成可供其他人引用的三方包?)
|
||||||
|
2. 选用什么样的依赖管理机制?
|
||||||
|
3. 编译最终产物的时候用什么工具,make 还是 maven 还是 gradle 还是 shell 还是 python?...
|
||||||
|
4. walk 能不能兼容不同平台的系统?在 win 下面能不能用?
|
||||||
|
5. 有没有什么设计模式可以用?(开始翻书)
|
||||||
|
6. 卧槽,用官方推荐的组织架构的话这个程序有点单薄啊,要不要加点功能上去
|
||||||
|
7. ...
|
||||||
|
|
||||||
|
要明白,拿着个锤子绝不能看什么都是钉子。
|
||||||
|
|
||||||
|
设计模式本身也是权衡的艺术,我们今天经常说的东西,比如 DDD,SOA,微服务,monorepo,也都是一种广义的设计模式。权衡什么呢?权衡的是:是要维持程序在发生功能变动时的可拓展性、降低程序维护复杂度,还是追求程序的快速实现。
|
||||||
|
|
||||||
|
拿上文的例子来说,如果你的所有程序都是在运行 Linux 上的,这个也只是给你自己快速检查文件完整性,之后也几乎不存在增加新的功能的可能,为什么不随便找个脚本语言快速十几行写完呢?
|
||||||
|
|
||||||
|
## 如何学习
|
||||||
|
|
||||||
|
个人认为,现在所谓的设计模式分两种,第一种是狭义的设计模式,就是各种设计模式的堆积。
|
||||||
|
|
||||||
|
此外,还有广义的设计模式,这块内容就很多了,但也是讨论如何降低代码复杂度的,包括:
|
||||||
|
|
||||||
|
1. 程序代码怎么组织(在开发 web 应用时这块经常有争议,可以参考 [https://cloud.tencent.com/developer/article/1837487](https://cloud.tencent.com/developer/article/1837487))
|
||||||
|
2. 程序之间怎么组织(是放在一个编成个大的,还是微服务,还是用 FaaS 之类的变体)
|
||||||
|
3. 一些帮助减少程序复杂度的代码原则:[https://zhuanlan.zhihu.com/p/82324809](https://zhuanlan.zhihu.com/p/82324809)
|
||||||
|
|
||||||
|
这部分的学习不能操之过急。个人的建议是:
|
||||||
|
|
||||||
|
1. 学习一些设计模式,看完两次肯定没什么感觉,甚至会觉得看了个寂寞(可以先看看 Head first 设计模式)
|
||||||
|
2. 忘了他,去写你自己的代码,遇到复杂度诅咒了再考虑如何解决
|
||||||
|
3. 读他人的优秀代码,想一想这里他为什么要这么写,换成是你的话会怎么写,各自有什么利弊
|
||||||
|
4. 重复 1
|
||||||
66
3.编程思维体系构建/3.Y 附加模块:Linux.md
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
# 附加模块:Linux
|
||||||
|
|
||||||
|
本来这个模块在编程模块内,但是鉴于大家都反应做这一块非常难,因此我将他提出作为一个额外的附加模块。
|
||||||
|
|
||||||
|
如果你想尝试使用 Linux 编程或者想了解更多计算机科学领域知识,你可以学习并阅览本部分内容。
|
||||||
|
|
||||||
|
当然你也可以先尝试完成第三部分的一些内容再回过头解决本部分的内容。
|
||||||
|
|
||||||
|
可能会花费你大量的时间,并且让你感受到非常困难,但是可以保证的是:你的一切投入,都是有收获的。
|
||||||
|
|
||||||
|
# What???Linux???
|
||||||
|
|
||||||
|
大家可能知道我们的电脑是 Windows 作为操作系统的。
|
||||||
|
|
||||||
|
而 Linux 也是一款有趣的开源(不懂意思?STFW)的操作系统
|
||||||
|
|
||||||
|
它既免费也自由 (能知道它内部的实现),而且互联网上有丰富的 (英文) 文档。
|
||||||
|
|
||||||
|
它的设计继承自 “Keep it simple, stupid” 的 UNIX,这个经典的设计背后的动机反而更容易为第一次接触操作系统的初学者所理解。让我们看看它的威力:
|
||||||
|
|
||||||
|
- 首先,操作系统里的一切对象都用文件表示 (Everything is a file)。进程、设备……都可以在任何编程语言里用文件 API 访问。
|
||||||
|
- Linux 的命令行 Shell 是一门编程语言——没错,你每天都在 “编程”!更准确地说,Shell 的功能就是把你想要做的事情 (类似自然语言描述的代码) 翻译成操作系统能看懂的文件/进程管理 API 调用。
|
||||||
|
|
||||||
|
# Why Linux???
|
||||||
|
|
||||||
|
作为一个双系统用户体验者来说,他除了玩游戏不那么方便以外,可以更为高效且便捷的办到 Windows 费很大力气才能办到的事情。
|
||||||
|
|
||||||
|
并且相当多的开发软件在 Linux 上有更好的兼容性,而到 windows 上你将会花费大量的时间配置各种环境变量还容易出错。
|
||||||
|
|
||||||
|
并且目前,服务器上为了保证低损耗,高效率,基本上百分之九十九都是 Linux 的系统,实验室的服务器也是 Linux 系统。
|
||||||
|
|
||||||
|
简单来说就是,你如果想干点事情,肯定要靠 Linux,因此学会 Linux 的操作是不可或缺的
|
||||||
|
|
||||||
|
## GUI 与 CLI
|
||||||
|
|
||||||
|
诚然,我们现在的图形化界面(GUI)已经深入到了生活的方方面面
|
||||||
|
|
||||||
|
[Command line vs. GUI](https://www.computerhope.com/issues/ch000619.htm)
|
||||||
|
|
||||||
|
这篇文章详细对比了图形化界面和单纯的终端命令的优劣
|
||||||
|
|
||||||
|
# How Linux???
|
||||||
|
|
||||||
|
那么这么好的东西哪里可以获得呢?
|
||||||
|
|
||||||
|
因为 Linux 有诸多发行版本,我在这里建议大家使用 Ubuntu22.04 作为主要版本进行使用
|
||||||
|
|
||||||
|
<del>作为</del><del> </del><del>STFW</del><del> </del><del>的尝试我将会把下载并使用这个作为一次作业留给大家</del>(过于高难 😤 这里给出教程)
|
||||||
|
|
||||||
|
# 任务
|
||||||
|
|
||||||
|
任务:装 Ubuntu22.04
|
||||||
|
|
||||||
|
tip1:推荐这个 [VMware 的安装与安装 ubuntu22.04 系统](https://gw9u39xwqi.feishu.cn/wiki/wikcnPquqfxujAgMWPbtRptk3BC)
|
||||||
|
|
||||||
|
tip2:可以使用 WSL[WSL 的安装](https://gw9u39xwqi.feishu.cn/wiki/wikcnwG2FBQe4FvkUSPF7207epg),<del>但是我更建议实装到电脑上双系统之类的</del>(我不建议 bug 很多 例如开不开机 要开好几回 网络连不上等),正好锻炼一下<del>装系统</del>倒腾的能力。大可不必删了 windows 换成 ubuntu。
|
||||||
|
|
||||||
|
tip3:前两个 tip 二选一
|
||||||
|
|
||||||
|
任务:阅读 GUI 与命令行之间对比的文章,尝试开始阅读英文文章
|
||||||
|
|
||||||
|
# 教程推荐
|
||||||
|
|
||||||
|
[https://missing-semester-cn.github.io/](https://missing-semester-cn.github.io/)
|
||||||
|
|
||||||
|
计算机教育中缺失的一课
|
||||||
111
3.编程思维体系构建/3.Y.1VMware的安装与安装Ubuntu22.04系统.md
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
# VMware 的安装与安装 Ubuntu22.04 系统
|
||||||
|
|
||||||
|
与 wsl 安装二选一 安装了 wsl 不用 VMware
|
||||||
|
|
||||||
|
首先下载 VMware
|
||||||
|
|
||||||
|
如果是 pro16 版本(key <strong>ZF3R0-FHED2-M80TY-8QYGC-NPKYF</strong>)
|
||||||
|
|
||||||
|
如果是 pro17 版本(key <strong>JU090-6039P-08409-8J0QH-2YR7F</strong><strong> </strong>)
|
||||||
|
|
||||||
|
本文写的时候用的版本是 pro16 ,但目前已经更新到 pro17 所以来更新个 key (如下安装与 16 版本无异)
|
||||||
|
|
||||||
|
[https://www.vmware.com/products/workstation-pro/workstation-pro-evaluation.html](https://www.vmware.com/products/workstation-pro/workstation-pro-evaluation.html)
|
||||||
|
|
||||||
|
一路下一步
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
这俩我推荐勾掉
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
安装过后点许可证 输上面的 key 激活
|
||||||
|
|
||||||
|
[https://mirror.nju.edu.cn/ubuntu-releases/22.04/ubuntu-22.04.1-desktop-amd64.iso](https://mirror.nju.edu.cn/ubuntu-releases/22.04/ubuntu-22.04.1-desktop-amd64.iso)
|
||||||
|
|
||||||
|
去这里下载 Ubuntu22.04 镜像包 iso
|
||||||
|
|
||||||
|
下好回到 VMware
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
创建新的虚拟机-典型(推荐)-下一步-安装程序 iso 选中你刚下的 iso 下一步
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
这里填你一会儿要登录 linux 的个人信息
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
这里建议把位置改到其他盘
|
||||||
|
|
||||||
|
一路下一步直到完成
|
||||||
|
|
||||||
|
启动后进入 Ubuntu 安装
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
键盘映射 直接 continue
|
||||||
|
|
||||||
|
接下来一路 continue install now
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
最后 restart
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
这个 skip
|
||||||
|
|
||||||
|
后面一路 next 最后 done
|
||||||
|
|
||||||
|
点右上角 settings
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
然后按指引 restart 系统
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
会提示你要不要重新命名这些用户下的文件夹
|
||||||
|
|
||||||
|
我建议选 `keep old names`
|
||||||
|
|
||||||
|
如果你的语言还没有变过来的话
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
点击这个他会安装语言
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
把汉语拖到英文之上 点应用到整个系统
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
右上角 logout 重新登陆 就是中文辣
|
||||||
|
|
||||||
|
最后在设置-电源把息屏改成从不
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
<strong>至此 恭喜安装完成!</strong>
|
||||||
|
|
||||||
|
之后就可以在桌面上右键
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
打开命令行
|
||||||
|
|
||||||
|
<strong>开始你的 Linux 学习吧</strong>
|
||||||
24
3.编程思维体系构建/3.Y.2WSL的安装.md
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
# WSL 的安装
|
||||||
|
|
||||||
|
与 VMware 安装二选一 安装了 VMware 不用 wsl
|
||||||
|
|
||||||
|
先说<strong>坏处</strong>:
|
||||||
|
|
||||||
|
1. 开启 hyperv 的后果是 如果你电脑装模拟器玩手游的话 装了 hyperv 你的模拟器是打不开的(目前只有 `蓝叠国际版HyperV版`(性能很差)支持共存 hyperv 和模拟器)
|
||||||
|
2. WSL 很难装辣 安装过程中会出很多 bug 需要你自行 STFW
|
||||||
|
|
||||||
|
## <strong>官方文档</strong>
|
||||||
|
|
||||||
|
## [史上最全的 WSL 安装教程](https://blog.csdn.net/wojiuguowei/article/details/122100090)
|
||||||
|
|
||||||
|
笔者不清楚当前版本 wsl 安装步骤 但是笔者安装的时候是需要在 `windows 功能` 中开启这三项
|
||||||
|
|
||||||
|
(现在可能是只开 `适用于Linux的windows子系统`)
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
如果你的 windows 版本为<strong>家庭版</strong> 那么 hyperv 选项是没有的
|
||||||
|
|
||||||
|
你需要右键以管理员权限打开以下脚本来强行开启 hyperv
|
||||||
|
|
||||||
|

|
||||||
157
3.编程思维体系构建/3.Y.3Linux初探索.md
Normal file
@@ -0,0 +1,157 @@
|
|||||||
|
# Linux 初探索
|
||||||
|
|
||||||
|
以下内容引自 JYY 课程的 Linux 教程,如果你是第一次接触,请一边仔细阅读,一边尝试敲命令在终端内。
|
||||||
|
|
||||||
|
有一点非常重要,这章节的内容到后面会略为困难,并且 linux 内容繁杂多样。
|
||||||
|
|
||||||
|
因此你可以自己选择是否完成后面的相关任务[一些基本常识](https://linux.cn/article-6160-1.html)这个是一定要看的,看了这个之后自由选择是否继续往下做
|
||||||
|
|
||||||
|
同时,如果你觉得难度太大,可以先去蓝桥云课进行尝试
|
||||||
|
|
||||||
|
# 探索命令行
|
||||||
|
|
||||||
|
Linux 命令行中的命令使用格式都是相同的:
|
||||||
|
|
||||||
|
```
|
||||||
|
命令名称 参数1 参数2 参数3 ...
|
||||||
|
```
|
||||||
|
|
||||||
|
参数之间用任意数量的空白字符分开. 关于命令行, 可以先阅读[一些基本常识](https://linux.cn/article-6160-1.html). 然后我们介绍最常用的一些命令:
|
||||||
|
|
||||||
|
- (重要)首先教一个命令 `sudo su` 进入 root 账户(敲完之后会让你敲当前登录账户的密码 密码敲得过程中没有*****这种传统敲密码的提示 为 linux 传统艺能 其实是敲进去了),因为本身普通账户没什么权限,会出现处处的权限提示,建议直接使用 root 账户。
|
||||||
|
|
||||||
|
```
|
||||||
|
这里有一个彩蛋 (如果你用的是centos的话)
|
||||||
|
<strong>当用户第一次使用sudo权限时CentOS的系统提示:</strong>
|
||||||
|
我们信任您已经从系统管理员那里了解了日常注意事项。
|
||||||
|
总结起来无外乎这三点:
|
||||||
|
#1) 尊重别人的隐私。
|
||||||
|
#2) 输入前要先考虑(后果和风险)。
|
||||||
|
#3) 权力越大,责任越大。
|
||||||
|
```
|
||||||
|
|
||||||
|
- `ls` 用于列出当前目录(即"文件夹")下的所有文件(或目录). 目录会用蓝色显示. `ls -l` 可以显示详细信息.
|
||||||
|
- `pwd` 能够列出当前所在的目录.
|
||||||
|
- `cd DIR` 可以切换到 `DIR` 目录. 在 Linux 中, 每个目录中都至少包含两个目录: `.` 指向该目录自身, `..` 指向它的上级目录. 文件系统的根是 `/`.
|
||||||
|
- `touch NEWFILE` 可以创建一个内容为空的新文件 `NEWFILE`, 若 `NEWFILE` 已存在, 其内容不会丢失.
|
||||||
|
- `cp SOURCE DEST` 可以将 `SOURCE` 文件复制为 `DEST` 文件; 如果 `DEST` 是一个目录, 则将 `SOURCE` 文件复制到该目录下.
|
||||||
|
- `mv SOURCE DEST` 可以将 `SOURCE` 文件重命名为 `DEST` 文件; 如果 `DEST` 是一个目录, 则将 `SOURCE` 文件移动到该目录下.
|
||||||
|
- `mkdir DIR` 能够创建一个 `DIR` 目录.
|
||||||
|
- `rm FILE` 能够删除 `FILE` 文件; 如果使用 `-r` 选项则可以递归删除一个目录. 删除后的文件无法恢复, 使用时请谨慎!
|
||||||
|
- `man` 可以查看命令的帮助. 例如 `man ls` 可以查看 `ls` 命令的使用方法. 灵活应用 `man` 和互联网搜索, 可以快速学习新的命令.
|
||||||
|
|
||||||
|
`man` 的功能不仅限于此. `man` 后可以跟两个参数, 可以查看不同类型的帮助(请在互联网上搜索). 例如当你不知道 C 标准库函数 `freopen` 如何使用时, 可以键入命令
|
||||||
|
|
||||||
|
```
|
||||||
|
man 3 freopen
|
||||||
|
```
|
||||||
|
|
||||||
|
## <strong>统计代码行数</strong>
|
||||||
|
|
||||||
|
第一个例子是统计一个目录中(包含子目录)中的代码行数. 如果想知道当前目录下究竟有多少行的代码, 就可以在命令行中键入如下命令:
|
||||||
|
|
||||||
|
```
|
||||||
|
find . | grep '\.c$\|\.h$' | xargs wc -l
|
||||||
|
```
|
||||||
|
|
||||||
|
如果用 `man find` 查看 `find` 操作的功能, 可以看到 `find` 是搜索目录中的文件. Linux 中一个点 `.` 始终表示 Shell 当前所在的目录, 因此 `find .` 实际能够列出当前目录下的所有文件. 如果在文件很多的地方键入 `find .`, 将会看到过多的文件, 此时可以按 `CTRL + c` 退出.
|
||||||
|
|
||||||
|
同样, 用 `man` 查看 `grep` 的功能——"print lines matching a pattern". `grep` 实现了输入的过滤, 我们的 `grep` 有一个参数, 它能够匹配以 `.c` 或 `.h` 结束的文件. 正则表达式是处理字符串非常强大的工具之一, 每一个程序员都应该掌握其相关的知识. ? 上述的 `grep` 命令能够提取所有 `.c` 和 `.h` 结尾的文件.
|
||||||
|
|
||||||
|
刚才的 `find` 和 `grep` 命令, 都从标准输入中读取数据, 并输出到标准输出. 关于什么是标准输入输出, 请参考[这里](http://en.wikipedia.org/wiki/Standard_streams). 连接起这两个命令的关键就是管道符号 `|`. 这一符号的左右都是 Shell 命令, `A | B` 的含义是创建两个进程 `A` 和 `B`, 并将 `A` 进程的标准输出连接到 `B` 进程的标准输入. 这样, 将 `find` 和 `grep` 连接起来就能够筛选出当前目录(`.`)下所有以 `.c` 或 `.h` 结尾的文件.
|
||||||
|
|
||||||
|
我们最后的任务是统计这些文件所占用的总行数, 此时可以用 `man` 查看 `wc` 命令. `wc` 命令的 `-l` 选项能够计算代码的行数. `xargs` 命令十分特殊, 它能够将标准输入转换为参数, 传送给第一个参数所指定的程序. 所以, 代码中的 `xargs wc -l` 就等价于执行 `wc -l aaa.c bbb.c include/ccc.h ...`, 最终完成代码行数统计.
|
||||||
|
|
||||||
|
## <strong>统计磁盘使用情况</strong>
|
||||||
|
|
||||||
|
以下命令统计 `/usr/share` 目录下各个目录所占用的磁盘空间:
|
||||||
|
|
||||||
|
```
|
||||||
|
du -sc /usr/share/* | sort -nr
|
||||||
|
```
|
||||||
|
|
||||||
|
`du` 是磁盘空间分析工具, `du -sc` 将目录的大小顺次输出到标准输出, 继而通过管道传送给 `sort`. `sort` 是数据排序工具, 其中的选项 `-n` 表示按照数值进行排序, 而 `-r` 则表示从大到小输出. `sort` 可以将这些参数连写在一起.
|
||||||
|
|
||||||
|
然而我们发现, `/usr/share` 中的目录过多, 无法在一个屏幕内显示. 此时, 我们可以再使用一个命令: `more` 或 `less`.
|
||||||
|
|
||||||
|
```
|
||||||
|
du -sc /usr/share/* | sort -nr | more
|
||||||
|
```
|
||||||
|
|
||||||
|
此时将会看到输出的前几行结果. `more` 工具使用空格翻页, 并可以用 `q` 键在中途退出. `less` 工具则更为强大, 不仅可以向下翻页, 还可以向上翻页, 同样使用 `q` 键退出. 这里还有一个[关于 less 的小故事](http://en.wikipedia.org/wiki/Less_(Unix)).
|
||||||
|
|
||||||
|
## <strong>在 Linux 下编写 Hello World 程序</strong>
|
||||||
|
|
||||||
|
Linux 中用户的主目录是 `/home/用户名称`, 如果你的用户名是 `user`, 你的主目录就是 `/home/user`. 用户的 `home` 目录可以用波浪符号 `~` 替代, 例如临时文件目录 `/home/user/Templates` 可以简写为 `~/Templates`. 现在我们就可以进入主目录并编辑文件了. 如果 `Templates` 目录不存在, 可以通过 `mkdir` 命令创建它:
|
||||||
|
|
||||||
|
```
|
||||||
|
cd ~
|
||||||
|
mkdir Templates
|
||||||
|
```
|
||||||
|
|
||||||
|
创建成功后, 键入
|
||||||
|
|
||||||
|
```
|
||||||
|
cd Templates
|
||||||
|
```
|
||||||
|
|
||||||
|
可以完成目录的切换. 注意在输入目录名时, `tab` 键可以提供联想.
|
||||||
|
|
||||||
|
##### <strong> 你感到键入困难吗?</strong>
|
||||||
|
|
||||||
|
你可能会经常要在终端里输入类似于
|
||||||
|
|
||||||
|
cd AVeryVeryLongFileName
|
||||||
|
|
||||||
|
的命令, 你一定觉得非常烦躁. 回顾上面所说的原则之一: 如果你感到有什么地方不对, 就一定有什么好办法来解决. 试试 `tab` 键吧.
|
||||||
|
|
||||||
|
Shell 中有很多这样的小技巧, 你也可以使用其他的 Shell 例如 zsh, 提供更丰富好用的功能. 总之, 尝试和改变是最重要的.
|
||||||
|
|
||||||
|
进入正确的目录后就可以编辑文件了, 开源世界中主流的两大编辑器是 `vi(m)` 和 `emacs`, 你可以使用其中的任何一种. 如果你打算使用 `emacs`, 你还需要安装它
|
||||||
|
|
||||||
|
```
|
||||||
|
apt-get install emacs
|
||||||
|
```
|
||||||
|
|
||||||
|
`vi` 和 `emacs` 这两款编辑器都需要一定的时间才能上手, 它们共同的特点是需要花较多的时间才能适应基本操作方式(命令或快捷键), 但一旦熟练运用, 编辑效率就比传统的编辑器快很多.
|
||||||
|
|
||||||
|
进入了正确的目录后, 输入相应的命令就能够开始编辑文件. 例如输入
|
||||||
|
|
||||||
|
```
|
||||||
|
vi hello.c
|
||||||
|
或emacs hello.c
|
||||||
|
```
|
||||||
|
|
||||||
|
就能开启一个文件编辑. 例如可以键入如下代码(对于首次使用 `vi` 或 `emacs` 的同学, 键入代码可能会花去一些时间, 在编辑的同时要大量查看网络上的资料):
|
||||||
|
|
||||||
|
```
|
||||||
|
#include <stdio.h>
|
||||||
|
int main(void) {
|
||||||
|
printf("Hello, Linux World!\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
> 相信你在写完代码之后苦于不知道怎么保存并退出,不用担心,这个是正常的,毕竟上面提到的两个文本编辑器都是以入门时的学习曲线及其陡峭而著称。<br/>对于 vi(m)风格的编辑器,你需要先按 `ESC` 返回 NORMAL 模式(具体处于那个模式可以观察窗口左下角,NORMAL 模式是空白的),再输入 `:wq` 来保存并退出(注意 `:` 是输入的一部分 )(`:q 仅退出` `:q! 不保存退出` )<br/>呃呃 [【保姆级入门】Vim 编辑器](https://www.bilibili.com/video/BV13t4y1t7Wg)
|
||||||
|
|
||||||
|
保存后就能够看到 `hello.c` 的内容了. 终端中可以用 `cat hello.c` 查看代码的内容. 如果要将它编译, 可以使用 `gcc` 命令:
|
||||||
|
|
||||||
|
```
|
||||||
|
gcc hello.c -o hello
|
||||||
|
```
|
||||||
|
|
||||||
|
`gcc` 的 `-o` 选项指定了输出文件的名称, 如果将 `-o hello` 改为 `-o hi`, 将会生成名为 `hi` 的可执行文件. 如果不使用 `-o` 选项, 则会默认生成名为 `a.out` 的文件, 它的含义是 [assembler output](http://en.wikipedia.org/wiki/A.out). 在命令行输入
|
||||||
|
|
||||||
|
```
|
||||||
|
./hello
|
||||||
|
```
|
||||||
|
|
||||||
|
就能够运行改程序. 命令中的 `./` 是不能少的, 点代表了当前目录, 而 `./hello` 则表示当前目录下的 `hello` 文件. 与 Windows 不同, Linux 系统默认情况下并不查找当前目录, 这是因为 Linux 下有大量的标准工具(如 `test` 等), 很容易与用户自己编写的程序重名, 不搜索当前目录消除了命令访问的歧义.
|
||||||
|
|
||||||
|
# 任务
|
||||||
|
|
||||||
|
尝试使用 linux,并且完成上述内容
|
||||||
|
|
||||||
|
自行搜索不懂得内容并且尝试使用更多你感兴趣的 linux 操作或 linux 插件
|
||||||
|
|
||||||
|
将你探索未知得心得写成邮件发给我吧
|
||||||
74
3.编程思维体系构建/3.Y.4Vim初探索.md
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
# Vim 初探索
|
||||||
|
|
||||||
|
# 下载 vim
|
||||||
|
|
||||||
|
vim 被称为编辑器之神
|
||||||
|
|
||||||
|
看到这一句可能就激发了你学习 vim 的热情,但是看完整篇文章和文章里面的所有参考资料,可能这股来之不易的热情也早就消失了。为了避免这种情况,我给一个小小的建议:
|
||||||
|
|
||||||
|
1. 首先学会盲打,不会的话,不是很建议用 vim / Emacs 这样的编辑器,还是拥抱鼠标吧
|
||||||
|
2. 学习使用 hjklia 这六个键,然后理解插入模式和普通模式,再了解怎么退出
|
||||||
|
3. 使用 vim 作为日常的编辑工具,在你所有的代码编辑器里面都装上 vim 插件并使用,强迫自己习惯 hjkl 的移动和带模式的输入,习惯按 <ESC>
|
||||||
|
4. 到这个时候你就会感觉的确可以不用鼠标了,但是有的时候会比较别扭,比如想新建一行时,得按 L 移到行尾,然后按 a 追加,再按回车,远远比鼠标麻烦有没有,这种情况就可以上网查询,`vim 如何新建一行`,就会学到 o 可以向下新建一行,O 可以向上新建一行,然后你就能自然地学会更多的操作。
|
||||||
|
|
||||||
|
因为其具有着非常完整的生态以及诸多配套的插件,但是第一次使用得你可能感觉很不习惯。
|
||||||
|
|
||||||
|
讲一个笑话,你如何获得一个随机字符串,只要让新人使用 vim 就好了。
|
||||||
|
|
||||||
|
不开玩笑,为了让你不小心在命令行模式下进入 vim 又不知道怎么退出时不需要拔电源来退出,先按几次 <ESC> 键(避免你之前不小心按到了 i 或 a 或 o 或等等按键)进入普通模式,然后顺序敲击 `:q`(冒号 和 q 两个按键 ),再按回车就可以退出了。
|
||||||
|
|
||||||
|
```
|
||||||
|
apt-get install vim
|
||||||
|
```
|
||||||
|
|
||||||
|
但是我仍然推荐你尝试使用或者结合 VSC 一起使用,使用习惯后将有效提高你的开发效率。
|
||||||
|
|
||||||
|
# 如何学习 vim
|
||||||
|
|
||||||
|
作为程序员,我们大部分时间都花在代码编辑上,所以花点时间掌握某个适合自己的编辑器是非常值得的。通常学习使用一个新的编辑器包含以下步骤:
|
||||||
|
|
||||||
|
- 阅读教程(比如这节课以及我们为您提供的资源)
|
||||||
|
- 坚持使用它来完成你所有的编辑工作(即使一开始这会让你的工作效率降低)
|
||||||
|
- 随时查阅:如果某个操作看起来像是有更方便的实现方法,一般情况下真的会有。
|
||||||
|
|
||||||
|
如果您能够遵循上述步骤,并且坚持使用新的编辑器完成您所有的文本编辑任务,那么学习一个复杂的代码编辑器的过程一般是这样的:头两个小时,您会学习到编辑器的基本操作,例如打开和编辑文件、保存与退出、浏览缓冲区。当学习时间累计达到 20 个小时之后,您使用新编辑器的效率应该已经和使用老编辑器一样快。在此之后,其益处开始显现:有了足够的知识和肌肉记忆后,使用新编辑器将大大节省你的时间。而现代文本编辑器都是些复杂且强大的工具,永远有新东西可学:学的越多,效率越高。
|
||||||
|
|
||||||
|
# <strong>Vim 的哲学</strong>
|
||||||
|
|
||||||
|
在编程的时候,你会把大量时间花在阅读/编辑而不是在写代码上。所以,Vim 是一个_多模态_编辑 器:它对于插入文字和操纵文字有不同的模式。Vim 是可编程的(可以使用 Vimscript 或者像 Python 一样的其他程序语言),Vim 的接口本身也是一个程序语言:键入操作(以及其助记名) 是命令,这些命令也是可组合的。Vim 避免了使用鼠标,因为那样太慢了;Vim 甚至避免用 上下左右键因为那样需要太多的手指移动。
|
||||||
|
|
||||||
|
这样的设计哲学使得 Vim 成为了一个能跟上你思维速度的编辑器。
|
||||||
|
|
||||||
|
# 学习 Vim
|
||||||
|
|
||||||
|
如果想要使用他最基本的操作的话,在电脑上键入 vimtutor
|
||||||
|
|
||||||
|
会有官方的教程进行引导哦。
|
||||||
|
|
||||||
|
# 配置 vim
|
||||||
|
|
||||||
|
vim 有大量的配置,通过更改./vimrc 文件或者安装插件都可以有效提高你的开发效率,定制属于你个人的编辑器哦~
|
||||||
|
|
||||||
|
快去试试吧
|
||||||
|
|
||||||
|
# 任务
|
||||||
|
|
||||||
|
定制 vim 成为你喜欢的模样,加装足够多的插件和更改足够多的配置让他满足以下几点或以上
|
||||||
|
|
||||||
|
- 文件管理
|
||||||
|
- 快速回退
|
||||||
|
- 变得好看
|
||||||
|
- 行号
|
||||||
|
- 代码搜索
|
||||||
|
- 模糊搜索
|
||||||
|
- ...............
|
||||||
|
|
||||||
|
可以尝试查看 vim Awesome 哦
|
||||||
|
|
||||||
|
[vim awesome](https://vimawesome.com/)
|
||||||
|
|
||||||
|
# 拓展阅读
|
||||||
|
|
||||||
|
[Learn-Vim(the Smart Way) 中文翻译](https://github.com/wsdjeg/Learn-Vim_zh_cn)
|
||||||
|
|
||||||
|
讲述了 vim 哲学的优秀教程
|
||||||
20
3.编程思维体系构建/3.Y.5linux小任务.md
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
# linux 小任务
|
||||||
|
|
||||||
|
1. 本课程需要使用类 Unix shell,例如 Bash 或 ZSH。如果您在 Linux 或者 MacOS 上面完成本课程的练习,则不需要做任何特殊的操作。如果您使用的是 Windows,则您不应该使用 cmd 或是 Powershell;您可以使用<u>Windows Subsystem for Linux</u>或者是 Linux 虚拟机。使用 `echo $SHELL` 命令可以查看您的 shell 是否满足要求。如果打印结果为 `/bin/bash` 或 `/usr/bin/zsh` 则是可以的。
|
||||||
|
2. 在 `/tmp` 下新建一个名为 `missing` 的文件夹。
|
||||||
|
3. 用 `man` 查看程序 `touch` 的使用手册。
|
||||||
|
4. 用 `touch` 在 `missing` 文件夹中新建一个叫 `semester` 的文件。
|
||||||
|
5. 将以下内容一行一行地写入 `semester` 文件:
|
||||||
|
|
||||||
|
```
|
||||||
|
#!/bin/sh
|
||||||
|
curl --head --silent https://missing.csail.mit.edu
|
||||||
|
```
|
||||||
|
|
||||||
|
第一行可能有点棘手, `#` 在 Bash 中表示注释,而 `!` 即使被双引号(`"`)包裹也具有特殊的含义。 单引号(`'`)则不一样,此处利用这一点解决输入问题。更多信息请参考 <u>Bash quoting 手册</u>
|
||||||
|
|
||||||
|
1. 尝试执行这个文件。例如,将该脚本的路径(`./semester`)输入到您的 shell 中并回车。如果程序无法执行,请使用 `ls` 命令来获取信息并理解其不能执行的原因。
|
||||||
|
2. 查看 `chmod` 的手册(例如,使用 `man chmod` 命令)
|
||||||
|
3. 使用 `chmod` 命令改变权限,使 `./semester` 能够成功执行,不要使用 `sh semester` 来执行该程序。您的 shell 是如何知晓这个文件需要使用 `sh` 来解析呢?更多信息请参考:<u>shebang</u>
|
||||||
|
4. 使用 `|` 和 `>` ,将 `semester` 文件输出的最后更改日期信息,写入主目录下的 `last-modified.txt` 的文件中
|
||||||
|
5. 写一段命令来从 `/sys` 中获取笔记本的电量信息,或者台式机 CPU 的温度
|
||||||
BIN
3.编程思维体系构建/static/CWDhbW6gzogyMFxtd6kcnPBunv2.png
Normal file
|
After Width: | Height: | Size: 131 KiB |
BIN
3.编程思维体系构建/static/Cpfzb9oK2oMyGxxgkqVceE8DnId.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
3.编程思维体系构建/static/FkOybDwtnoQeRyxejlwcjhQ2nch.png
Normal file
|
After Width: | Height: | Size: 171 KiB |
BIN
3.编程思维体系构建/static/GEN5b1HHdoDegPxAp8WcQDGknoc.png
Normal file
|
After Width: | Height: | Size: 70 KiB |
BIN
3.编程思维体系构建/static/HZNMbzGZOoQGAhxQ29gcM5V4nNd.png
Normal file
|
After Width: | Height: | Size: 93 KiB |
BIN
3.编程思维体系构建/static/HgTfbMhCGodZbzxBNh9crH3cnCe.png
Normal file
|
After Width: | Height: | Size: 450 KiB |
BIN
3.编程思维体系构建/static/L5HvblSuYonJn4x03a4cMLKknrh.png
Normal file
|
After Width: | Height: | Size: 9.3 KiB |
BIN
3.编程思维体系构建/static/MF4ZbUZ0qo70gRxeNGocsYvmnwe.png
Normal file
|
After Width: | Height: | Size: 154 KiB |
BIN
3.编程思维体系构建/static/boxcn1HbQct335qvZ71tGNu7jne.png
Normal file
|
After Width: | Height: | Size: 31 KiB |
BIN
3.编程思维体系构建/static/boxcn30VJILYpO81pq89mAmzjTf.png
Normal file
|
After Width: | Height: | Size: 175 KiB |
BIN
3.编程思维体系构建/static/boxcn3PLPIvKSSvYiCnwx50FYvf.png
Normal file
|
After Width: | Height: | Size: 124 KiB |
BIN
3.编程思维体系构建/static/boxcn5Uk41JyjjdTzXWQqUkexzc.png
Normal file
|
After Width: | Height: | Size: 114 KiB |
BIN
3.编程思维体系构建/static/boxcn5sVnE76FYpVW2RDxtWDiZc.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
3.编程思维体系构建/static/boxcn6ZnAzhaj2Tj7xk9K6FxBJh.png
Normal file
|
After Width: | Height: | Size: 58 KiB |
BIN
3.编程思维体系构建/static/boxcn85Yb3JIQ3520KeaSoyPVDd.png
Normal file
|
After Width: | Height: | Size: 72 KiB |
BIN
3.编程思维体系构建/static/boxcn8aRDQpe7uuDxFv9v1WvZ4c.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
3.编程思维体系构建/static/boxcn95LbcwuMC2dIViOxWk8BFb.png
Normal file
|
After Width: | Height: | Size: 84 KiB |
BIN
3.编程思维体系构建/static/boxcn9DSPlFgG2WMZhTOE9Zhzgb.png
Normal file
|
After Width: | Height: | Size: 8.0 KiB |
BIN
3.编程思维体系构建/static/boxcn9VFPUYHl8ghJ3C78RsXjtf.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
3.编程思维体系构建/static/boxcnBMq0sw6c48jvjdPJwmAGtZ.png
Normal file
|
After Width: | Height: | Size: 75 KiB |
BIN
3.编程思维体系构建/static/boxcnCNpeAE9Hy61cyvtxfioIHg.png
Normal file
|
After Width: | Height: | Size: 144 KiB |
BIN
3.编程思维体系构建/static/boxcnCX92JHjg8PU3quKs4GziZb.png
Normal file
|
After Width: | Height: | Size: 9.1 KiB |
BIN
3.编程思维体系构建/static/boxcnG6z1VpAYUGMSkSwDBUxEvf.png
Normal file
|
After Width: | Height: | Size: 114 KiB |
BIN
3.编程思维体系构建/static/boxcnGHnjgZvtcBrm0XXitFl4Jg.png
Normal file
|
After Width: | Height: | Size: 41 KiB |
BIN
3.编程思维体系构建/static/boxcnHd7Qfi8C0Y7V2Ot5ii4vpf.png
Normal file
|
After Width: | Height: | Size: 97 KiB |
BIN
3.编程思维体系构建/static/boxcnHemi9HkeAG1fgoznHbHLrc.png
Normal file
|
After Width: | Height: | Size: 294 KiB |
BIN
3.编程思维体系构建/static/boxcnJOjh1Zfp9tCd3llL9NsEzb.png
Normal file
|
After Width: | Height: | Size: 90 KiB |
BIN
3.编程思维体系构建/static/boxcnKzJjY8Dvj13A49bnMAztPg.png
Normal file
|
After Width: | Height: | Size: 102 KiB |
BIN
3.编程思维体系构建/static/boxcnL5Jn3g7AdzVzoBb6ZINs1f.png
Normal file
|
After Width: | Height: | Size: 83 KiB |
BIN
3.编程思维体系构建/static/boxcnLguvbHihJ3ngqrtyGLI6zf.png
Normal file
|
After Width: | Height: | Size: 87 KiB |
BIN
3.编程思维体系构建/static/boxcnLxZnyFN3ohE8zrTwNaCA8e.png
Normal file
|
After Width: | Height: | Size: 213 KiB |
BIN
3.编程思维体系构建/static/boxcnNBu1EJnva4EkyQZAVlwGMe.png
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
3.编程思维体系构建/static/boxcnQkVQ4uyYCveO6toBujoGOc.png
Normal file
|
After Width: | Height: | Size: 144 KiB |
BIN
3.编程思维体系构建/static/boxcnTfvjYweuIZFKlcH78X38Pd.png
Normal file
|
After Width: | Height: | Size: 54 KiB |
BIN
3.编程思维体系构建/static/boxcnTiaT2EnNfKVkretPsyajVd.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
3.编程思维体系构建/static/boxcnXilUhHNEyU4r95FxiVgCdg.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
3.编程思维体系构建/static/boxcnYHd076RAqfDmHjbUkeNSvg.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
3.编程思维体系构建/static/boxcnYVkEecWdUs710e8h6G9GTh.png
Normal file
|
After Width: | Height: | Size: 60 KiB |
BIN
3.编程思维体系构建/static/boxcnZLHO1JGWoSqhM9zEEhSMAd.png
Normal file
|
After Width: | Height: | Size: 87 KiB |
BIN
3.编程思维体系构建/static/boxcnZpPsp4FP78auolzHvCKP0g.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
3.编程思维体系构建/static/boxcnaS7aOzdt31vsZZx8R1s33e.png
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
3.编程思维体系构建/static/boxcnccDSRQj5W3lZWEUkCOHz2b.png
Normal file
|
After Width: | Height: | Size: 33 KiB |
BIN
3.编程思维体系构建/static/boxcndHnAuGC7TXhQgLkpLkHghf.png
Normal file
|
After Width: | Height: | Size: 63 KiB |
BIN
3.编程思维体系构建/static/boxcndgDKfTuio3nF0QboemIPHe.png
Normal file
|
After Width: | Height: | Size: 79 KiB |
BIN
3.编程思维体系构建/static/boxcnfcCnAdtdX2oyLIC3NibVnf.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
3.编程思维体系构建/static/boxcnfwk8gnFAHu5JzVUiugJjQe.png
Normal file
|
After Width: | Height: | Size: 250 KiB |
BIN
3.编程思维体系构建/static/boxcngNZOSnYUtCKH6pm8UaUMNd.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
3.编程思维体系构建/static/boxcni2dupDzNO8qTWPAxS5c67b.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
3.编程思维体系构建/static/boxcnltCL3atXHtC3BUj5VI1Lqf.png
Normal file
|
After Width: | Height: | Size: 83 KiB |
BIN
3.编程思维体系构建/static/boxcnm4R1ZN0WeUBuYht6zge7pd.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
3.编程思维体系构建/static/boxcnmwlYWOzwPbNqTAuSZK9dW3.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
3.编程思维体系构建/static/boxcnnLCJzGoFrUbWIMAPGFkxcb.png
Normal file
|
After Width: | Height: | Size: 127 KiB |
BIN
3.编程思维体系构建/static/boxcnnsuoHmhK4dBCLHlKhpRWIe.png
Normal file
|
After Width: | Height: | Size: 7.0 KiB |
BIN
3.编程思维体系构建/static/boxcnoCF5MilDma33yviwRGdDHe.png
Normal file
|
After Width: | Height: | Size: 33 KiB |
BIN
3.编程思维体系构建/static/boxcnp33Oc3Ia2HzASTZJNOhEWb.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
3.编程思维体系构建/static/boxcnsN133WrLrbxsX8JgvsQmif.png
Normal file
|
After Width: | Height: | Size: 32 KiB |
BIN
3.编程思维体系构建/static/boxcntUYJNAaOwB8L6KSEhJJojh.png
Normal file
|
After Width: | Height: | Size: 83 KiB |
BIN
3.编程思维体系构建/static/boxcnvLxCTKYfogPm9GNaKmusEf.png
Normal file
|
After Width: | Height: | Size: 21 KiB |
BIN
3.编程思维体系构建/static/boxcnvTQPcmPpUonmDZFZXNnGWd.png
Normal file
|
After Width: | Height: | Size: 39 KiB |
BIN
3.编程思维体系构建/static/boxcnyt3eeZQyN8b1xM1WjDrTGe.png
Normal file
|
After Width: | Height: | Size: 59 KiB |