鹰鸽博弈

奇怪的人类

曾经住在一个老破小的小区里,很长一段时间。
因为老破小的原因,车位短缺,停车就成了一个问题,甚是拥挤。为了管理方便,物业在小区内部设定了一条只能单行的线路。
有一次开车出门,在距离单行线出口约 10 米处,一辆车逆行而来,我想当然地在对方先退出去,除了逆行之外,而且对方倒车的空间很大。
匪夷所思的是,对面车下来一个令人不喜的气息非常浓烈的妇女,气势汹汹地说道:都是开车的,就不能互相让一下吗?!
呃?什么操作?
花了几秒钟时间,忍了忍,然后,我让步,开始倒车。

几乎所有小孩都会被教育去成为美好的人类,他们会长大,成为未来社会人类的主要组成部分。即便如此,在可预见的时间里,社会中人与人的交错,到了未来,也总会大量发生如上匪夷所思的现象吧,说着有道理的话,做着想不到的事
从生物族群上看,人类必然有利他性的基因,不然发展不到现在的局面。

上面这个事例或许不够显著,后来,寻到另一个极端例子,就更容易接受这个无理的现象了。
例子是这样的: AB 是好友,A 突然动手要杀死 B,然后 B 防住了,并表示难以置信,A 原有的愧疚立马消失,认为自己的杀心是正确的,明显 B 早已提防他了,毕竟 B 防住了不是?

存在即合理,在这个层面上,是能接受社会上一些糟糕现实的,虽然有些恶心,倒不至于感到困惑。
真正让我感到困惑的是: 如果成为糟糕的人类,可以获得额外收益,那么,我要不要成为糟糕的人?那么,未来的社会从长期来看,不就遍地恶人了吗?

鹰鸽博弈

博弈论中,有一个经典的鹰鸽博弈(Hawk Dove Game),有各种演变,但基本的逻辑是 双方相遇时,采取的策略分为 或者 ,那么两两交错,就有 鸽鸽 (双赢)、鹰鹰(胜者为王)、鹰鸽 (谁鹰谁赢) 三种情况。
只要从宏观角度去考虑,我们会非常清楚,这种博弈的结果,会达到一定的动态均衡。但这个结果,于我而言,不够释疑。
宏观来看,不管我们个体做什么选择,总体总是趋向于平衡的。而微观来看,于我们个体而言,但凡开始思考这个问题了,其实就拥有了一定自我改变的选择权。
如果做坏人的好处是明显的,我们要如何说服自己做个好人呢?

坏人看的多了,怀疑也就更多了。
如果我们可以在这个博弈的基础上,模拟整个社会中所有人类的遭遇战,就能理解这个社会的进化、演变。
如果明显好人收益更高,那么就可以多吃点亏;如果明显好人收益垫底,那就听从先天道德的教育,随着生命的拉长,心灵逐渐腐化,真哪天变成了自己不想见的『坏人』,也坦然处之,别有太大的负担。

鹰鸽博弈就像一道光,或许可以消解我们对人类根子里抱有的怀疑。

我们来看代码吧!

啊,怎么回事?!
我好像想不到更好的办法来介绍 Python 了。
难道要老生常谈去介绍 Python 的历史?好像没有什么必要,有兴趣搜索引擎上找一下,没有兴趣不了解也不影响这门编程语言的使用;而且似乎也没有必要 print("hello world") 这种作为开篇。
不如把 鹰鸽博弈 作为一个案例,代码化;然后,我们作为一名新手,在 即使从未写过代码 的基础上,尝试去理解代码本身的逻辑。
或许,你会发现,所谓的代码,其实就像一篇有严格逻辑性的文章一般,并不复杂。

当然,最好的前提,你应该通读过《FirstWeb》,起码已经知道了 函数变量变量空间 这些基本的概念。

强调再强调!

因为是 学习,特别还是基础性学习,有朋友可能会尝试去 深刻记住,极端的说法,就是背书,着实没有这个必要。
在接下来 读代码 的过程中,必须要强调: 只要去就可以了,能读懂,甚至只有局部能懂,也是足够的。
把代码当做一本另类的小故事进行阅读,大概看明白就可以了。至于之后能否复述整个故事,并不重要。甚至连主角的人名都没有记住,也没有关系呀。

如果真的觉得枯燥、晦涩,那么跳着看,也是可以的。

Python 基本语法

有些同学看到代码时,没有办法做到『不求甚解』,一定想要理解代码的意思。
强迫症也是好事情,我们还是先对 Python 的基本语法做简单的介绍

  • Python 用缩进方式来对齐,以表达代码的结构
  • 变量的名称可以由英文、数字、下划线组成,但是不能以数字开头
  • 大小写是敏感的,比如 Var 和 var 是两个不同变量名
  • 注意一些标点符号,比如引号、逗号、括号、中括号这些在代码结构中出现的全部要英文,不然语法错误
  • 写代码是有风格的,主要一方面是变量名的风格,一般普通变量 lower_word, 定义 class 的名称则类似 ThisIsClass
  • 理解 class、function 的定义语法
  • if elif else、and or 是条件判断,就如字面的意思
  • for + in,是循环,也如字面的意思
  • while + 具体条件,是另外一种循环,但要注意某时条件不符合了完成并跳出整个循环,避免死循环
  • : 这个标点符号的使用,在条件判断、循环、函数定义、类定义中都会出现,表示下一行开始还有内容
  • :不一定都会产生两行以上内容,简单的如 if True: my_var = 12 这种写成仅一行还是两行,效果一样
  • a += b 相当于 a = a+b,比如 a +=1, 加减乘除都可以于 = 连用
  • import 的出现,是 module 被导入了,module 是『复用』其它 Python 代码的表现

我们呈现一个 函数 (function) 的定义,但是要注意,里面出现的中文实际要换成英文

def a_function(1, 2=一个默认值, *其它不指定名字的变量们, **其它指定名称的变量们):
    if isinstance(1, int):  # 如果 变1 是整数
        1 += 1  # 叠加 1
    else:
        1 = 0  # reset
    for v in 其它不指定名字的变量们: # 循环,可把 『其它不指定名字的变量们』 当一个列表
        print(v)
    for key, value in 其它指定名称的变量们.items(): # 有名,有值
        print(key, value)

我们呈现一个 (class) 的定义,但是要注意,里面出现的中文实际要换成英文

class TheClass(object):
    def __init__(self, 变量1, 变量2=一个默认值)
        # 以 # 开头的一行,是 Python 中的注释内容,不是实际的代码
        # __init__ 相当于初始化时候的处理
        self.v1 = 变量1
        self.v2 = 变量2
        # self 就是代表自身,Class(类) 相当于一个 『整理用的房间』
        # 『房间』内有很多其它组成部分,这些『部分』可以用 self 来获得整个房间的所有内容
    def other_function(self):
        # 一般,Class 内的子函数的第一个变量都是 self
        pass
    def other_function_2(self, 必须的某变量):
        if 必须的某变量:
            这么处理
        elif not 必须的某变量 and 今天天气很好:
            那么处理
        else:
            不处理

我们处理一个异常的逻辑,但是要注意,里面出现的中文实际要换成英文

try:
    运行了一个函数
except NameError as error:  # 这是一种错误类型
    这么处理,可以调用其它函数
except ZeroDivisionError as error: # 如果是另外的错误类型
    另外的处理逻辑
finally:
    不管有没有错误,都要这么处理

或者还有这种方式:

try: 运行了一个函数
except: pass  # 出错了,啥也不管