《联邦党人文集》阅读笔记一

 

《联邦党人文集》是汉密尔顿、麦迪逊和杰伊,在1787年美国宪法草案颁布之后,为说服纽约州居民支持该草案而撰写的一系列说明性的文章。今天我们仍然阅读《联邦党人文集》,是因为它依然是对美国宪法立法者们立宪意图的最权威解读。

《联》一般可以分为五个部分。第一部分为前十四篇,主要阐释为何需要一个强大的联邦来保卫安全和保证繁荣;第二部分为十五至二十二篇,主要讨论当时联邦组成的弱点。第三部分为二十三至三十六篇,主要论证一个有活力的联邦需要哪些权力。第四部分为三十七至五十一篇,主要定义了新的联邦主义者。第五部分为五十二至八十三篇,主要描述联邦政府的机构设置。

在第一部分当中,作者意在说明分散的州政府的诸多缺点。首先是战争的危险。作者认为,正当的战争多半是因为国际条约没有得到有效履行。相对于十三个独立的小政府,成立一个联合的大政府更容易保证这些国际条约得到有效的正确的执行。而对于不义的战争,最好的策略是建立强大的军队使得敌国不敢冒犯,而一个强大的联邦政府比分散的小州政府更能够维持一只强大的军队。作者还认为,如果保持十三个州分别独立,他们会因为种种原因产生冲突并最终酿成战争。比如外国的干扰、州与州之间贸易的摩擦、领土的纠纷和军事不平等。而由于州与州之间的战争或者军事竞争,政府必然会扩大权力和军队力量,最终损害人民利益。成立联邦政府则可以有效避免这些危险,既可以有效评定叛乱,还有助于海上商业的发展和海军的建立,同时可以简化税收,降低联邦的运行成本。

第二部分主要是对当前联邦的弱点的描述。其中最主要的问题是,当时的联邦政府的立法基础是建立在州之上而非个人之上的,而联邦公约的执行毫无强制的手段。作者认为,解决这些问题的办法是让联邦政府的执法权建立在个人基础之上。关于这一点,反对者认为联邦政府将过于强大而侵犯人民权利。作者则反驳道,联邦政府之下有处理当地事务的州政府和地方政府,联邦政府并不直接与公民的日常生活发生联系,联邦政府想要直接获取他们手中的权利既困难也无此不必要。初立法权之外,作者认为联邦政府还缺乏管理商业的能力、招募军队的能力以及司法权力。

在第三部分当中,作者论证了为了建立一个有活力的联邦需要哪些权力。首先是征兵并维持常备军的权利。关于这一点反驳的意见认为,维持常备军将更容易使政府侵害公民权利。但作者认为,在紧急情况之下,零时征召军队是不可行的,而作为制衡的手段,只需要周期性的重新审定常备军的预算计划即可。其次是征税的权力,在此前的联邦政府设置当中,政府经费需要由各州缴付,联邦政府经常陷入经费不足的境地,直接征税的权利是联邦政府顺利运行的关键。

在整部《联》当中,第十篇是最重要的一篇。汉密尔顿在这篇文章里阐述了党争的不可避免以及控制他们影响的办法。汉密尔顿认为由于人与人天然在观念上不同、在财产上不均,人们必然会和他们最相近的人组成团体,有时候甚至不惜危害公众的利益,侵犯他人的权利,这样的党争是无法避免。

在所有党争当中,麦迪逊认为危害最大的是因为财产不均而起的。在当时的美国,有产阶级占少数,无财产者仍然占多数。麦迪逊担心,如果实现直接民主,这些多数无产者将会最终控制政府,并且通过各种手段,以牺牲其他富人和有产者利益为代价重新分配国家的财富,是为多数人的暴政。

麦迪逊认为解决这个问题的办法只有两个:消除其源头,或者控制其影响。消除源头或者需要完全剥夺人的自由,或者需要创立一个均富社会,二者都不可行。为了控制党争的影响,麦迪逊认为需要实行共和制而非直接民主制。共和制所选出来的代表更有可能是为了集体的利益,而不是个人的利益而制定决策。而大规模的共和制比小规模的共和制更能够有效控制党争。大规模的共和制意味着更多更优秀的的候选人,人们的利益更加多元而难以形成利益上的大多数。

至此,我们已经了解了《联》前三部分的主要内容,更多的内容将会出现在接下来的笔记当中。

《费城奇迹》书评

1787年5月25日到9月17日,联邦制宪会议在费城市的州议会大楼召开。费城会议是美国历史最重要的转折点之一。华盛顿汉密尔顿,麦迪逊,富兰克林等知名人物都参加了会议。这次会议通过的宪法将成为美国未来长久的繁荣的坚实基础。

美国宪法因为其伟大的设计成为历史长卷上的神来之笔。很多人将美国宪法的制定与独立战争联系在一起,误以为这部宪法是独立后的自然结果。实际上在联邦宪法制定之前,美国联邦一直以《联邦条例》为宪法而运行。《联邦条例》制定于1777年美国独立战争期间,是当时的美国各州为了争取更广泛的利益而达成的结盟协议。而联邦宪法的制定过程更是充满了波折。

《联邦条例》的制定是为了在各州的基础上建立一个统一的联盟,以在军事,外交,商业上争取更大的利益。联邦会议作为当时的联邦政府正是在这个条例的框架之下成立和运行的。

然而由于缺乏权力根基,《联邦条例》在各个领域的表现都差强人意。军事上,联邦陆军因为军费征收不力一度濒临解散。外交上,因为财力和权力有限,也一直未能达成有效的贸易协议。联邦在商业上的表现更为糟糕。因为缺乏征税能力,同时无法独立制定国际和洲际贸易的规则,联邦政府在促进易商上的努力也收效甚微。

《联邦条例》的失败是因为其所建立的权力基础不足。整体上她只是一种联盟性质的约定。联邦之内的各州拥有完全的主权,联邦会议的决议也必须要得到州政府的通过才得以推行。联邦的财政收入需要分摊到各州,但同时她又缺乏对各州的强制征税能力,所以即使各州拖欠费用联邦也无计可施。

正是看到了联邦的这些问题,汉密尔顿、华盛顿等人决定推动重新制宪,已建立一个更加强大的联邦政府。1787年,联邦会议决定修改条例,并邀请各州代表共同商讨修改方案。因此,在最初的计划当中,也许是为了获得更多州的支持,费城会议名义上并不是为了重制宪法而是为了改进联邦条例而召开的。

费城会议上一共出现了三套主要的制宪方案。包括更加激进,提议成立国家级联邦政府的弗吉尼亚方案,更加温和、提议在现有联邦条例框架上进行改进的新泽西方案,还有与当时英国制度颇为相似的汉密尔顿方案。其中汉密尔顿的方案因为与英国政体过于接近,并且需要州权作出更多让步而最终没有被接受。

佛吉尼亚方案主要由詹姆斯麦迪逊,即后来的美国第四人总统提出。弗吉尼亚方案提议设立一个强有力的两院制立法机构,即美国国会,国会上下两院,过会两院代表按照各州人口比例分配拟并选举。

在这里,我们需要了解的背景是,在当时美国联邦的十三个州当中,有人口和面积都巨大的弗吉尼亚州,佐治亚州,纽约州等,也有相对更小的新泽西州、罗德岛州等州。各州虽然人口和经济实力不同,但在联邦会议中都拥有同等的投票权。因此,弗吉尼亚方案中按照人口分配国会议员比例的方案可能会削弱小州在联邦中的权力。因此,新泽西州提出了一份反对弗吉尼亚州方案的新方案。

新泽西方案提议,各州在新的两院制立法部门拥有同等的投票权,这一提议与当时的《联邦条例》完全相同。新泽西提议一方面反映了各州希望以完全独立、平等的状态自愿结成联盟的心态,另一方面也反映了小州对于在新联邦中话语权降低的威胁的担忧。新泽西方案并未被会议认真考虑过,但是在制宪会议临近尾声的时候,小州的代表们以此为威胁阻止最后协议的达成。

在带领读者了解制宪会议的历史进程、并还原了州代表在制宪会议上的发言和背景之后,作者还试图让读者更为清楚的体会到制宪会议上最重大的争论:立法部门代表分配问题,的历史背景。因为对国会席位分派方案上的争论,制宪会议一读陷入僵局。这个时候,作者笔锋转移,带领读者对当时的美洲大陆进行了一次巡视。

这种巡视式的方式让我们更加了解费城制宪会议的历史背景,比如为何美国的人民如此真在意州权。在制宪会议陷入僵局的时候,康涅狄格妥协成为了最终的方案。这个方案主张,两院制国会当中,下院的代表名额按照每个州的人数分配,而上院代表队的名额平均分配,每州两名。这个妥协的方案平衡了大州和小州的利益,于是最终得以通过。

除了对于制宪会议的历史还原,《费城奇迹》这本书还刻画了会议上最令人瞩目的人物。包括沉默寡言的华盛顿将军,能言善辩的汉密尔顿等。其中又以对经验丰富,政治手腕高强的富兰克林博士的刻画最有趣味,比如作者还原了富兰克林在制宪会议陷入僵局时,为了鼓励大家放下成见放眼未来的而进行了轻松幽默而又发人深省的发言。正是这样的细节就让我们感到了他欢快而又充满智慧的个性。

作者在本书的最后几个章节还介绍了宪法批准的过程。因为根据新宪法的规定,比如得到13个州当中9个州的批准才能正式通过。这些情节同样精彩。

对于想要了解1787年制宪会议这段历史的读者,《费城奇迹》这本书是个不错的选择。作者在内容上的选取有度,重点还原了制宪会议上主要争论,而没有陷入到对于细枝末节的沉闷讨论。另一方面,对于会议上重要人物的刻画给阅读增添了趣味,也使读者通过靠近这些改变历史的人物更加体会到历史事件的发展过程。作者在记述会议进程期间还穿插了历史背景的介绍,以使得读者更容易理解为何当时的辩论如此重要。

《万历十五年》书评

按照作者黄仁宇的说法,万历十五年,即1587年,是历史上极为平常的一年。这一年‘四海升平,全年并无大事可叙’,‘实为平平淡淡的一年’。既然平淡,作者何以要单单将这一年抽出来叙述呢?要理解作者的做法需要从作者的大历史观说起。

黄仁宇的历史研究从大的时空范围着手,强调不通过历史人物的生涯探讨和单一历史事件来分析历史,而是通过对历史社会面貌进行整体的分析和把握,掌握历史社会的结构特征。

万历十五年是五百年明清史中极为平常的一年,这也正是作者选取这一年作为研究切片的原因之一:从宏观上看,明清社会的根本问题从未改变,从这极为平常的一年着手,也可看出不变的矛盾并理解明清社会走向衰落的根本原因。

黄仁宇在这本书中对万历朝的诸多人物做了群像式的描绘。在他看来,传统中国社会以道德代替法律,阻碍了技术的发展,最终导致中国社会从汉唐的先进走向明清的衰落。黄仁宇在描绘这些历史人物的时候,重点展示了他们在这种社会设定之下辗转腾挪。

比如张居正之后的第二任首辅申行时,一般认为他是个和事佬,老好人。作者却认为,他早已看出整个文官集团中,作为统治基础的道德要求和文关门本身的的私欲之间的相互抵触。

作者以阳和阴来说明道德与私欲的矛盾。道德礼法是阳,皇帝和百官需要通过各种象征性的仪式来维持人们对于道德的信任,从而达到上下一心的目的,bi并完成国家治理。但另一方面,大明王朝历经两百年,文官集团已经成为事实上的统治集团,文官们为了私欲进行各种争斗也是无可否认的事实。

万历皇帝了解到道德与私欲并存的过程正是从张居正死后大臣对他的弹劾开始的。万历皇帝发现这个曾经以道德教育自己,以简谱自居的首辅大臣其实私生活相当奢侈,他对于自己多年受到的要为明君的道德信条也终于坍塌。

万里皇帝还逐渐了解到,及时那些对张居正进行攻击的大臣,也并不是完全怀着纯正的目的,他们也是通过这种手段获取利益。作为皇帝表面上拥有无上的权力,但也不得不收到传统文化和文官集团的掣肘,而他并无能力改变这一局面,于是他选择了怠政的方式作为对文官集团的报复。

张居正死后被清算的原因在于他改革社会的同事,试图以权威压制私欲,最终在死后遭到反弹。申行时在了解这一问题之后调整方法,努力维持人们对于道德的信任的同事又不过分压制文官的私欲。

申行时的这种中庸和妥协的方法当然难免受到非议,人们会认为他不作为,对导致明朝覆亡的诸多隐患置之不顾。但作者却指出,在传统中国社会道德统治的设定之下,供申行时选择的空间不存在了。

另一个代表人是以清廉正直的名声享誉本朝的海瑞。他所提倡的社会治理的方法乃是以残酷的手段,如朱元璋时期的剥皮之刑,惩治道德败坏,贪污腐败者。立足点仍然是惩治私欲,维护道德。即使是万历皇帝也认为他的主张过于怪癖而认为他冥顽不化,最终海瑞落寞的死在任上。

军事领域的情形十分类似。明朝立国以来,为防止武将作乱,始终以文职为尊,打压排挤武将。戚继光所进行的军事改革也仅仅是局限在抗击倭寇的前线部队之中,而无法触动更大的军事集团。

思想界的代表人物李贽同样如此。李贽力图突破程朱理学的限制,提出人可以有私欲的观点。但是最终仍然不被认可,并在信仰程朱理学的士绅们的迫害之下入狱,最终自刎。

在作者看来,海瑞,戚继光,李贽都是因为受到传统文化的掣肘而得不到有意义的发展的人。

本书作者黄仁宇原本是国民党的军官,二战结束后进入美国密歇根大学跟随著名学者余英时学习历史,1964年获得密歇根大学历史学博士学位。本书1976年即已成稿,然而因为研究方法别出心裁,一直到1981年才在耶鲁大学出版社的支持下出版。

这本书原作为英文,后经作者翻译为中文,但行文乃仍然保留了许多英语文章的特色。

Building Microservices Note: Integration

What is Microservices Integration ?

How one microservice can talk with another? In general, the following technologies could be used: shared database, RPC, and REST. But how do we pick up the right one?

The following are general answers to the questions:

  • Avoid breaking changes.

When we add a change on the server side, the client side should not be impacted unless necessary.

  • Keep your APIs technology agnostic

This is to avoid integration technology that dictates what technology stacks we can use to implement the micro services.

  • Make your service simple for consumers

Make it easy for the consumers to user the services.

  • Hide internal implementation details

Don’t have the consumers bound to the internal implementation.

With this guideline, let’s take a look at available options.

Integration technology

Shared Database

The most common form of integration is database(DB) integration: if other services want to retrieve or update the information from another service, they reach into the database.

This integration pattern definitely breaks many of the guidelines we set put:

  • It allows the external parties to view and bind to internal implementation details.
  • The customers are tied to a specific technology choice. For instance, if we decided to use Postgres, the consumer has to find a way to integrate with Postgres.
  • It would be very difficult to change the logic, the logic of parsing the data must be spreader across all consumers.

So in sum, shared database is never a good choice for micro service integration.

Remote Procedure Call

Remote Procedure Call(RPC) refers to the technique of making a local call and having it execute on a remote service somewhere.

The common used PRC techniques includes SOAP, Thrift, Protocol Buffers. They support separate interface definition, and client/server stub generation based on the definition.

Some of the technique bind to a specific networking protocol, while some allows you to use different type of protocols. For example, gRPC utilizes Protocol Buffer and HTTP2.

Some RPC mechanism are heavily tied to a specific platform, but some other mechanisms for example Thrift and protocol buffer support multiple languages.

So, what’s the major downside of RPC calls? The problem is, Local Calls are not like Remote Calls. The consumers often forget about one thing: the network is not reliable. The client needs to keep in mind that the remote server could be down, be slow or the request could be lost and handle these situations properly.

REST

Representational State Transfer(REST) is another technique. The most important concept of REST is resources. The REST service creates different representations of this resource on request.

REST and HTTP

REST as a design pattern does not talk about underlying protocols, although it is most commonly used over HTTP. The major reason is HTTP itself defines some useful capabilities that works very well with REST style, for example, the HTTP verbs: GET, POST, and PUT, and HTTP error codes.

There are, of course, downside of REST over HTTP. For server to service communication, if extremely low latency or small message size is important, HTTP might not be a good choice, as the message header can be big. TCP/UDP might be a better choice in these case.

Data Interchange

REST support many formats of data interchange framework, the most comply used one are JSON and XML. Application data are converted into JSON/XML format, and then transmitted to the other service.

JSON V.S. XML

Both JSON and XML are human readable and machine readable.

  • XML supprots store the metadata information with the tag.

For example, the type of the field, while JSON has to encode these metadata as an object and associate it with the data.

  • XML supports link while JSON does not.

Xlink is used to create hyperlink in XML documents, with Xlink, the link content can be defined outside the linked files. While JSON is purely data based, and does not support anything similar. For python, the objects has to be concretely rendered in multiple places even though they share the same content.

  • JSON is significantly less verbose than XML.
  • JSON supports array.

This make it easy to be mapped to the data structure in the programming languages, for example, array, list, hash map etc. . For example, JSON is directly interchangeable with python dict. JSON objects can be easily parsed and manipulated in almost all programming languages.

《自私的基因》书评

对于流行的东西我总有意无意保持一定的距离,《自私的基因》也属于此类。这本书在我上大学时就已十分流行,我在许多场合、听许多人谈起过这本书,但一直没有下定决心去读。大概因为这个名字过于标新立异,透漏着一种想要以奇特的理论来震撼读者的刻意。最近重点在读人类学的书,于是终于决心翻出来认真读一读。

这本书主要从基因的自私性出来解释个体和群体中的行为,尤其是最受传统进化论困扰的利他的行为

简单的说,这本书的理论框架是这样的:

  1. 基因是进化的基本单位,所谓基因是控制某个生物形状或特性的染色体片段。
    个体或者群体都不是进化的基本单位。
  2. 基因进化的竞争对手是控制同一个性状或特性的等位基因。
  3. 基因的进化的目标是为了提高自己在整个等位基因库中的比例。
  4. 基因进化的一切目标都是以此为出发点,是完全利己的。
  5. 基因进化主要通过控制个体的形状或特性来实现。
  6. 不同的形状或者遗传特性最终会为个体带来不同的繁殖机会,从而影响控制这一特性的基因在后代中的比例。
  7. 基因和等位基因之间的竞争会最终达到一个稳定状态,各个等位基因在基因库中所占的比例保持稳定。
  8. 带来这个稳定状态的策略是进化稳定策略(evolution stable strategy),稳定策略是不同策略博弈的产物。
  9. 基因的竞争并不是单一的,而是相互影响的,最后可能造成不同基因相互配合的效果。
  10. 生物的行为包括利他的行为都可以用基因的自私性来解释。

这本书最核心的概念是ESS,也就是进化稳定策略。ESS的特别之处在于,它从博弈论的角度来研究带来不同竞争策略的基因是如何相互影响并最终达成平衡的。作者几乎花了一半的篇幅在讲解如何使用ESS这个概念解释生物的行为,其中着墨最多也最有趣的是生物的性选择策略,这里可以简要介绍一下。
 

生物性选择的基础是两性生育和抚养后代的成本的不对等。这种不对等主要体现在两性的配子的不对等(出现这种不对等的原因作者在书中有介绍)以及孕育后代的不对等上。雌性和雄性在博弈过程中的优化目标都是尽可能多地繁殖带有自己基因的后代,然而不对等的生殖成本带来了雄性和雌性在性选择策略上的差异。作者归纳一般有两种性选择的策略,幸福家庭类以及大丈夫类的。

幸福家庭类的策略中,雌性选择延长决定时间来考验男性的忠诚程度,进而推断出其照料后代的机会和能力,雄性选择通过大量前期投入来证明自己付出的意愿和能力。这两种类型之外还有两个变动因素是浪荡的雌性和薄情雄性,前者会和任何后代交配但并不会养育后代,后者会在交配后抛弃雌性和幼子。浪荡的雌性会有更多的机会和诚实的雄性集合,但是随着浪荡雌性比例在后代中的提高,薄情雄性的机会也随着增大了, 最后养育成本还是会到浪荡雌性一方,而对着薄情雄性的增多,忠诚雌性的优势就会增加,比起被抛弃,不产生交配的净收益更大,因此忠诚雌性对浪荡雌性更具有优势。而对着忠诚雌性比例的增加,薄情雄性的数量就会相应下降了,因为无法找到足够进行交配的雌性。这四种性选择的个体的比例就会在这样的动态博弈之中到达平衡。
 

当然作者还用自私基因的理论介绍了更多生物的行为,比如在有些鱼类当中,主要依靠雄性照顾后代。这主要是因为雌性会先排出卵子并逃走,从而将照料后代的任务转嫁到雄性一方。作者通过这些例子有效的证明了自私的基因这个理论所具有的强大说服力。用一个简洁有力的理论对诸多现象进行剖析本身是十分有趣的,更多的例子以后有机会再单独拿出来介绍。 

作者还花费了很多篇幅批判群体进化论。所谓群体进化论是认为生物的利他行为是出于对整个群体或者物种的利益的考虑,也即牺牲自己造福种群的理论。作者认为,这一概念的根源其一是人们将进化的单位上升到了群体,其二是因为这种理论契合了人类的道德感召的需求,即对牺牲自我的利益以换取更多人利益的这种利他主义的感召(这在许多宗教中非常常见)。但这个理论的根源问题在于,让生物在长期物种的利益和短期个体的利益之间选择前者无疑是不现实的,另一方面,种群进化的理论在很多例子当中是有解释力不足的问题的。

在最后一章中,作者还提出了一个文化觅母(meme)的概念。meme指人类的文化观念。meme的发展目标与基因类似,就是最大程度上的复制自己。但是meme的利益并不总是和基因的利益相同。比如有越来越多的家庭选择不生育孩子,这种观念就与基因传播自己到下一代的利益相悖。但平衡指出在于,如果二者相悖太远,meme传播的基础人类载体本身就会减少,从而降低自己被传播的机会。 

人类行为的特殊性在于,除了受到遗传的影响,还会受到文化的影响。在本书中,作者一直强调,从进化的观点看,生物只是运载和复制基因的载体。同样的,人也可以看作是文化观念的载体,文化不断发生,发展,传播,演变,和基因的演化和气相似。而这种相似性正是meme这个概念所想要揭示的规律。

 
当然,自私基因的理论如此强大,以至于有人会产生人类的高尚行为背后不过是基因的意志这种感觉。实际上,在很多年前初次知道这种理论的时候我也感到有些困惑:这和历史上的种种还原论何其相似,人类的行为被还原到了化学物理层面,现在又被还原到了生物层面,那么人类的这些高尚的可贵的行为真的包含了值得赞颂的东西吗?

我的回答是:人具有自由意志。尽管人类的行为强烈的受到基因的影响甚至控制,但是人类有足够的自由意志可以克服甚至消除这种影响,而这才是人类最可贵的地方。父母对子女的爱固然包含着基因的自私性这一根源,但是我们无法否认他们事实上的付出、奉献和关爱,理解了这些才会更加感到人的可贵。 

Python Notes: Global Interpreter Lock

Why Python use GIL

Python uses reference count for memory management. Each objects in python has a reference count variables that keep track of the number of reference to the object. When the reference count goes back to 0, Python would release this object from memory.

However, in multi threading scenario, multiple thread might access the same object, and object reference count could be changed incorrectly in race conditions. Then objects that should be released could still stay in memory and worst case, objects that should not be release are incorrectly released.

To solve this problem, python introduced GIL, which is a global lock in python interpreter level. The rules is that, any python code has to acquire this lock to be executed. You might ask why not add one lock to each objects? This could result in deadlock.

In this way, python code guarantees that only one thread would be able to change the object reference count.

Problem of GIL

The GIL solution, however has problems in that Python code would not be able to utilize multi CPUs. If your code is CPU intensive, python multi-thread would not help you at all. However, if you program is not CPU intensive, but I/O intensive, for example, network application, Python thread is still a good choice.

Solution to this problem?

Are there solutions to the problem? Yes, there are. Python community has tries many times to solve this problem. Python GIL is not really tie to python language it self, it ties to Python interpreter it self. So, as long as we change the underlying python interpreter, python could support multithread. For example, Jython, is implemented in Java.

However, another important reason why Python GIL is not removed is that python has many extended libraries that are writing in C. Those libraries works well with Python in that they don’t need to worry about multi-thread models, the GIL model is really easy to integrate. Moving those libraries to other interpreters are hard works.

Another solution is to use multiprocess instead of multithread. Python has good designed libraries that supports multiprocess. However, process management would have more overhead than thread management for operating system, which means the performance of multiprocess programs are worse than multithreads.

Python Notes: Decorator

By definition, a decorator is a function that takes another function and extends the behavior of the latter function without explicitly modifying it. Built-in decorators such as @staticmethod, @classmethod, and @property work in the same way.

How decorator works? Let's take a look at the following example:

def my_decorator(some_func):
    def wrapper():
        some_func()
        print("Some function is being called.")

    return wrapper

def another_func():
    print("Another function is being called.")

foo = my_decorator(another_func)

foo()

You would see the following print on the screen:

"Another function is being called."
"Some function is being called."

As you can see, we pass some_func into a closure, and do something before or after calling this function without modifying its original behavior, and we return the function. As we already learned, python functions are just like other python objects, they are first class objects. The returned function could be called just as any other functions.

@decorator

The above example is already very similar to decorator. The difference is that decorator often comes with a @ symbol. This is an example of python syntax sugar, which often refers to syntax in a programming language that aims to make the things easy to read or to express. For example, the following is an example of a decorator:

@my_decorator
def another_func():
    print("Another function is being called.")

Decorator that takes any argument

In python, we can use *args and **kargs to represent arbitrary arguments. The following example shows how to take arbitrary arguments in a decorator:

def proxy(func):
    def wrapper(*args, **kargs):
        return func(*args, **kargs)
    return wrapper

Decorator with parameters

Sometimes we want the decorator to take parameters, for example, we should implement it in this way:

def decorator(argument):
    def real_decorator(function):
        def wrapper(*args, **kwargs):
            do_something_with_argument(argument)
            result = function(*args, **kwargs)
        return wrapper
    return real_decorator

Decorator tips

One practical tips when defining decorator is to use the functoolss.wraps, this function would keep all the meta data information of the original functions, including the function signature and docstring information.

import functools

def uppercase(func):
    @functools.wraps(func)
    def warpper():
        return func()
    return wrapper