重读《黔之驴》

今天计划做点无聊的事。突然想起柳宗元的《黔之驴》。原文如下:

黔無驢,有好事者,船載以入;至則無可用,放之山下。虎見之,龐然大物也,以為神。蔽林間窺之,稍出近之,憖憖然莫相知。他日,驢一鳴,虎大駭遠遁,以為且噬已也,甚恐!然往來視之,覺無異能者,益習其聲,又近出前后,終不敢搏。稍近益狎,蕩倚衝冒。驢不勝怒,蹄之。虎因喜曰:「技止此耳!」因跳踉大闞,斷其喉,盡其肉,乃去。

噫!形之龐也,類有德;聲之宏也,類有能。向不出其技,虎雖猛,疑畏卒不敢取,今若是焉,悲夫!

大意是说:黔地没有驴,一个无聊人运了头驴过去。黔地老虎没见过驴,开始很害怕,后发现驴不过“技止此耳”,跳上去,吃了驴。

故事创作于作者永贞革新失败之后。后人一致认为,作者是在讽刺朝中外强中干的权贵。

以我今天的眼光来看,故事却是这样的:一个很有想法的人,给一个没有驴子的地方运了头驴。驴新来,遭到当地传统势力的敌视,最终不敌,被吃了。这个很有想法的人,就是指作者自己,驴指永贞革新,老虎指当时朝中掌控实权的权贵和地方的藩镇。

我们今天谋求创新,就要做很多看似无聊的尝试,敢于承担失败的风险。想法的落地,则需要短时间适应现实情况,否则很快夭折。即使最终项目失败了,也未必意味着想法是错误的。现在黔地已经没有老虎,留下的是驴。

Python实现数据类的方法集合

当前Python最新稳定版为3.6。主流Linux发行版官方仓库提供Python版本的有2.7和3.5,默认依然是坚强的2.7。

1、dataclass装饰器。正规军,需要Python 3.7+,还在路上。dataclass装饰器会给类添加__init__、__str__、__repr__等方法。

@dataclass
class InventoryItem:
    '''Class for keeping track of an item in inventory.'''
    name: str
    unit_price: float
    quantity_on_hand: int = 0

    def total_cost(self) -> float:
        return self.unit_price * self.quantity_on_hand

2、collections.namedtupletyping.NamedTuple。要求不多的用这两个最合适了。Python 3.6+的typing.NamedTuple才支持默认参数。

class Employee(NamedTuple):
    name: str
    id: int = 3

employee = Employee('Guido')
assert employee.id == 3
Employee = namedtuple('Employee', 'name, age, title, department, paygrade')

3、autoassign装饰器,和auto_assign装饰器。算是奇技淫巧,前者支持Python2,后者支持Python 3.5+。

4、collections.namedtuple + functools.partial。通过partial实现默认参数,也是我当前采用的方案

fields = ("name", "age", "title")
defaults = OrderedDict({"title": None})
Employee = partial(namedtuple("Employee", fields), **defaults)
employee = Employee("Guido", "18")

网上还有一些相对麻烦点的方案,比如重写namedtuple的__new__方法,就不一一列举了