在 Python 中,普通列表可以使用 set()
来进行去重,这是使用了集合的唯一性,把列表转换为集合之后保证没有重复的元素,然后再使用 list()
把集合转换为列表。但这种方法并不保证元素之间的顺序,而且如果原列表之中含有不能被 hash 的元素(如字典、集合之类),原列表更无法转换为集合类型。
这种情况下应该保持列表的类型,使用 lambda 表达式进行去重:
1 | import functools.reduce |
这个时候列表 lst 就是 [2, 3, 1] 了。
在 Python 中,普通列表可以使用 set()
来进行去重,这是使用了集合的唯一性,把列表转换为集合之后保证没有重复的元素,然后再使用 list()
把集合转换为列表。但这种方法并不保证元素之间的顺序,而且如果原列表之中含有不能被 hash 的元素(如字典、集合之类),原列表更无法转换为集合类型。
这种情况下应该保持列表的类型,使用 lambda 表达式进行去重:
1 | import functools.reduce |
这个时候列表 lst 就是 [2, 3, 1] 了。
1 | with open('file_name') as f: |
能够使用 with 语句块的条件是 with 所求值的对象必须有一个 __enter__()
方法,一个 __exit__()
方法。
而紧跟在 with 关键字后面的语句被求值后,返回对象的 __enter__()
方法被调用,这个方法的返回值将被赋值给 as
后面的变量。当 with 语句块中的全部语句被执行完之后,将调用前面返回对象的 __exit__()
方法。
对于读写文件来说,使用 with 语句块一般较为保险。在读文件时,如果使用了 with 语句块,在代码块结束后,由于自动执行了 __exit__()
方法,因此不需要手动使用 close()
方法来关闭被读的文件;当写文件时,操作系统往往不会立刻把数据写入磁盘,而是放到内存中缓存起来,空闲的时候再进行写入,只有调用 close()
方法时,操作系统才保证把没有写入的数据全部写入磁盘,忘记调用 close()
的后果是数据可能只写了一部分到磁盘,剩下的丢失了,而使用 with语句块就有效避免了这个问题。
在 Python 中声明一个类的时候,如果这个类继承 object
类,这个类就是新式类;如果这个类没有继承任何类,这个类就是经典类。
1 | # 声明一个新式类 |
Python 的新式类已经兼容经典类,而且新式类已经解决了经典类中关于多继承的缺陷,因此在 Python 中推荐使用新式类。
1 | class A: |
B、C 是 A 的子类,D 多继承了 B、C 两个类,其中 C 重写了 A 中的 foo()
方法。
如果 A 是经典类,当调用 D 的实例的 foo()
方法时,Python 会按照深度优先的方法去搜索 foo()
,路径是 B-A-C ,执行的是 A 中的 foo()
;
如果 A 是新式类,当调用 D 的实例的 foo()
方法时,Python 会按照广度优先的方法去搜索 foo()
,路径是 B-C-A ,执行的是 C 中的 foo()
。
因为 D 是直接继承 C 的,从逻辑上说,执行 C 中的 foo()
更加合理,因此新式类对多继承的处理更为合乎逻辑。
在 Python 3.x 中的新式类已经兼容了经典类,无论 A 是否继承 object
类, D 实例中的 foo()
都会执行 C 中的 foo()
。但是在 Python 2.7 中这种差异仍然存在,因此还是推荐使用新式类,要继承 object
类。
在中文 Windows 系统中,文件的默认字符编码为 GBK,如果将一段编码为 UTF-8 的数据流在 Windows 下写入文件,就可能会解析失败并抛出 UnicodeEncodeError 异常。
解决方案是在打开要写入的文件时在 encoding
参数中指定数据流的编码,这样就能在先从数据流的编码转换为目的编码,然后写入文件。
1 | f = open('something.txt', 'w', encoding='utf-8') |
对于一些编码不规范的文件,在读取是可能会遇到 UnicodeDecodeError 异常,因为在文件中有可能夹杂了一些非法编码的字符。这种情况下 open()
可以接受一个 errors
参数,来指定如果遇到编码错误时应该如何处理。这个参数有两个枚举值,分别是 strict
和 ignore
,前者在遇到异常的时候直接抛出异常并退出,后者为直接忽略。
1 | f = open('something.txt', 'w', encoding='utf-8', errors='ignore') |
在使用公有云的时候,可能会受到大量的扫描,其中大部分都是对常用用户(例如 root)的口令暴力猜测。虽说使用由各种字母、数字、符号混杂的口令能够大大提高安全性,但登录后看到那几万个 failed logins 总是有点碍眼。把 ssh 的端口从 22 改成其它不常见的端口也算是一个方法,但始终是治标不治本,毕竟这只能防一防那些随意乱扫的人,对于指定要 hack 某一台主机的,总能找到开放的 ssh 端口。
从另一个角度来说,在自己反复连接远程主机的时候,每次都需要重新输入口令,也是一键比较烦的事情。
使用 sshkey 来免口令 ssh 就可以避免以上两个问题。即使把 ssh 端口保持在 22,只要 sshkey 不符合,直接就拒绝连接了。同时,在ssh key 符合的情况下,能够不需要输入口令秒连接。
首先在本地 ssh-keygen -t rsa 生成密钥,就会在 ~/.ssh
目录下生成 id_rsa
和 id_rsa.pub
两个文件,分别是私钥和公钥。私钥是自己本地保存的,而公钥是可以公开分发的,因此将公钥文件 id_rsa.pub
通过能想到的各种方法放置到远程主机的 ~/.ssh
下,并执行 cat id_rsa.pub >> authorized_keys
追加写入,这样就相当于让远程主机认识到本地主机,可以免口令登录了。
然后修改 ssh 服务的配置文件 /etc/ssh/sshd_config
,把 PasswordAuthentication
字段的值改为 no
,并重启 ssh 服务,就把 ssh 口令登录禁用了。