0%

  吾实乃庸人,于理虽觉明晰通达,于情却犹豫不畅。

  独处之时意淫幻想,骤然临之慌乱畏惧不前。平生如遇佳人则豫惧无措,欲与之亲近而不得。而后偶一回想,怅然颓首而无所解。如此于人于己有何益处,空留念想,只招惆怅而已。

  呜呼,面皮之为物当得了几两干饭,胆气之所缺非得几斤豹胆所能解。

  为文以纪,聊为自勉,愿余能一扫前非。

  人事皆非己见,人心不堪洞见。

  既不若向之所求,何须用心添烦恼。

  不谏已悟,来者可追。

  当效拂袖,心役即脱。

  这世界上这么多纷争与烦恼,很大一部分都是因为人与人之间不能相互理解,他人为敌国、以邻为壑等等层出不穷。之所以不能理解,是因为同一个东西,对于不同的人(或者不同时间或空间的同一个人),价值是全然不同的。

  可能你认为重于生命的东西,于他人不过徒增笑谈尔。比如信教者的斋戒等行为,对无神论者来说是多余的,而对信徒来说却是可能比生命更重要。
  
  又如,你还在大学的时候,这时的时间对你来说十分廉价,所以你愿意去发8元每小时的宣传单;等你事业有成或是垂垂老矣,你还愿意花这一小时去干这个吗,也许只会感叹自己当时太年轻吧。一个人尚且不能理解年轻时的自己,又怎能奢望他理解别人呢?
  
  真正的相互理解是要认同他人对事物价值的判定,但一个事物对他们的价值有天壤之别,这样你叫他们如何相互理解呢?

  那么怎么解决这种情况呢?也就是怎么寻找一种相对普适的价值衡量方法呢?
  
  我的一个浅薄的思路是,衡量一个事物的价值可以通过这个人的付出相对自身的稀缺性,这种付出包括物资的付出和精神上承受的压力。
  
  比如说,一个乞丐付出了仅有的100元买了个表,和一个百万富豪付出1000元买了个表。对乞丐来说这表是全部,而对富豪来说表是1/1000。因此乞丐对表爱护有加,富豪对表弃之如弊履,就完全可以理解了。也可以说乞丐的表价值大于富豪的表。
  
  虽然绝对价值不可判定,并且造成很多纷争。但是,同一件事对不同的人价值不同也不是全然没有好处,至少在市场经济里,你们完全可以交换这些东西嘛。

  要之,于娑婆世界中,众生皆苦,要以事物相对他人的稀缺性来看他人的付出与承受,如此理解他人才成为可能。

背景

在linux服务器上工作,常常和rm打交道,难免手滑删除了重要的东西。而且linux又没有回收站功能,一旦删错东西真是欲哭无泪。别问我为什么知道,说多了都是泪。
主要思路是用mv命令代替rm,将要删除的东西移动到回收站目录。

方案

新建删除到回收站脚本

mkdir ~/bin

vim ~/bin/trash # 将下面的内容写入

1
mv -v $@ ${trash_bin}

chmod +x ~/bin/trash # 增加执行权限

登录时初始化回收站

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 将以下内容追加到"~/.bashrc"中,回收站是以每天的日期新建文件夹

today=$(date "+%Y%m%d") # 形如20160606格式的日期

trash_bin="/tmp/trash/${today}"

if [ ! -d "/tmp/trash" ]; then
mkdir "/tmp/trash"
fi

if [ ! -d ${trash_bin} ]; then
mkdir ${trash_bin}
fi

export trash_bin # 加入环境变量

alias rm="~/bin/trash"

概述

文如其名,是由91篇关系不是很紧密的python文章集合而成
这本书和国内很多技术类书籍一样,排版的代码缩进很有问题,还有文章有些观点并不正确。

除此之外,还是有很多有用的知识点,需要读者自己辨别。

笔记

Python的包和模块规范

结构日益规范化。现在的库或框架跟随了以下潮流:

  • 包和模块的命名采用小写、单数形式,而且短小。
  • 包通常仅作为命名空间,如只包含空的__init__.py文件。

x, y=y, x赋值

Python表达式计算的顺序说起。

一般情况下Python表达式的计算顺序是从左到右,但遇到表达式赋值的时候表达式右边的操作数先于左边的操作数计算,因此表达式expr3, expr4=exprl, expr2的计算顺序是exprl, expr2 —> expr3, expr4

因此对于表达式x, y=y, x,其在内存中执行的顺序如下:

  1. 先计算右边的表达式y,x,因此先在内存中创建元组(y,x),其标示符和值分别为y、x及其对应的值,其中y和x是在初始化时已经存在于内存中的对象。
  2. 计算表达式左边的值并进行赋值,元组被依次分配给左边的标示符,通过解压缩(unpacking),元组第一标识符(为y)分配给左边第一个元素(此时为X),元组第二个标识符(为x)分配给第二个元素(此时为y),从而达到x、y值交换的目的。

提高and、or表达式的效率

python的and、or表达式并不会将每个值都算出,一旦整个表达式的值已知,其他部分就不会被计算,并且返回最后计算的那个值。
因此,在编程过程中,如果对于or条件表达式应该将值为真可能性较高的变量写在or的前面;
而对于and则相反,应该推后。

阅读全文 »

四念处观

  1. 身体的观察——身随念处
  2. 心情、感觉的观察——受随念处
  3. 内心的观察——心随念处
  4. 法则的观察——法随念处

欲望和干劲是两回事,干劲反而因为欲望的压力而消耗。

博主云:你的欲望和使欲望满足的方法往往是两个东西,所以欲望越多,越不知道该干什么。欲望想要的是一件事的结果,而我们能做的却仅仅是每一个具体的过程。

难以抉择会给心灵带来极大负担。

博主云:人在一段时间内的自制力是有限的,一个选择在内心停留越久,对自制力就越大损耗,自制力耗尽就表现为什么都不想做。

欲望最原生的材料就是压力,即是苦,所以说将我们驱逐至欲望的正是(痛)苦。

一直待在痛苦的世界是不好的。

我们的欲望并不是自己的欲望,它是你前一段时间所有行为对当下心灵的残留影响。

往往看起来高尚伟大的“xxx主义”,大致上总说着一些漂亮的场面话,实际上只是执着于想要增加自己所属团体的利益。

觉得快乐并不是什么坏事,但是这往往会导致想要追求更多的快乐,就是扩大欲望。

博主云:因快乐而生欲望,因欲望而生执着,因执着而造业。

阅读全文 »

  有些人以为生活只有诗与远方,后来他离开了生活。
  
  有些人以为生活只是眼前的苟且,后来他失去了自我。

  人生在世,无论理想如何远大,终须为稻粱谋。陶渊明不为五斗米折腰,前提没这点俸禄也不至于饿死。若是形式迫人,虽嗟来之食亦受之。一旦不为生计发愁,迎接你的必是诗与远方。故我先欲求之财务自由,后践吾心之所向。

  不够强大的理想主义者,一大部分矮化成了现实主义者,另一部分成了随波逐流的躯壳,余下的抛弃了这个娑婆世界。
  
  而我,先欲求安身立命之所,后追寻最初的梦想,希望能走得更远。

  对于初学者来说,python的类变量(也就是java中的静态变量)和实例变量(也就是属性)有一些很容易混淆的地方,同时对这些特性深入了解有助于理解python的面向对象思想。

类变量与实例变量区分

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
>>> class ClassA(object):  # 1
... num1 = 1 # 类变量
... def __init__(self):
... self.num2 = 2 # 实例变量,或者说属性

>>> a1 = ClassA()
>>> a1.num1
1
>>> ClassA.num1
1
>>> a1.num1 is ClassA.num1 # 2
True

>>> a1.num1 = 3
>>> a1.num1 is ClassA.num1 # 3
False

>>> a1.__class__.num1
1
>>> a1.__class__.num1 = 4 # 4
>>> ClassA.num1
4

>>> a2 = ClassA()
>>> a2.num1
4
  1. 这里我们定义了ClassA类,它有一个类变量num1,还有一个实例变量num2
  2. a1是ClassA的一个实例,当我们写下a1.num1的时候,实际上是引用类变量num1,因此a1.num1 is ClassA.num1值为True
  3. 运行a1.num1 = 3的时候,其实给a1绑定了一个属性num1,这是动态语言的特性,此时a1.num1 is ClassA.num1值为False
    因此我不建议通过实例的名称来引用类变量,这样容易引起混淆,你以为改变了ClassA.num1,其实没有。
    这里就扯到了Python的作用域与命名空间,运行a1.num1的时候,先是在a1自己的命名空间内查找num1,没找到就在所属类的命名空间找,还没有就抛出AttributeError: 'ClassA' object has no attribute 'num3'.
    运行a1.num1 = 3之后,a1自己的命名空间内找到了num1,就不继续往上查找了。
  4. 如果此时还想通过a1访问和改变类变量num1,可以通过a1.__class__.num1来访问。

以上这些,也适用于staticmethodclassmethod

如果ClassA还有父类

阅读全文 »

占座党乃图书馆通病

  凡是条件好一点的图书馆,只要工作人员不禁止,必定有一部分座位因占座党而闲置。
  
  举我最近去的广州图书馆为例,我早上9点开始自习,到下午5点,占座的人始终没来,而且不是一两次。几乎每次有占座的,很大可能一天都不来。
  
  这也很好理解,既然需要占座自然是来的意愿不是很强,不来自然是情理之中。人皆有惰性,无可厚非,但座位有限,还是留给需要的人为好。

在图书馆玩手机很畅快

  除占座党之外,手机党和电脑党也是图书馆一大特色,并且与年龄无关。
  
  今天坐我对面的是个大概60岁的大爷,先是早上来没找到位置坐,把我对面的占座党呵斥了一通,抢了她占的座位。然后等我下午从图书馆出来时,他手上拿的手机还没有放下。既然玩手机,在家里不是更舒服吗,何必呢?学得下就学,不行就回去休息,在这磨洋工除了求个心安之外毫无裨益。
  
  另外,品行、习惯与年龄没多大关系,不好的不改正,年纪大了还是不好,不过是习惯了而已。俗语说三岁看老,未免夸张了点,十三、二十三看老估计是十拿九稳。
  
  人呐,还是要对自己有所要求,若是随着年岁的增长而没有丝毫长进,多么可悲,多么可怕。年少时不学好有人教育你,年老了还无长进,无需教育也无人可教育你了。

免费的终究会被滥用

  在卫生间,洗完手,有一人擦手用了接近2米的纸,很大一堆,不知道什么心态。如果你平时在家都是这样使用,我无话可说,但仅因为免费就滥用,未免太下作了。
  
  免费的东西并不是没有成本,而是一些心存善念的人承担了,因此我们在使用它的时候因心存感激。
  
  一切免费的物品,如图书馆的座位,如纸巾,如果不能在使用价值或者获取代价上和通常物品加以区分,就不免会被滥用,导致真正需要的人不能得到。
  
  而这正是这个世界的可悲之处,所有事物并不是让需要的人得到,而是让有取得优势的人得到。

概述

re是python中的正则表达式处理模块,本文是为了总结re模块的用法。

至于正则表达式的写法可以看正则表达式30分钟入门教程

用法

re.compile

re.complie(pattern, flags=0)
把正则编译为_sre.SRE_Pattern object对象,在多次匹配的时候可提高运行效率。

1
2
3
4
5
6
7
8
9
>>> pattern = re.compile(r'\w(o)')
>>> pattern.match('doooo')
<_sre.SRE_Match object at 0x7f45fc3d9990>
>>> pattern.match('doooo').group(1)
'o'
>>> re.match(r'\w(o)', 'doooo')
<_sre.SRE_Match object at 0x7f45ec0be0a8>
>>> re.match(r'\w(o)', 'doooo').group(1)
'o'

阅读全文 »

概述

顾名思义,所谓装饰器就是对原有的对象做一些装饰,也就是给已有的对象添加一些功能。

假如我现在想在函数运行时输出一些信息

小学水平

1
2
3
4
5
6
7
8
9
def running(func):
print '`%s` is running...' % func.__name__
return func

@running
def my_sum():
return "I cat't sum right now!"

print my_sum()

输出

1
2
`my_sum` is running...
I cat't sum right now!

要使用装饰器,先得定义一个装饰器函数,然后在需要装饰的函数的前一行使用@符号加上装饰器名称
在这里的效果等效于running(my_sum)(),不过看起来有点别扭。
注意:一旦通过@running装饰了函数,不管被装饰函数是否运行,python解释器都会执行一遍running函数。

中学水平

上一个装饰器用起来还行,但是有一个致命的问题,它不能装饰带参数的函数。所以我们在装饰器内部定义_wrapper函数,并返回它。这个函数接收所有位置参数*args,和关键字参数*kwargs,在_wrapper内部执行func(*args, **kwargs)

阅读全文 »

例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
taskman
├── db.sqlite3
├── manage.py
├── task
│   ├── __init__.py
│   ├── admin.py
│   ├── models.py
│   ├── urls.py
│   └── views.py
└── man
├── __init__.py
├── settings.py
├── urls.py
└── wsgi.py

说明

上面的例子是一个Django项目,Python包的导入都是相对于主程序来说的。
这个项目的主程序就是manage.py,跟manage.py同级的文件夹(含有__init__.py)如task,man就称之为包,若同级有文件就称之为顶级模块。
在这个项目里所有Python包的导入,都应该写完整路径。

例如在文件/taskman/task/views.py中,想要导入/taskman/man/setting.py,就得这样。

1
2
3
from man.setting import some_setting
# or
from man import setting

记住:

  1. 所有导入都是根据主程序的路径,然后从完整路径导入包
  2. 主程序应该位于包的最顶层,否则发生ValueError: Attempted relative import in non-package

原理

由于在Python2中字符串有两种类型strunicode,他们都是basestring的子类。

str类型,即是ascii字符或者经过encode的unicode,一个字符占用1byte。ascii码是美国信息交换标准代码,主要用于显示现代英语和其他西欧语言,用一个字节储存一个字符,所以ascii字符最多只有256(2^8)个。

而unicode包含了256个ascii码之外还包含其他各个国家的文字的编码,所以unicode的一个字符占用2个字节,这样理论上一共最多可以表示2^16(即65536)个字符,远大于256。

utf-8是unicode的一中实现,是unicode的一种编码方式。而且utf-8的编码方式,包含了ascii码的内容,也就是utf-8兼容ascii。

打个比方,unicode是商品,utf-8就是打包好的一个个包裹(encode),打包是为了传输和储存的方便。而不同的编码之间不能直接互相转换,都需要转成unicode,也就是decode。

所以碰到一个str,你就得明白它是encode过的,你得调用相应的decode方法才不会乱码。

python2解释器的默认编码方式是ascii,如果我们给系统的输入是非ascii编码的字符,系统在尝试解码时就会出现UnicodeDecodeError

1
2
3
4
5
6
7
8
9
10
11
12
13
14
>>> s = '2'
>>> u = u'2'
>>> type(s)
<type 'str'>
>>> type(u)
<type 'unicode'>
>>> issubclass(str,basestring)
>>> issubclass(unicode,basestring)
True
>>> '啊'.decode('ascii')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe5 in position 0: ordinal not in range(128)
'ascii' codec can't decode byte 0xe5 in position 0: ordinal not in range(128)

几种解决方法

阅读全文 »

以vmware虚拟机为例

设置IP

运行 sudo nano /etc/network/interfaces
将文件修改成如下:

1
2
3
4
5
auto eth0  # eth0是网卡名称,你的不一定是这个,可通过ifconfig查看
iface eth0 inet static
address 192.168.157.129 # 地址
gateway 192.168.157.2 # 网关
netmask 255.255.255.0 # 掩码

修改DNS

运行 sudo nano /etc/resolvconf/resolv.conf.d/base
把文件改成 nameserver 192.168.157.2
192.168.157.2改成你需要的dns,这里因为是vmware的NAT模式,所以dns和网关是一样的。

概述

如果一个在函数中存在yield关键字,那么这个函数就构成了生成器。生成器是一个函数,它生成一个序列,以便在迭代中使用。
调用这个函数,并不会马上开始执行函数体中的代码,而是返回一个生成器对象,通过调用生成器对象的next()方法(python3中是__netx__())执行函数。

那么,具体的函数中语句的执行顺序是怎么样的呢?

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def func(x=10):
print 'the beginning of function'
if x <= 0 or not isinstance(x, int):
return
for i in range(x):
print 'before yield', i
yield i
print 'after yield', i

gen = func(2)
print '*'*20
print '-> yielding: %s' % gen.next()
print '*'*20
print '-> yielding: %s' % gen.next()
print '*'*20
print '-> yielding: %s' % gen.next()

输出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
********************
the beginning of function
before yield 0
-> yielding: 0
********************
after yield 0
before yield 1
-> yielding: 1
********************
after yield 1
Traceback (most recent call last):
File "D:\Projects\test.py", line 28, in <module>
print '-> yielding: %s' % gen.next()
StopIteration

分析

  1. 首先运行func(2),这时函数的所有语句都没有执行,返回一个生成器赋值给gen
  2. 第一次执行gen.next(),函数从头开始执行,运行完yield语句暂停住了。
  3. 再次运行gen.next(),从停下的地方继续,直到遇到遇到下一个yield,运行完yield语句又暂停住了。
  4. 第三次尝试运行gen.next(),运行完print 'after yield', i,由于循环次数已满,找不到下一个yield,就出现StopIteration错误