历史笔记 2
原载于 https://github.com/district10/blog/blob/master/_pages/notes.md。
- How many Computer Languages are there?
@
late 1940s first electronic computers & LLLs 1950s first HLLs for computers 1969 about 120 HLLs, about 15 in widespread use 1977 about 80 HLLs in active (non-trivial) use Today more than 2000 HLLs
- Scripting Paradigm
So far, we have been thinking about languages suitable for solving very large problems, where the resulting programs are tens of thousands or more lines long, written and maintained by more than one person. However, not all problems require industrial-strength solutions, and different requirements have given rise to different kinds of languages. The situations where they are applicable are:
building applications by gluing together existing components controlling applications that have a programmable interface writing programs where ease of development is more important than anything else (such as run-time efficiency, or maintainability)
- Google Search
@
inurl:text intitle:text allintitle:text filetype:pdf site:pan.baidu.com weather:wuhan see more and...
计算机相关词汇
@
- CGI(公共网关接口,Common Gateway Interface) — 在 Web 服务器上,用来在脚本和/或应用程序之间传输数据,然后将该数据返回给 Web 页面或浏览器。CGI 脚本经常是使用 Perl 语言创建的,它能够生成动态 Web 内容(包括电子商业购物篮、讨论组、调查表单以及实时新闻等)。
- CHS(柱面/磁头/扇区,Cylinder/Head/Sector) — FDISK 在分区期间所需的磁盘信息。
- CLU(命令行实用程序,Command Line Utility) — 从命令行会话或 shell 运行的程序,如 Tar 或 Mkdir。
- LILO(Linux 装载程序,LInux LOader) — 一种流行的分区引导管理器实用程序,能够引导到 Linux 以外的操作系统。它并不特定于文件系统。
- MIME(多用途因特网邮件交换,Multipurpose Internet Mail Exchange) — 允许文本电子邮件消息包含非文本(例如图形、视频或音频)数据的通信协议。
- PAM(可插入的认证模块,Pluggable Authentication Modules) — 用于系统安全性的可替换的用户认证模块,它允许在不知道将使用何种认证方案的情况下进行编程。这允许将来用其它模块来替换某个模块,却无需重写软件。
- RCS(修订控制系统,Revision Control System) — 一组程序,它们控制组环境下文件的共享访问并跟踪文本文件的变化。常用于维护源代码模块的编码工作。
- RFS(远程文件共享,Remote File Sharing) — 一个程序,它让用户访问其它计算机上的文件,就好象文件在用户的系统上一样。
- RPM(RPM 软件包管理器,RPM Package Manager) — 一种用于因特网下载包的打包及安装工具,它包含在某些 Linux 分发版中。它生成具有 .RPM 扩展名的文件。与 Dpkg 类似。
ag --pager less <qry> [<filename>]
pt --color --group <qry> | less
- 假脱机(Spool)(外围设备联机并发操作,Simultaneous Peripheral Operation On-Line) — 将数据发送给一个程序,该程序将该数据信息放入队列以备将来使用(例如,打印假脱机程序)。
- 隐写术(Steganography,
[,stegə'nɔgrəfi]
n. 速记式加密)— 将一段信息隐藏在另一段信息中的做法。一个示例是在数字化照片中放置不可见的数字水印。 - Tux— 虚构的 Linux 企鹅吉祥物的名字。
- 工作目录(Working Directory)— 当前目录或用户当前工作时所在的目录的另一名称。
"kyy
vs."Kyy
"kp
==="Kp
:reg
- Vim notes
@
Yank the text you want to copy with
y[motion]
- this text is saved in"
and0
registers. Delete the text you want to replace withd[motion]
- this text is saved in"
register. Paste the yanked text with"0p
We can now just type
@m
to run this macro on the current line. Furthermore, we can type100@m
to do this 100 times! Lifes looking pretty good.:%normal @a
apply to this region.J
合并行,并两行之间增加一个空格gJ
合并行没有空格vip
我一直使用 v i p 按键组合,快速选中一段,在代码块间使用非常方便。<c-a> <c-x>
number++, number–cat /etc/fstab
mount /cdrom
eject /cdrom
cd
+ TABmd path/to/dir
===mkdir -p path/to/dir
rd path/to/dir
===rmdir path/to/dir
d
===dirs -V
: lists last used directories- Bash:
set -o vi
,set -o emacs
- Zsh:
bindkey -v
,bindkey -e
C-t
交换光标所在字符与其前的字符M-t
交换光标所在的单词与前面单词的位置C-m
相当于“回车键”
%s/重车,运营/运营,重车/g %s/,超速报警//g %s/,登录//g g/,设备工作正常/d g!/ACC/d
- “Unix 用起来容易,但学习起来难”。
@
Unix/Linux 操作系统的使用作为实践性非常强的一门“技术”,有章可循。每一个命令的命令格式、参数、选项都可以通过阅读手册获得,所以用起来很容易。
但它学习起来,并不是每天扫地的阿姨一眼就能轻松掌握的工具。如作者所言,“设计 Unix 的目的不是为了学习而是为了使用。”为了达到使用 Unix 这一工具的目的,我们需要了解其“然”,也就是基本操作:了解如何登陆 Unix、如何使用 Unix 编辑文件、操作目录……
其实就是说,Unix 就要用。不要“学”太深,因为设计者的设计并不完美(不可能)。
- Helpful aliases for common git tasks
@
g
→git
gst
→git status
gl
→git pull
gup
→git pull --rebase
gp
→git push
gd
→git diff
gdc
→git diff --cached
gdv
→git diff -w "$@" | view -
gc
→git commit -v
gcR
→git commit -v --amend
gca
→git commit -v -a
gcaR
→git commit -v -a --amend
gcmsg
→git commit -m
gco
→git checkout
gcm
→git checkout master
gr
→git remote
grv
→git remote -v
grmv
→git remote rename
grrm
→git remote remove
gsetr
→git remote set-url
grup
→git remote update
grbi
→git rebase -i
grbc
→git rebase --continue
grba
→git rebase --abort
gb
→git branch
gba
→git branch -a
gcount
→git shortlog -sn
gcl
→git config --list
gcp
→git cherry-pick
glg
→git log --stat --max-count=10
glgg
→git log --graph --max-count=10
glgga
→git log --graph --decorate --all
glo
→git log --oneline --decorate --color
glog
→git log --oneline --decorate --color --graph
gss
→git status -s
ga
→git add
gm
→git merge
grh
→git reset HEAD
grhh
→git reset HEAD --hard
gclean
→git reset --hard && git clean -dfx
gwc
→git whatchanged -p --abbrev-commit --pretty=medium
gsts
→git stash show --text
gsta
→git stash
gstp
→git stash pop
gstd
→git stash drop
ggpull
→git pull origin $(current_branch)
ggpur
→git pull --rebase origin $(current_branch)
ggpush
→git push origin $(current_branch)
ggpnp
→git pull origin $(current_branch) && git push origin $(current_branch)
glp
→git log prettily
- Python notes
@
- 表面上看,tuple 的元素确实变了,但其实变的不是 tuple 的元素,而是 list 的元素。
- list 和 tuple 是 Python 内置的有序集合,一个可变,一个不可变。根据需要来选择使用它们。
if <条件判断1>: <执行1> elif <条件判断2>: <执行2> elif <条件判断3>: <执行3> else: <执行4>
birth = int(raw_input(birth: ))
要避免 key 不存在的错误,有两种办法,一是通过
in
判断key
是否存在:>>> Thomas in d >>> False
所以,对于不变对象来说,调用对象自身的任意方法,也不会改变该对象自身的内容。相反,这些方法会创建新的对象并返回,这样,就保证了不可变对象本身永远是不可变的。
要保证 hash 的正确性,作为 key 的对象就不能变。在 Python 中,字符串、整数等都是不可变的,因此,可以放心地作为 key。而 list 是可变的,就不能作为 key
int()
,float()
,str()
,bool()
原来返回值是一个 tuple!但是,在语法上,返回一个 tuple 可以省略括号,而多个变量可以同时接收一个 tuple,按位置赋给对应的值,所以,Python 的函数返回多值其实就是返回一个 tuple,但写起来更方便。
def power(x, n=2): s = 1 while n > 0: n = n - 1 s = s * x return s
默认参数必须指向不变对象!
def add_end(L=None):
为什么要设计
str
、None
这样的不变对象呢?因为不变对象一旦创建,对象内部的数据就不能修改,这样就减少了由于修改数据导致的错误。此外,由于对象不变,多任务环境下同时读取对象不需要加锁,同时读一点问题都没有。我们在编写程序时,如果可以设计一个不变对象,那就尽量设计成不变对象。- list:
[1, 2, 3]
- tuple:
(1, 2, 3)
定义可变参数和定义 list 或 tuple 参数相比,仅仅在参数前面加了一个
*
号。在函数内部,参数 numbers 接收到的是一个 tuple,因此,函数代码完全不变。但是,调用该函数时,可以传入任意个参数,包括 0 个参数def calc(*numbers): sum = 0 for n in numbers: sum = sum + n * n return sum nums = [1, 2, 3] calc(*nums) 14
>>> kw = {city: Beijing, job: Engineer} >>> person(Jack, 24, **kw) name: Jack age: 24 other: {city: Beijing, job: Engineer}
- 参数定义的顺序必须是:必选参数、默认参数、可变参数和关键字参数。
- args 是可变参数,args 接收的是一个 tuple;
**kw
是关键字参数,kw 接收的是一个 dict。
尾递归是指,在函数返回的时候,调用自身本身,并且,return 语句不能包含表达式。这样,编译器或者解释器就可以把尾递归做优化,使递归本身无论调用多少次,都只占用一个栈帧,不会出现栈溢出的情况。
>>> L[1:3] [Sarah, Tracy] for key in d: for value in d.itervalues(): for k, v in d.iteritems(): [x*x for x in range(1, 11)] isinstance(x, str) g = (x * x for x in range(10)) g.next()
- map, reduce
filter(function, list)
def not_empty(s): return s and s.strip() filter(not_empty, [A, , B, None, C, ]) # 结果: [A, B, C]
sorted([list], <function>)
- 高阶函数除了可以接受函数作为参数外,还可以把函数作为结果值返回。
In : def lazy_sum(*args): ...: def sum(): ...: ax = 0 ...: for n in args: ...: ax = ax + n ...: return ax ...: return sum ...: In : f = lazy_sum( 1, 2, 3, 4) In : f Out: <function __main__.sum> In : f() Out: 10
在这个例子中,我们在函数 lazy_sum 中又定义了函数 sum,并且,内部函数 sum 可以引用外部函数 lazy_sum 的参数和局部变量,当 lazy_sum 返回函数 sum 时,相关参数和变量都保存在返回的函数中,这种称为“闭包(Closure)”的程序结构拥有极大的威力。
lambda x: x*x
import functools int2 = functools.partial(int, base=2) int2('1000000')
注意到上面的新的 int2 函数,仅仅是把 base 参数重新设定默认值为 2,但也可以在函数调用时传入其他值:
int2("1000000", base=10)
请注意,每一个包目录下面都会有一个
__init__.py
的文件,这个文件是必须存在的,否则,Python 就把这个目录当成普通目录,而不是一个包。__init__.py
可以是空文件,也可以有 Python 代码,因为__init__.py
本身就是一个模块,而它的模块名就是 mycompanyif __name__ == '__main__': test()
try: import json # python >= 2.6 except ImportError: import simplejson as json # python <= 2.5
类似
__xxx__
这样的变量是特殊变量,可以被直接引用,但是有特殊用途,比如上面的__author__
,__name__
就是特殊变量,hello 模块定义的文档注释也可以用特殊变量__doc__
访问,我们自己的变量一般不要用这种变量名;类似
_xxx
和__xxx
这样的函数或变量就是非公开的(private),不应该被直接引用,比如_abc
,__abc
等;外部不需要引用的函数全部定义成 private,只有外部需要引用的函数才定义为 public。
from __future__ import division
, use python3.x in python2.xclass Student(object): def __init__(self, name, score): self.name = name self.score = score In : class Me(object): ....: def __init__(this): ....: this.name = "shit" this.__private_var, this.__not_private_var__, this._not_private_but_dont_touch_me_please class Dog(Animal): pass instanceof (dog, Dog) instanceof (dog, Animal) # true def run_twice(animal): animal.run() animal.run()
对于一个变量,我们只需要知道它是 Animal 类型,无需确切地知道它的子类型,就可以放心地调用
run()
方法,而具体调用的run()
方法是作用在 Animal、Dog、Cat 还是 Tortoise 对象上,由运行时该对象的确切类型决定,这就是多态真正的威力:调用方只管调用,不管细节,而当我们新增一种 Animal 的子类时,只要确保run()
方法编写正确,不用管原来的代码是如何调用的。这就是著名的“开闭”原则:- 对扩展开放:允许新增 Animal 子类;
- 对修改封闭:不需要修改依赖 Animal 类型的
run_twice()
等函数。
type(123), type("string") >>> import types __slots__ = (name, gender) class Student(object): def get_score(self): return self._score def set_score(self, value): if not isinstance(value, int): raise ValueError('score must be an integer!') if value < 0 or value > 100: raise ValueError('score must between 0 ~ 100!') self._score = value >>> s.score = 60 # OK,实际转化为s.set_score(60)
@score.setter
@property
的实现比较复杂,我们先考察如何使用。把一个 getter 方法变成属性,只需要加上@property
就可以了,此时,@property
本身又创建了另一个装饰器@score.setter
,负责把一个 setter 方法变成属性赋值,于是,我们就拥有一个可控的属性操作
class Student(object): @property def birth(self): return self._birth @birth.setter def birth(self, value): self._birth = value @property def age(self): return 2014 - self._birth
由于 Python 允许使用多重继承,因此,Mixin 就是一种常见的设计。只允许单一继承的语言(如 Java)不能使用 Mixin 的设计。
- Mixin
__str__()
,print(Student("Michael"))
__repr__ = __str__
__iter__
__getitem__
,s = Student()
,s
__getattr__
当调用不存在的属性时,比如 score,Python 解释器会试图调用
__getattr__(self, score)
来尝试获得属性__call__
,s = Student()
,s()
import types type(u'abc')==types.UnicodeType isinstance(a, (str, unicode)) # string or unicode
如果要获得一个对象的所有属性和方法,可以使用
dir()
函数,它返回一个包含字符串的 list,比如,获得一个 str 对象的所有属性和方法:dir(Dog)
getattr()
,setattr()
,hasattr()
hasattr(Dog, "__init__")
callable(Student())
# true__getattr__
type()
函数可以查看一个类型或变量的类型,Hello 是一个 class,它的类型就是 type,而 h 是一个实例,它的类型就是class Hello
。type()
to create class,__metaclass__ = <Class>
try... except ...finally
.
第二个 except 永远也捕获不到 ValueError,因为 ValueError 是 StandardError 的子类,如果有,也被第一个 except 给捕获了。
也就是说,不需要在每个可能出错的地方去捕获错误,只要在合适的层次去捕获错误就可以了。这样一来,就大大减少了写
try...except...finally
的麻烦。import logging # log error and run, with error
虽然用 IDE 调试起来比较方便,但是最后你会发现,logging 才是终极武器。
如果你听说过“测试驱动开发”(TDD:Test-Driven Development),单元测试就不陌生。
d = dict(a=1,b=2) d = dict({"a":1,"b":2}) raise FooError("invalid value: %s" % s) assert n != 0, "n is zero" logging, logging.info("n =%d" %n) import logging logging.basicConfig(level=logging.INFO) python -m pdb err.py pdb.set_trace() import pdb file-like object, `StringIO` <mode>=rb, f.read().decode("gbk") import codecs import os os.name os.path.abspath(".") os.getenv("PATH") os.path.split("url....") # dirname, basename import shutil split extension: os.path.splitext(str)==".py"
我们把变量从内存中变成可存储或传输的过程称之为序列化,在 Python 中叫 pickling,在其他语言中也被称之为 serialization,marshalling(集结待发的), flattening 等等,都是一个意思。
try: import cPickle as pickle except ImportError: import pickle
python 语言特定的序列化模块是 pickle,但如果要把序列化搞得更通用、更符合 Web 标准,就可以使用 json 模块。
json 模块的
dumps()
和loads()
函数是定义得非常好的接口的典范。当我们使用时,只需要传入一个必须的参数。但是,当默认的序列化或反序列机制不满足我们的要求时,我们又可以传入更多的参数来定制序列化或反序列化的规则,既做到了接口简单易用,又做到了充分的扩展性和灵活性。如果要启动大量的子进程,可以用进程池(pool)的方式批量创建子进程在 Unix/Linux 下,可以使用 fork() 调用实现多进程。要实现跨平台的多进程,可以使用 multiprocessing 模块。
进程间通信是通过 Queue、Pipes 等实现的。当多个线程同时执行
lock.acquire()
时,只有一个线程能成功地获取锁,然后继续执行代码,其他线程就继续等待直到获得锁为止。获得锁的线程用完后一定要释放锁,否则那些苦苦等待锁的线程将永远等待下去,成为死线程。所以我们用try…finally来确保锁一定会被释放。
import threading
# 创建全局 ThreadLocal 对象: local_school = threading.local() import re s = r'ABC\-001' # Python的字符串 In : if re.match(r'^/d{3}\-\d{3,8}$', '010-12345'): ....: print 'ok' ....: In : >>> re.split(r'\s+', 'a b c') ['a', 'b', 'c'] >>> re.split(r'[\s\,]+', 'a,b, c d') ['a', 'b', 'c', 'd'] >>> m = re.match(r'^(\d{3})-(\d{3,8})$', '010-12345') >>> m <_sre.SRE_Match object at 0x1026fb3e8> >>> m.group(0) '010-12345' >>> m.group(1) '010' >>> m.group(2) '12345'
- 贪婪匹配
>>> re.match(r'^(\d+)(0*)$', '102300').groups() ('102300', '')
- 非贪婪匹配
>>> re.match(r'^(\d+?)(0*)$', '102300').groups() ('1023', '00') # 编译: >>> re_telephone = re.compile(r'^(\d{3})-(\d{3,8})$') # 使用: >>> re_telephone.match('010-12345').groups() # ('010', '12345')
Python 之所以自称“batteries included”,就是因为内置了许多非常有用的模块,无需额外安装和配置,即可直接使用。
- modules
from collections import namedtuple from collections import deque q = deque(["a", "b", "c"]) q.append("x") q.appendleft("y") q append(), pop(), appendleft(), popleft() from collections import defaultdict from collections import OrderdDict from collections import counter %Base64 >>> n = 10240099 >>> b1 = chr((n & 0xff000000) >> 24) >>> b2 = chr((n & 0xff0000) >> 16) >>> b3 = chr((n & 0xff00) >> 8) >>> b4 = chr(n & 0xff) >>> s = b1 + b2 + b3 + b4 >>> s '