婚礼上,我哥在我妻子面前嚎啕大哭,多年家丑终于曝光

 

文 | 刘小念 · 主播|一凡
来源 | 写故事的刘小念(ID:xgsdlxn)

 

– 01 –

 

妈妈走后,我们的家也散了。

 

彼时,我正在本市读大三。

 

家里兄弟姐妹五个,我是老小,上面有两个哥哥,两个姐姐。

 

安葬了妈妈之后,大家就为爸妈留下的房子争执不休。

 

“尽管小五上学花的钱最多,但谁让咱们是哥哥姐姐呢,所以房子也有他的份,就平分吧。”

 

“凭什么呀?

 

前些年,爸病重时,全是大哥和我照顾的,妈病重时也一样。

 

啊,合着照顾的时候你们遛边打蹭,现在分财产了,开始讲究不偏不向了,我不同意!”

 

二姐一向心直口快。

 

“爸妈病重是你们照顾的,但最后还不是我们掏的住院费。”

 

二嫂是向来得理不饶人,遇到吵架就红眼睛的主儿。

 

“房子卖了,小五毕业住哪?”

 

大哥懦弱的声音淹没在一片争吵中,但我还是听见了。

 

那是妈妈离开后,我在这堆亲人里面,看到的唯一一点点暖。

 

在他们的吵闹声中,我弄明白了,哥哥姐姐就是要在我毕业之前,把房子卖掉。

 

不然,等我毕业住回家里,卖房子就难了。

 

 

– 02 –

 

这个家,兄弟姐妹众多,一直在跟贫困抗争,父母一辈子都在为钱犯难,而兄弟姐妹没有对外竞争的能力,只会在家庭内部显能耐。

 

我是家里唯一一个上了高中,而后又考进大学的人。

 

那时候,哥哥姐姐都已结婚,有了自己的家,妈妈坚持让我读书,为此,他们只要一吵架,就会声讨妈妈偏心。

 

 

 

妈妈只能用一句话平息众怒:

 

“以后我老了就跟小五,你们谁我也不指望,不拖累。”

 

可是,她没有等到我为她养老的那一天。

 

“妈妈尸骨未寒,你们就着急忙慌地要卖房子,你们要不要这么过分。”

 

我涕泪交流地大吼一声,卖房子的事情算是暂时搁置了。

 

 

– 03 –

 

可是半年后,哥姐以给爸妈扫墓为名,要我回家。

 

回家后我才知道,房子已经找到了买主,但没有我的签字,他们卖不出去。

 

二哥率先向我哭穷,然后是大姐和二姐,每一个,都把自己家描绘成明天就揭不开锅的样子。

 

见我不说话,他们的目光齐刷刷看向大哥。

 

老实巴交的大哥脸憋的通红,啥也说不出来,大嫂却一直在捅他:

 

“你倒是说句话,劝劝小五啊。”

 

事已至此,我只求速卖速决,不想再看到眼前这几个一母同胞的人。

 

三天后,房子卖了,75万,一家15万。

 

分钱那会儿,二嫂还在骂二哥:

 

“叫你早点动手,妈那个新电视机到底让你二妹抢走了,你个窝囊废!”

 

“那电视机本来就是我买的好吧。”二姐大声回应。

 

我不想再听他们争吵,在一片混乱中悄悄离开了那个生活了21年的家。

 

在公交站等车时,大哥追了上来,他伸手拦了辆的士,给了司机100块钱。

 

“小五,拖着这么多东西,打个车回学校吧,大哥有空就去看你。”

 

他一边说着,一边把我的行李放进后座。

 

婚礼上,我哥在我妻子面前嚎啕大哭,多年家丑终于曝光

 

下车后,我给了司机零钱,把大哥给他的那100元要了回来。

 

那半旧不新的100元,是我在这世界上,残破而微弱的亲情。

 

 

– 04 –

 

妈妈走后的第一个春节,我去给爸妈扫了墓。

 

说来悲凉,他们有五个子女,除了大哥,其他人都没来。

 

其实也直到此时,我才肯承认,我没有家了。

 

妈妈在时,每年这个时候,一家15口人还是会聚在一起。

 

尽管打个麻将,他们也会为几块钱的输赢吵上几句,但至少家还在,热闹也在。

 

回到学校后,宿管阿姨叫住我,递给我一个饭盒,说是大哥送来的。

 

那个除夕夜,我就着眼泪把那盒猪肉酸菜饺子吃完了,心里也解散了自己的原生家庭。

 

我对自己说,将来若有余力,会报答大哥对我的滴水关心。

 

他是这个世界上仅存的,拿我当家人的人。

 

 

– 05 –

 

大四时,我在中铁某局实习,因为表现还不错,两个月后,就有了3000元的底薪。

 

人生中第一次拿到工资,我率先想到的是父母,给他们买了鲜花,给爸爸买了瓶好酒。

 

从墓地回来的路上,我又买了一些水果去了大哥家。

 

大哥生性沉闷懦弱,看到我,只淡淡的说了句:“来啦。”

 

然后让大嫂去买菜,留我在他家吃饭。

 

闲谈间,难免说到散在这个城市里哥哥姐姐们的现状。

 

一个比一个糟心。

 

婚礼上,我哥在我妻子面前嚎啕大哭,多年家丑终于曝光

 

大姐一度被骗进传销组织,2万块打了水漂,被解救回来后,整个人都有点魔怔了。

 

二嫂下岗了,整天为了钱和二哥吵架。

 

二姐更惨,她有一次下夜班,包被抢了,里面刚好有500块钱,她舍命不舍财地追了好远,最后大腿被扎了三刀。

 

我气急败坏地说:“是命要紧还是钱要紧啊?”

 

大哥却对我说:“五啊,都穷怕了,看不了那么长远!”

 

 

– 06 –

 

每一家都是一边屋漏,一边阴雨连绵。

 

大哥一边说,一边叹息,为自己的有心无力。

 

见我吃得很少,他有几分过意不去地说:

 

“你多吃点,平时要是想吃啥了,就吱一声,你来吃或者我给送去都行。”

 

我只能赶紧夹了菜,大口吃饭,生怕一说话,眼泪就掉下来。

 

“回家吃饭”对很多人来说,不过是最普通的小事,但对我,却是奢侈。

 

 

– 07 –

 

那天临走时,大哥大嫂把我送到公交站。

 

等车时,大哥红着眼睛问我:

 

“五啊,你说咱们兄弟姐妹还能不能团结起来?

 

亲兄弟都不来往,想想真是寒心啊,大哥没这威望,也没这能力……”

 

我想起妈妈生前,几个子女一直不和,妈妈说这个,这个不服,说那个,那个不忿。

 

每个人都觉得自己被亏待,每个人都在抱怨别人。

 

妈妈的心,每天都疼,但她没时间多愁善感,也没能力处理好儿女之间的关系。

 

 

她生命的最后一刻,还在坚持做手工,供我读书。

 

她一直对我说:“五啊,咱家就你一个读书人,就你一个明事理的……”

 

 

– 08 –

 

那天,我流着泪做了一个决定:把一家人聚在一起,吃顿饭。

  

大哥接连说了几个好,激动地说:“你放心,我一定早早到。”

 

那是一个周六的晚上,我在蟹子楼订了包间。

 

没曾想,这顿饭吃了个稀碎。

 

我刚举杯想让大家集体喝一口,二哥却不满地说:

 

“我喝不惯白酒,给我来瓶青岛纯生吧。”

 

大姐很不高兴:“有啥就喝啥,摆什么谱,你什么档次啊。”

 

然后,他们轻车熟路地进入吵架模式。

 

大姐夫指责二哥不应该在包间里抽烟,二哥就开始抖露姐夫当年的糗事。

 

随后,二人的战争升级到一群人的争吵,最后把妈妈偏心供我读书这件事又提了出来……

 

 

– 09 –

 

大哥一次次站起来,让这个少说一句,然后有人立马怼回来:

 

“大哥,你怎么不说说他?”

 

大哥再去劝那个,那个回复:“早知道她来,我就不来吃这顿饭。”

 

再看包间服务员瞅我们一家的眼神,我整个人心灰意冷,想赶紧结账走人。

 

结果,大姐看了一眼账单,说道:

 

“小五,你要是真发达了,就赞助大姐点钱,别请我吃什么饭。

 

一是这饭店的饭根本吃不饱,二是你觉得你大姐是来这儿吃饭的人吗?”

 

那顿饭把我的心彻底吃凉了,发誓不再管他们。

 

 

– 10 –

 

而这时,大哥细心地把剩的东西打了包,平均分成五份。

 

挨个儿递到他们手里,没有人说谢谢,一个个气咻咻地走了。

 

站在空旷的包间里,我对大哥说:“没救了,真的没救了。”

 

那一刻,我恨透了这个家,恨透了自己拥有像他们这样自私冷漠的手足。

 

可是,大哥似乎没那么悲观。

 

他居然说:“你大姐夫到这样的地方,都知道抽烟不对,五啊,他们也没那么不可救药。”

 

不管是否可救药,那时那地,我只想跟这个家划清界线,各自眼不见为净。

 

 

– 11 –

 

毕业后,我在家乡中铁某局和北京一家私企间摇摆。

 

想去北京就是想离开家,离开这些所谓的家人,越远越好。

 

正在我犹豫之际,一个学姐请我去她的果园做客。

 

学姐毕业后当过建筑师,后来父亲生病,她回乡照料,结果,这一回去就彻底扎了根。

 

留下她的,是父亲留给她的那片果园,她雄心勃勃地要种绿色有机苹果,带动全村致富。

 

 

第一年,进行得很顺利,尤其是电商做起来之后,比往年多卖了不少钱。

 

于是,乡亲们开始信任她,愿意和她一起扩大规模,种植有机苹果。

 

我去的第二天,恰逢新引进的树苗运进村子,六辆大货车,很是壮观。

 

可是,车子刚进村,一个村民就躺在一辆大货车前。

 

原来,这人将土地承包给了学姐,他一见树苗运来,就开始坐地起价,表示如果不给涨价,大货车就甭想进村。

 

更可气的是,其他几个签约的人,也有样学样的加入碰瓷队伍,生怕吃了亏。

 

此情此景,我一个外人都气愤难当。

 

学姐却不慌不忙,先是跟他们讲违约的后果。

 

然后又把卖苹果的账本拿出来,告诉他们去年挣了多少,今年有可能再增加多少收入,以及现在好多资金急着注入。

 

如果他们想反悔,她现在就给退钱。

 

但说好了,日后不管她赔多少,赚多少,都不会带他们玩了。

 

“别介呀,大侄女,我们都等着跟你发财呢,你不能不带我们啊。”

 

若非亲见,真不敢相信这世界上,还有这样的人,前一秒还不共戴天,下一秒却攀亲带故。

 

 

– 12 –

 

那天晚上,我跟学姐在院子里聊天。

 

看着她脸上被山风吹出的两坨红,我问她:“何苦呢?值得吗?”

 

学姐说,乡村风景是很美,但人心有时确实很伤人。

 

然而,她用一年时间明白了一件事:

 

这片土地和这片土地上的人们,一直在输出,从来没被反哺过。

 

她是村里的第九个大学生,但,那些读书出去的人,再也没有回到这里。

 

“只有输出,没有补充与反哺,土地会贫瘠,人也一样。”

 

师姐这句话,让我突然想起了自己的家人。

 

他们何尝不像我脚下这片贫瘠的土地。

 

不是他们不想活得丰饶富有,而是他们没有这个能力。

 

 

– 13 –

 

从学姐那回来后,我跟中铁某局签了就业协议,并在市中心租了套两室一厅的房子。

 

每个周五晚上,我都会把哥姐家的孩子叫来,给他们辅导功课。

 

哥姐家都不宽裕,没钱让孩子们上辅导班,也没能力自己辅导,所以几个孩子的成绩都处于听天由命的状态。

 

我周五晚上带他们在家里看电影,基本都是那些经典的外语大片。

 

周六则给他们辅导功课,顺便带他们把这个城市的公园、博物馆、书店一一打卡。

 

而大哥大嫂每个周五的下午就早早来我家,帮忙做饭。

 

我们看电影时,他和大嫂就把家收拾得窗明几亮,然后悄悄离开。

 

 

– 14 –

 

那年除夕,大哥向所有人发出邀请——去他家过年。

 

我备齐了年货,买了好酒。

 

五家人在妈妈去世后,第一次在一起过年。

 

开饭前,大哥把我事先买好的衣服给大家发了下去。

 

“小五出钱,大嫂陪逛,每人都有份,就一个要求,吃饭时都穿上新衣服,过个新年。”

 

看着哥哥姐姐带着孩子们穿新衣,看着他们不好意思地瞟着镜子里的自己,我心里有点暖。

 

等到了开饭时间,气氛有点尴尬,大哥让大嫂发言。

 

大嫂当时就急了:“我哪会说话?吃得了,说什么话,事事的。”

 

眼见就要进入熟悉的争吵模式,我赶紧解围:

 

“大哥,你是咱家长子,还是你来吧。”

 

于是,从不喝酒的大哥给自己倒了一杯白酒,一饮而尽。

 

然后,他开口了:

 

“酒壮怂人胆,小五提起长子这事,我心里有愧。

 

我这个当大哥的没能耐,什么也没为你们做。

 

倒是小五,带着娃学习、见世面,眼见着孩子们比咱们活得有见识,说话办事文明,而且,成绩都提高了。”

 

说着,大哥给自己又倒了满满一杯酒:

 

“五啊,谢谢你,我这个大哥当得不好,让这个家散了。

 

但以后,你们有任何事叫大哥,大哥随叫随到,我干了。”

 

那个除夕,我们家没有争吵,相反,大哥开了头之后,哥哥和姐姐也开始检讨自己。

 

我们家,第一次有了道歉机制。

 

大家喝了点酒,流着泪对彼此说了一些抱歉的话。

 

那不是一个欢乐的除夕,但对我们家来说,意义非凡,那是一场自我反省的仪式,是改变的开始。

 

 

– 15 –

 

夜里12点,我们一家人去放烟花。

 

我还收到了四个红包,是哥哥姐姐给包的。

 

依然是大哥做代言人:

 

“妈走时,你还是个学生,我们却把房子卖了,让你连个家都没了,这红包,是道歉,你必须得收下。”

 

我收下那些红包,接受了这份歉意。

 

 

– 16 –

 

打那之后,我们兄弟姐妹之间的走动变得频繁。

 

大姐秋天晒好了萝卜干,挨家送去。

 

二姐有一次路过我单位,给我打电话,说想看看我。

 

结果看到我,她又不知道该说啥,干脆走到旁边的超市,给我买了一支雪糕:“你小时候最爱吃雪糕。”

 

二哥有一次跑长途货运,大哥刚好在休假,就陪着去给帮忙……

 

我们之间,除了彼此攻击与抱怨,终于有了表达、关怀和陪伴。

 

最难忘的,是我结婚前的日子。

 

 

全家人都忙坏了。

 

大嫂和姐姐们忙着给我做被,哥哥们率领孩子包喜糖、贴喜字。

 

看着一家人说说笑笑,热热闹闹,我第一次真正觉得:有家人真好。

 

 

– 17 –

 

婚礼现场,本来是想让大哥代表男方家长发言的。

 

但木讷的大哥坚持免了这个环节。

 

婚礼进行时,当主持人说:“因为新郎的父母都不在了,下面有请新娘的妈妈为一对新人送上祝福”时,大哥却走上了台。

 

他颤抖着拿过话筒,说:

 

“我是新郎的大哥,一个上不了台面的人,本来我求小五别让我说,但我觉得如果不说,小五一定会很遗憾。”

 

“小五是我们家最小的一个,也理应是最得宠的那一个,但我们这些哥哥嫂子姐姐姐夫,都欠小五一点宠爱。

 

他到底是读书人,不记恨,还热心地把我们这个家重新组织在了一起,他是我们全家的希望,今天,我代表全家人谢谢他,也代表全家人祝福他。”

 

“五啊,你一定要幸福!薇(妻的小名)啊,五要是敢欺负你,我们全家收拾他。”

 

说到激动处,大哥泪如雨下,我和妻子走上去,紧紧拥抱了他。

 

台下掌声阵阵,我的哥哥嫂子姐姐姐夫们却哭得像泪人。

 

大哥认为自己搞砸了婚礼,我告诉他,这是我有生以来最幸福的一天。

 

我娶回了自己最爱的女子,有了自己的小家,而我的大家,碎而复得。

 

这一天,比我生命中的任何一天,都值得纪念。

 

 

– 18 –

 

蜜月旅行时,我和妻子在西安的街头闲逛。

 

看到一个老式茶杯,上面写着“全村的希望”。

 

突然想起,当年卖房分家时,我背着行李回学校,大哥赶到车站送我的情景,想起除夕夜他送的饺子……

 

我果断买下那个杯子,决定送给大哥。

 

那一刻,我明白了一件事:

 

这些年,是大哥的微善助燃了我心中微弱的亲情火种,让我们一盘散沙的一大家子,没成为冷漠的路人。

 

《查令十字街84号》中有一段话:

 

“人与人之间就如小夜灯,一开始,也许我们并不知道彼此的存在,但你如果向外界亮起光芒,一定会被别人捕捉到。

 

而大哥,就是我们家那道微光,会把我们的幸福永远点亮。

转自:https://mp.weixin.qq.com/s/FRKsAlAv5CaCe3vL5lVNQw

十分钟高效KDJ指标技巧,买卖点成功率90%

 

在股票市场中要赚钱,首先要做好选股工作。今天就跟大家说说KDJ这个指标的运用技巧,如何抓住行情机会。KDJ指标是一个非常不错的技术分析工具,特点是对股价波动反应灵敏,非常适合于短线买卖股票的操作,其特点是能够比较迅速、直观地判断行情。在股票市场中要赚钱,首先要做好选股工作。今天笔者跟大家说说KDJ这个指标的运用技巧!

一、首先是设定技术指标参数

将周线移动平均线参数设定为5、13、21,将KDJ设定为5;
将月线移动平均线参数设定为3、6、12,将月线KDJ参数设定为6。

研究KDJ用的是周K线和月K线,而不是日K线,这样效果更好一些。

二、KDJ买卖原则:

1、K值由右边向下交叉D值作卖,K值由右边向上交叉D值作买。

2、高档连续两次向下交叉确认跌势.低档两次向上交叉确认涨势。

3、D值<20%超卖,D值>80%超买;J>100%超买,J<10%超卖。

4、KD值于50%左右徘徊或交叉时,无意义。

5、投机性太强的个股不适用。

6、可观察KD值与股价之背离,以确认高低点。

(三)KDJ超买信号

当k线数值高于90,同时D线数值高于80以上,并且J线数值连续三天高于100以上时,即称之为KDJ超买,提示股价已进入超买区,短期回调概率较大。持股者应暂时考虑减仓规避风险,空仓者应继续空仓观望,避免盲目追高。

KDJ超买信号见下图:

 

十分钟高效KDJ指标技巧,买卖点成功率90%

 

KDJ的识别与运用

(四)KDJ超卖信号

反之,当k线数值低于10以下,同时D线数值低于20以下,并且J线数值连续三天低于0以下时,即称之为KDJ超卖,提示投资者股价已进入超卖区,股价短期下跌动能减弱,反弹概率较大,持股者可以继续持股等待反弹,短线空仓者也可择机介入,博取股价反弹差价。

KDJ超卖信号见下图:

 

十分钟高效KDJ指标技巧,买卖点成功率90%

 

三、KDJ指标的高级应用

KDJ指标轧空——持股待涨信号

当KDJ曲线向上突破80以后,如果KDJ曲线一直运行在80以上区域,则意味股价处于强势上涨行情之中,这是KDJ指标发出的持股待涨信号,如果股价也同时依托中短期均线上行,这种持股信号更加明显。此时,投资者应坚决短线持股待涨。

十分钟高效KDJ指标技巧,买卖点成功率90%

 

持币观望信号:

KDJ指标追杀——持币观望信号

当KDJ曲线向下突破20以后无法反弹,其后一段时间持续运行在20以下区域,意味着股价处于极度弱势下跌行情之中,这是KDJ指标发出的持币观望信号。如果股价收到空头排列的均线压制,这种持币观望信号更加明显。此时,投资者应坚决持币观望。

十分钟高效KDJ指标技巧,买卖点成功率90%

 

KDJ卖出形态:K线和股价顶背离

案例分析:华映科技股价在2013年的这波上涨行情中,在上涨后期,股价走出新高的同时,KDJ指标中K线并却出现了一顶比一顶低的下跌走势,这是上涨的动能已经越来越弱的信号,到10月10号后股价开始下行。

十分钟高效KDJ指标技巧,买卖点成功率90%

 

形态简介:当股价持续上涨,连创新高的同时,如果KDJ指标中的K线没有创出新高,反而出现了一顶比一顶低的下跌走势,就说明股价虽然还在上涨,但是其上涨的动能已经越来越弱,未来股价有见顶下跌的趋势,这是看跌卖出信号。

转自:https://zhuanlan.zhihu.com/p/41588887

中盘股晋升千亿市值公司的十个选股指标

“曲棍球选股模型”之二

1/5

中盘公司的进阶

春节后,各大研究所都提出今年的机会在中等市值的公司上,并提出各种100亿流通盘的“中盘股策略”,但这个策略说起来容易做起来难。

大盘股其实很好选,盯着龙头干就行了,相当于在一百个股票当中选两三个,率高,只是赔率低,对估值容忍度要求比较高,适合“不看估值死捂股”的人;但选中等市值公司就不同了,可选数量增加到近千个,看上去都是低估值高增长,但难在确定性不高,选股的胜率大大降低。

大部分的大市值公司都是从中小盘成长起来的,中盘股的选股思路实际上就是:什么样的中型公司有更大的概率在三五年内成长为大市值公司呢?

麦肯锡战略业务的三位合伙人Chris Bradley、Sven Smit和Martin Hirt合写了一本名为《突破现实的困境:趋势、禀赋与企业家的大战略》的书,他们研究了麦肯锡企业数据库中2393家企业15年的财务数据,每一年按20%为一档,以利润为标准,将其分为五组。

 

中盘股晋升千亿市值公司的十个选股指标

作者重点考察了中间三组向上进入前五分之一的头部企业的“进阶规律”。

这些公司的规模相当于A股的上市公司,对应到A股,前五分之一相当于沪深300的公司,起点是400亿市值。中间的三组,相当于中证500和中证1000中较大的公司,起点是80亿市值。

这本书的结论就与本文开头提出的问题类似——一个80~400亿中等市值的公司,具备了哪一些特征,就能快速成长为大市值公司?这些特征又对应了哪些经营指标?

作者分析了几十项常用的企业经营指标,列出了与这些企业上行下降结果最相关的10项指标,然后调整权重,最后得到了一个“完美成长战略模型”。

中盘股晋升千亿市值公司的十个选股指标

上图为排名中间的三组企业,在满足了这些指标后,排名向上移动的概率。

以第四项“行业趋势”为例,这张图的意思是说,之前排名最右边(即最高的)20%的企业满足了这项指标后,有24%的概率进入最高组;之前中间排名30%的企业满足了这项指标后,有10%的概率进入最高组;之前排名最左边50%的企业满足了这项指标后,有4%的概率进入最高组。

这十个指标可以分为三组,与企业战略刚好对应:

“优势类指标”有3项,解决“我过去做了什么”的问题;

“趋势类指标”有2项,解决“我需要往哪儿走”的问题;

“举措类指标”有5项,解决“我需要做什么”的问题。

所有的模型都有一个弱点——只能代表过去,不一定能代表未来,但正因为“完美成长战略模型”是国外的案例,所以对中国企业的作用更大,中国的市场环境和企业发展阶段大多滞后于欧美企业五到二十年,模型更可能代表着中国企业的现在。

当然,因为中国市场的特点,部分因素的权重需要调整,所以,本文重点分析这10个指标,弱化其在模型中的权重。

2/5

关于“我过去做了什么”的三个指标

首先来看代表优势的三个指标,即一家公司的起点。

第一项是起点的“营收规模”,作者认为,当公司的总营收规模达到前20%的大型企业时,其成长性明显提升(满足这个条件的大多数已经是总利润前五分之一的企业了,所以重点是规模尽可能大一些)。

十年前做投资,选成长股总是倾向于中小企业,中国以前都是中小企业的增速快于大企业,但近十年,很多行业从成长变成成熟,存量竞争代替了增量竞争,大企业不断蚕食中小企业的份额,增速明显高于中小企业。

不过,中国因为经济体量太大,行业之间的差异性太大,我觉得规模在同一个行业内比较更有意义,在一级行业中上市公司排名前10%的公司,或者细分行业的老大也行。

第二项是起点的债务水平,作者给的门槛是不高于行业的40%,即资产负债率水平低于行业内60%的公司。

这项指标之前在A股很容易被忽略,能够贷得到款反而才是好企业,优秀企业还可以通过欠行业上下游的钱提高经营杠杆,但成长型企业常常是要加资本杠杆的,起点必须留有空间,接下来所有都是“挂最高档上高速”的指标,高负债率就像不系安全带一样危险。

第三项是起点的过去几年,研发投资要在整个行业的前50%。

一般的选股模型更喜欢用“研发占比”,即研发费用占总营收的比重,方便评估不同规模的企业对研究的注重。但从选股的角度,研发投入的绝对金额更重要,高研发比的10个亿,不可能比低研发比的15亿更能出成果。

这三项,它们强调的是过去的投入,因为过去的投入有先发优势,更类似于“护城河” 类的理论。

打个比方,就好像“找对象”,所谓有潜力不是“屌丝逆袭”,而是家底殷实、没有房贷压力,除了大公司的工作之外还在读EMBA或搞投资。

3/5

关于“我需要往哪儿走”的两个指标

虽然只有两项,但权重占了25%,充分体现了“选择比努力更重要”的战略判断原则。

第四项是行业趋势,要求该行业所有公司的平均利润增长率,在过去10年,至少上升了5%的排名。

 

中盘股晋升千亿市值公司的十个选股指标

就像大润发被阿里收购后,创始人说:“我们战胜了所有对手,却输给了时代”。行业的趋势甚至比公司本身的排名更重要,在趋势向上的行业中,即使是普通公司,排名向上移动的概率,也高于趋势向下行业的头部公司。

A股2010年以前上市的很多企业,管理能力并不差,只是因为身处夕阳行业,再努力也摆脱不了向下沉沦的命运。所以这些企业在2010年以后,就算成功概率并不高,也必须通过投资或并购进入趋势向上的行业。

这一项可结合前三项找到正处于上升趋势的行业,也可以合后五项,找到正在进入上升趋势的行业。

第五项是地点,这一项强调的是本国市场的规模,即巴菲特发明的“卵子红利”。中国企业都可以拿满分,因而可以忽略。

这里不得不提一下选股中的“地域歧视”,很多人宣称XX地区的企业一律无视,如果你没有什么好的选股方法,这样做排除也就算了;但如果你有了有效的选股指标,再用效果非常小的“地域指标”,完全是自我设限。

上面的两类指标,强调的是过去和选择,它的作用更多是剔除掉一些“成长为大市值公司的概率较低”的公司,重要的还是看下面的五项“正在进行的努力”。

4/5

关于“我需要做什么”的五个因素

六项是务实的并购。作者给出的量化指标是,每次并购的花费不能超过公司总市值的30%,并至少给公司带来30%的市值增长。

大部分的投资理念认为,企业的内生增长虽然速度比较慢,但更健康更安全,所以内生增长产生的利润,市场给予的PE倍数一般高于并购来的利润。

然而,在行业激进变革或者集中度加速提升阶段,都是“快鱼吃慢鱼”,速度慢就是最大的错误。A股的不少优秀企业,新业务的战略方向正确,但战略实施太保守,喜欢从零开始,结果贻误战机。

大部分高速成长的企业,如果有合适的并购对象,价格不离谱,更倾向于采用更高效的并购。

一个既快又安全的方法是滚动进行一系列金额中等的并购,即“收购——整合——再收购”,让经营性现金流与资本开支达到平衡的状态。

指标要求并购为公司带来同比例市值的增长,即,新业务的盈利能力与估值不低于老业务,这样的并购才能为老股东带来正向收益。

不过,具体到A股,很多企业上市就是为了拿钱收购其他公司,很多企业希望通过资产重组“脱胎换骨”,结果往往违反了“务实”这两个字,所以这一项,个人建议加上一个约束性指标——商誉不能超过净资产的30%。

高商誉产生的原因有两种:

一种是“蛇吞象”,即违反了“每次并购的花费不能超过公司总市值的30%”的原则,它的结果不仅仅是巨额商誉,还会摊薄原有投资者的权益,或者造成负债率的飚升。

另一种是“买贵了”,特别是数次不超过市值30%的并购,最后堆出了超过净资产50%的商誉,这就好像你买股票,公司都是好赛道好公司,也知道分散投资,但大部分都是以特别高的估值买在“山顶上”,那还是能力问题。

并购战略对一家企业至关重要,是战略管理的核心之一,我在《 A股的“并购之王”是如何保持盈利能力的?》一文中,详细分析了立讯精密的历次收购给市值带来的改变。

 

中盘股晋升千亿市值公司的十个选股指标

作为市值2400亿的上市公司,目前贡献利润的大部分资产都是上市后,通过三次股本扩张收购其他企业资产而来,但2020年末商誉仅为5.69亿元,占净资产比例仅为1.8%,可谓A股“低进高出”的“并购之王”。

第七项是动态分配资源。

企业应该把大部分资源投入到有爆发式增长潜力的部门,并及时裁撤前景不太好的业务部门,这一项的量化标准是几年内至少50%的资源是重新分配的。

因为资源投入是一个很难量化的指标,所以我调整成结果指标,企业重点投入的新业务营收占比应该逐年提升不少于5个百分点,并有望在两年内超过30%,五年内超过50%。

仍然以立讯为例,2014年通过收购进入消费电子行业,当年的业务占比为43%,当年的市值为450亿,之后这块新业务占比每年上升5到10个百分点,去年达到88%,而传统的连接器业务则每年下降5到10个百分点,从100%降到去年不足10%,5年后,营收增加了10倍,市值涨了8倍。

第八项是资本支出。这一项的量化标准是进入行业前20%,通常是中间水平的1.7倍。

资本支出是与经营性支出相对应的概念,企业用于原料、销售等现有产品的开支,是经营性支出,用于固定资产、长期投资的,即为资本开支。

资本支出在资产负债表上体现为各种长期资产增长净值的行业排序,更简单的是看“投资活动现金流”的流出项在行业中的排序。

第九项是生产效率改进,即为我们常说的降本增效。

这一项是衡量企业管理能力的核心指标,其量化标准是,生产运营成本或总资产周转率在行业排名前30%。

生产运营成本又是一项极其重要的指标,在重资产行业,体现为规模优势、技术优势、工艺优势、管理优势,在轻资产行业,主要是管理能力。成本在每一个行业中都有自己的量化指标,标准化产品可以直接比较单位商品的生产成本,中游制造业可以比较毛利水平,运营为主的企业可以比较管理费用,商超就复杂了,需要进行资产折旧、毛利、管理费用等全方位的综合判断。这也是我们在学习行业研究框架中重点搞清楚的内容。

第十项是差异化竞争的能力,即产品的定价能力。

前面所有的方法都要用钱,钱只能靠利润来赚,借的钱也要利润来还,经济学理论告诉我们,由于竞争的存在,大部分企业的净利润率都在下降,最后无限趋近于0。想要放慢下降的速度,就要避免价格的直接竞争,而避免价格竞争的唯一手段就是产品差异化。

差异化是很难的,要么你有专利壁垒(创新药)、专营壁垒(烟草),要么有几十年的品牌,要么有规模优势(半导体)。

这项能力的量化指标是产品综合毛利率,排名行业前30%。

作者在书中还分析了这五项举措对企业的影响,使用的越多,实现市值飞跃的概率越高:

中盘股晋升千亿市值公司的十个选股指标

5/5

曲棍球投资模型

在这一系列的第一篇,我介绍了“曲棍球投资模型”,回顾一下:

1、企业在利润没有明显下降之前,率先进行一系列战略型布局,且投资额较大;

2、新业务投资驱动增长的企业,如果成功,财务上的特点是营收先保持平稳再加速,某一类成本费用短期内会大增而后慢慢回落,导致利润先降后再大幅上升;

3、在业绩进入向上的“球杆”前,股价也会经历短期的向下“挖坑”,这也成为最佳的投资机会。

对照一下本文的这十个指标,其中的研发投入、行业趋势、并购、动态分配资源、资本支出和差异化竞争这六项都是“拓展型战略”,与传统的“护城河理论”相左,但很符合“曲棍球式投资模型”的选股标准

所以,这里要纠正上一篇文章发出后大家的一个误读,“曲棍球投资模型”不是困境反转,而是一种管理层在主业经营一切正常时的主动出击,是对抗企业平庸化的战略选择。新业务高速增长的同时,原有主务保持稳定,提供宝贵的现金流,以降低资本开支的压力。

所以“曲棍球战略”相比那些行业发生变化后管理层才开始匆忙应对的企业,更具战略前瞻性,值得高度注重。

事实上,即便是这种主动的未雨绸缪,且做对了上面五项措施中的两三件,其成功晋级的概率也只有17~40%,投资的胜率并不高。上一篇我也说过,“曲棍球式增长”失败就会变成“毛脊背”,所以,有必要梳理一下导致失败的原因,以提高投资的胜率,这将是这个系列的最后一篇。

转自:https://mp.weixin.qq.com/s/urXBNJ-9_DK2E6LAgoSr9Q

最容易出十倍牛股的“曲棍球增长模型”

“曲棍球选股模型”之一

 

最容易出十倍牛股的“曲棍球增长模型”

 

1/5

企业利润终将长期下降

马斯克在2018年的一次投资者会议中,直言不讳地说:“护城河的概念很逊(lame),也很古旧(quaint),如果你对抗入侵敌人的唯一壁垒就是护城河,你坚持不了多久,真正重要的是创新节奏,这才是保持住竞争力的核心要素。”

 

不光马斯克,我发现,在投资界被奉为圣经的“护城河理论”,在企业管理界也很少有人提及。管理学更相信,基业长青是一件非常非常困难的事,管理的作用就是为了对抗“企业利润长期下降”的趋势。

 

为什么说企业利润将长期下降?在一个完全竞争的市场达到长期均衡时,必然出现下面的情况:在长期残酷竞争中生存下来的厂商个个具有最高的经济效率,最低的成本,因而仅能获得正常利润,迫使任何新进入的竞争者都无法生存。

 

当然,“长期均衡”和“完全竞争市场”不可能完全实现,价值投资的核心任务是寻找在一段时间内能对抗平庸、维持高投资回报率水平的企业。

 

麦肯锡战略业务的三位合伙人Chris Bradley、Sven Smit和Martin Hirt合写了一本名为《突破现实的困境:趋势、禀赋与企业家的大战略》的书,他们研究了麦肯锡企业数据库中2393家企业15年的财务数据,每一年按20%为一档,以年底利润为标准,将其分为五组。

 

最容易出十倍牛股的“曲棍球增长模型”

 

结果是,五分之一的顶部组平均利润是中部组的30倍,90%的利润被头部公司拿走,中间的大部分公司靠着2%的利润率赚着最辛苦的钱,还有大量的公司因为亏损而走向破产。

 

作者将它们每一年在利润分布图上的移动方向分为三类:向左侧移动、不变、向右侧移动,结果发现,随着时间的推移,这根曲线更陡峭,大部分企业都在向左侧沉沦直到消失,中间三组能进入前五分之一的概率仅为8%,即便是前五分之一也在分化,所有企业的一半的利润被苹果、微软等40家公司拿走。

 

这张图统计的都是能进麦肯锡企业数据库的中大型公司,相当于A股的上市公司,也是近些年行业出清和龙头进阶的过程。

 

我之前的文章《为什么所有的企业最终都会沦为平庸》,从ROE这个核心财务指标趋势向下的角度,也论述过“再伟大的企业也终会沦为平庸”这个观点。

 

所以近两年市场最主流的思想是在前五分之一的企业中,找到排名不下降的,即“有护城河的企业”。

 

但护城河又是如何形成的呢?

 

2/5

战略就是对未来作出反应

茅台的护城河是“茅台”这两个字,而不是赤水河(否则建在河边的所有企业都有护城河了),但“茅台”这两个字的价值,并非凭空而来,而是几十年时间沉淀下来的结果。

 

换句话说,茅台的所谓护城河只是“时间红利”,几十年前的那些当时正确的选择到今天产生的超额回报,品牌护城河的本质是时间的不可逆性——打败茅台唯一的“办法”是穿越到过去跟它做一样的事。

 

从这个意义上说,茅台的品牌护城河价值也在慢慢消逝,因为今天的茅台并没有为未来做什么。

 

很多人会反对这个观点,茅台不是一直在做品牌维护吗,这难道不是在加深加宽护城河?

 

但问题在于,这些动作的前提是假定十几年后的中国人还喜欢高度白酒,但高度白酒其实只是建国以后才在政商高层流行起来,而有相似文化背景的日本韩国都选择了低度酒。

 

没有人知道未来是怎样的,唯一可以相信的是,如果你什么都不改变,你会渐渐“平庸化”,护城河也救不了你,你必须对未来而不是现在做出提前反应,提前布局一些现在不可能产生利润的“未来生意”,这就是战略。

 

一个好的CEO要做两件事情,一是建一个有战略执行力的管理层班子,让企业能高效自动的应对现状,二是作出对未来的战略安排。后者即是“战略管理”,也是投资者分析公司价值的重点之一。

 

我开头提到的《突破现实的困境:趋势、禀赋与企业家的大战略》这一本书的核心价值就是量化了企业战略管理能力的十个关键经营指标,也是我这个系列文章的重点。

最容易出十倍牛股的“曲棍球增长模型”

 

不过在第一篇,我要先介绍一个战略驱动的成长型企业的模型——曲棍球模型,也就是本书英文原名“Strategy Beyond The Hockey Stick”(超越曲棍球战略)的由来。

 

3/5

曲棍球增长模型

分析管理问题,一定要回到管理者视角,思考一下,假如你是这家上市公司的CEO,你将如何制定战略,如何保证战略得以执行?

 

你可以用一堆高大上的词包装战略,没有部门经理会反对战略,他们真正关心的只有一件事——你如何分配明年的资源与预算?

 

战略的核心作用之一就是分配资源,就像战争中的战略决定兵力部署。每年分配预算的部门经理会议才是最重要的战略会议,以下的场景是每一位CEO必须面对的:

 

产品研发部给出了三年十个大方向的新品研发计划,并提出三年增长一倍的研发人员招聘计划;

销售部计划将经销商下沉至更多的四线城市,这也意味着营销费用在此期间将猛增一倍;

市场部认为去年新品没有达到销售预期是因为广告投资力度不够,并花了一个小时介绍“饱和式广告攻击”的理念;

财务部认为,各分公司存在严重不合理的财务开支,建议向各地分公司派驻审计人员,当然目的是招人和更多的授权;

西南分公司认为,本地区基础薄弱,应该给予更大力度的促销支持,而华北分公司提出,去年在弱势地区投放了太多资源,而传统强势地区的不少空白市场点被竞争对手拿走……

 

所有的业务部门都在用各种带英文字母的大趋势大创新词汇堆砌着一个雄心勃勃的增长计划,可字里行间就是两个字:要钱。背后的原因也可以理解,有钱不一定能做出业绩,但没有钱一定做不出业绩。

 

你能说哪一个部门不重要吗?哪一项业务不重要吗?于是,那些战略上的“颠覆式创新”“开拓型业务”,最后落实到预算上,就是把去年的方案略微调整一下:最终,研发费用预算增加半个点,研发人员增长一点(但薪酬水平不能高于企业整体增幅);销售渠道增加几个四线城市,新产品广告投入增长一点,传统优势地区增加一点,薄弱地区也增长一点……

 

如果你觉得某个员工很重要,却不肯给他加工资,就代表他在战略上并不重要。这种撒胡椒面式的投入,你可以称之为“延续型战略”,本质上就是没有战略。

 

选择“延续性战略”的企业作为投资重点,哪怕有护城河,在没有低估的情况下,也只能获得市场平均收益。

 

“做正确的事”比“正确的做事”更重要,这本书的后半部分,也是我下一篇要讲到的,企业在利润曲线上向右移动的动力,50%来自行业因素,“进军什么领域”,是战略中最关键的选择之一。

 

最容易出十倍牛股的“曲棍球增长模型”

 

创业板的第一批上市公司中,上市后涨幅最高的是爱尔眼科和亿纬锂能,但两家企业面对的战略处境大不相同。

 

爱尔眼科生于一个空间广阔的黄金赛道,只要专注,就能获得高速发展;但亿纬锂能就没那么幸运了,上市之前的主营锂原电池业务因为下游的增长空间不足,上市后ROE一路下降至10%,只是从2014年开始,通过收购和投资多管齐下,布局多种锂电池和电子烟赛道,才在2017年之后,将ROE推升至20%以上。

 

很多人认为亿纬锂能的运气好,长期的运气其实就是战略管理能力。锂电池除了新能源汽车电池这个最大的下游之外,还有很多方向,比如各种智能终端、电子烟、二轮自动车、各种电动工具,这些方向,除了技术的变化外,更要求厂商对电池应用新场景的敏感度高,企业的研发更灵活,更有针对性。

 

事实上,CEO并非不知道企业的问题所在,但激进的投资战略不但结果高度不确定,就算最终结果是好的,前一两年仍然会造成企业利润的下滑。如果是职业经理人管理企业,很难做出这样的选择,即便是创始人控制的企业,也常常只是最后选项。

 

这就是“曲棍球战略”名字的由来,新业务创造的利润曲线如同曲棍球杆的球拍部分,先向下才能向上。

 

以近两年的十倍大牛股坚朗五金为例。

 

4/5

曲棍球投资模型

下图是坚朗五金过去十年的营收利润增长,从营收看,2011~2018年都是稳健增长,但从利润上看,2013年以前是快速增长期,2013~2018年是利润停滞期,2017~2018年,利润出现了大幅下滑。

 

最容易出十倍牛股的“曲棍球增长模型”

 

最容易出十倍牛股的“曲棍球增长模型”

 

如果只盯着财报投资,你在2018年年报中看到的是“增收不增利”,糟糕的“收现比”,再加上节节攀升的销售费用率,联系到五金建材这个传统行业,很容易再得出结论:这是一家在过度竞争的行业中利润下降的失败公司。

 

实际情况是,公司从2016年上市拿到大笔资金后,就在行业内率先做了两件事:

 

一个是线上服务平台“坚朗云采”,同时上架自家和其他品牌的产品,让客户实现自主采购,用信息化改造传统的采购流程,让订单的处理周期大大缩短。

 

最容易出十倍牛股的“曲棍球增长模型”

 

更重要的是第二件事,建立全国性的物流仓储配送体系,改变了传统五金企业通过五金店、建材市场来分销的体系,建立以直销为主的销售服务一体化的渠道。并建立了多个生产基地,以缩短补货周期——这正是销售费用率节节攀升的原因。

 

建筑五金件本来是一门没有任何门槛和壁垒的生意,但正是因为这个“大行业小生意”的属性,导致一旦有人对其进行改造,反而能建立起坚固的竞争壁垒。

 

其实只要仔细阅读财报,并不难发现这些原因,但未来是高度不确定的,如果是职业经理人型的企业,CEO可能早就被股东赶下台了,如果基金经理近两年重仓坚朗五金,早就被基民抛弃了。即便是有研究能力的研究机构,也会迫于排名压力,把研究资源集中到“大白马”身上。

 

坚朗五金股价爆发前,从2017年下半年到2019年上半年的一年半时间里,没有任何一个机构能坚持研报覆盖,最后两份研报是2017年9月由天风证券发布的,研报中已经指出了公司的核心增长逻辑:“对标伍尔特,加快直销网点建设”“柔性生产线满足客户定制化生产”,并同时认为“网点扩张拖累了公司利润的表现”。

 

非常遗憾,这种“拖累”还要再延续一年,只是投资者都失去了耐心,研究机构也放弃了跟踪,直到2019年2月份业绩快报发布后,市场发现公司四季度利润大增900%,这才恢复了对公司的跟踪。

 

总结一下“曲棍球投资模型”的三个特点:

 

1、企业在利润没有明显下降之前,率先进行一系列战略型布局,且投资额较大;

 

2、新业务投资驱动增长的企业,如果成功,财务上的特点是营收先保持平稳再加速,某一类成本费用短期内会大增而后慢慢回落,导致利润先降后再大幅上升;

 

3、在业绩进入向上的“球杆”前,股价也会经历短期的向下“挖坑”,这也成为最佳的投资机会。

 

最容易出十倍牛股的“曲棍球增长模型”

 

当然,市场的谨慎并非没有道理,曲棍球战略在没有发生作用前,没有人知道利润到底会不会出现拐点。坚朗五金从2019年开始实行三年股权激励计划,说明公司到了2018年下半年才确信公司即将进入利润释放的“球杆阶段”。

 

局内人尚且如此,更不用说局外人了,毕竟很多公司做出了大胆的转型,却没有走到“球杆阶段”,反而进入了本书所谓“毛脊背”的状态。

 

大部分上市公司在上市后到陷入困境之间的几年,都有几次新业务投入的自救,每一次战略投资,公司总是信心满满,宣称将实现第二次腾飞,而之后的利润大降,公司也都认为是短期现象,是加大投入所致。

 

但不幸的是,公司越折腾越向下,“曲棍球杆”却始终没有来,直到放弃挣扎。作者把每一年新业务向上的愿景与惨淡的现实连在一起,称之为“毛脊背”。

 

最容易出十倍牛股的“曲棍球增长模型”

 

80%的企业无法实现“自己吹过的牛”,为什么会出现“毛脊背”呢?

 

战略不仅仅是选择,而是选择之前预见其困难,选择之后务必要坚持。作者研究比较了这些失败企业的经营数据,总结了几个原因,这些原因,我将在后面的文章中详细分析。

 

5/5

基于新业务驱动增长

随着中国经济规模越来越大,GDP增速向下回归正常水平,A股的成熟型企业越来越多,越来越多的企业为了摆脱走向平庸的命运,必须走出前途莫测的“第二增长曲线”。

 

同时,头部企业在被充分研究后,估值不再有优势,而“曲棍球增长模型”将成为越来越重要的选股思路。

 

基于护城河的选股思维和基于新业务驱动增长的选股思维差异很大,前者就好像选天资好的学生,后者是选最爱学习且最有学习方法的学生,需要对管理能力进行充分的评估。

 

管理能力研究的最大问题在于无法量化,管理理论大部分都是围绕领导力、文化、人才、执行力等等定性因素,定性分析固然重要,但投资总是要回到定量分析上,否则,你把企业的管理能力夸成一朵花,结果财报一季比一季烂,你恐怕自己都不相信自己的研究结果了。

 

本书的作者却认为,“虽然从表面上看战略应该是一个纯粹的智力问题,但实际上,战略问题出现的频率很低,而且具有很高的不确定性,是最不适合由人脑来处理的问题。

 

管理能力是可以量化的,通过战略管理驱动利润增长的企业具有一些明显的特征,下一篇,我将详细拆解作者找到的十个关键经营指标。

转自:https://mp.weixin.qq.com/s/00HtMdHSsguqzH1s3tuL8w

marshmallow,支持 Python 对象和原生数据相互转换的库

在很多情况下,我们会有把 Python 对象进行序列化或反序列化的需求,比如开发 REST API,比如一些面向对象化的数据加载和保存,都会应用到这个功能。

这里看一个最基本的例子,这里给到一个 User 的 Class 定义,再给到一个 data 数据,像这样:

class User(object):
def __init__(self, name, age):
self.name = name
self.age = age

data = [{
'name': 'Germey',
'age': 23
}, {
'name': 'Mike',
'age': 20
}]

现在我要把这个 data 快速转成 User 组成的数组,变成这样:

[User(name='Germey', age=23), User(name='Mike', age=20)]

你会怎么来实现?

或者我有了上面的列表内容,想要转成一个 JSON 字符串,变成这样:

[{"name": "Germey", "age": 23}, {"name": "Mike", "age": 20}]

你又会怎么操作呢?

另外如果 JSON 数据里面有各种各样的脏数据,你需要在初始化时验证这些字段是否合法,另外 User 这个对象里面 name、age 的数据类型不同,如何针对不同的数据类型进行针对性的类型转换,这个你有更好的实现方案吗?

初步思路

之前我介绍过 attrs 和 cattrs 这两个库,它们二者的组合可以非常方便地实现对象的序列化和反序列化。

譬如这样:

from attr import attrs, attrib
from cattr import structure, unstructure

@attrs
class User(object):
name = attrib()
age = attrib()

data = {
'name': 'Germey',
'age': 23
}
user = structure(data, User)
print('user', user)
json = unstructure(user)
print('json', json)

运行结果:

user User(name='Germey', age=23)
json {'name': 'Germey', 'age': 23}

好,这里我们通过 attrs 和 cattrs 这两个库来实现了单个对象的转换。

首先我们要肯定一下 attrs 这个库,它可以极大地简化 Python 类的定义,同时每个字段可以定义多种数据类型。

但 cattrs 这个库就相对弱一些了,如果把 data 换成数组,用 cattrs 还是不怎么好转换的,另外它的 structure 和 unstructure 在某些情景下容错能力较差,所以对于上面的需求,用这两个库搭配起来并不是一个最优的解决方案。

另外数据的校验也是一个问题,attrs 虽然提供了 validator 的参数,但对于多种类型的数据处理的支持并没有那么强大。

所以,我们想要寻求一个更优的解决方案。

更优雅的方案

这里推荐一个库,叫做 marshmallow,它是专门用来支持 Python 对象和原生数据相互转换的库,如实现 object -> dict,objects -> list, string -> dict, string -> list 等的转换功能,另外它还提供了非常丰富的数据类型转换和校验 API,帮助我们快速实现数据的转换。

要使用 marshmallow 这个库,需要先安装下:

pip3 install marshmallow

好了之后,我们在之前的基础上定义一个 Schema,如下:

class UserSchema(Schema):
name = fields.Str()
age = fields.Integer()

@post_load
def make(self, data, **kwargs):
return User(**data)

还是之前的数据:

data = [{
'name': 'Germey',
'age': 23
}, {
'name': 'Mike',
'age': 20
}]

这时候我们只需要调用 Schema 的 load 事件就好了:

schema = UserSchema()
users = schema.load(data, many=True)
print(users)

输出结果如下:

[User(name='Germey', age=23), User(name='Mike', age=20)]

这样,我们非常轻松地完成了 JSON 到 User List 的转换。

有人说,如果是单个数据怎么办呢,只需要把 load 方法的 many 参数去掉即可:

data = {
'name': 'Germey',
'age': 23
}

schema = UserSchema()
user = schema.load(data)
print(user)

输出结果:

User(name='Germey', age=23)

当然,这仅仅是一个反序列化操作,我们还可以正向进行序列化,以及使用各种各样的验证条件。

下面我们再来看看吧。

更方便的序列化

上面的例子我们实现了序列化操作,输出了 users 为:

[User(name='Germey', age=23), User(name='Mike', age=20)]

有了这个数据,我们也能轻松实现序列化操作。

序列化操作,使用 dump 方法即可

result = schema.dump(users, many=True)
print('result', result)

运行结果如下:

result [{'age': 23, 'name': 'Germey'}, {'age': 20, 'name': 'Mike'}]

由于是 List,所以 dump 方法需要加一个参数 many 为 True。

当然对于单个对象,直接使用 dump 同样是可以的:

result = schema.dump(user)
print('result', result)

运行结果如下:

result {'name': 'Germey', 'age': 23}

这样的话,单个、多个对象的序列化也不再是难事。

经过上面的操作,我们完成了 object 到 dict 或 list 的转换,即:

object <-> dict
objects <-> list

验证

当然,上面的功能其实并不足以让你觉得 marshmallow 有多么了不起,其实就是一个对象到基本数据的转换嘛。但肯定不止这些,marshmallow 还提供了更加强大啊功能,比如说验证,Validation。

比如这里我们将 age 这个字段设置为 hello,它无法被转换成数值类型,所以肯定会报错,样例如下:

data = {
'name': 'Germey',
'age': 'hello'
}

from marshmallow import ValidationError
try:
schema = UserSchema()
user, errors = schema.load(data)
print(user, errors)
except ValidationError as e:
print('e.message', e.messages)
print('e.valid_data', e.valid_data)

这里如果加载报错,我们可以直接拿到 Error 的 messages 和 valid_data 对象,它包含了错误的信息和正确的字段结果,运行结果如下:

e.message {'age': ['Not a valid integer.']}
e.valid_data {'name': 'Germey'}

因此,比如我们想要开发一个功能,比如用户注册,表单信息就是提交过来的 data,我们只需要过一遍 Validation,就可以轻松得知哪些数据符合要求,哪些不符合要求,接着再进一步进行处理。

当然验证功能肯定不止这一些,我们再来感受一下另一个示例:

from pprint import pprint
from marshmallow import Schema, fields, validate, ValidationError

class UserSchema(Schema):
name = fields.Str(validate=validate.Length(min=1))
permission = fields.Str(validate=validate.OneOf(['read', 'write', 'admin']))
age = fields.Int(validate=validate.Range(min=18, max=40))


in_data = {'name': '', 'permission': 'invalid', 'age': 71}
try:
UserSchema().load(in_data)
except ValidationError as err:
pprint(err.messages)

比如这里的 validate 字段,我们分别校验了 name、permission、age 三个字段,校验方式各不相同。

如 name 我们要判断其最小值为 1,则使用了 Length 对象。permission 必须要是几个字符串之一,这里又使用了 OneOf 对象,age 又必须是介于某个范围之间,这里就使用了 Range 对象。

下面我们故意传入一些错误的数据,看下运行结果:

{'age': ['Must be greater than or equal to 18 and less than or equal to 40.'],
'name': ['Shorter than minimum length 1.'],
'permission': ['Must be one of: read, write, admin.']}

可以看到,这里也返回了数据验证的结果,对于不符合条件的字段,一一进行说明。

另外我们也可以自定义验证方法:

from marshmallow import Schema, fields, ValidationError

def validate_quantity(n):
if n < 0:
raise ValidationError('Quantity must be greater than 0.')
if n > 30:
raise ValidationError('Quantity must not be greater than 30.')

class ItemSchema(Schema):
quantity = fields.Integer(validate=validate_quantity)

in_data = {'quantity': 31}
try:
result = ItemSchema().load(in_data)
except ValidationError as err:
print(err.messages)

通过自定义方法,同样可以实现更灵活的验证,运行结果:

{'quantity': ['Quantity must not be greater than 30.']}

对于上面的例子,还有更优雅的写法:

from marshmallow import fields, Schema, validates, ValidationError


class ItemSchema(Schema):
quantity = fields.Integer()

@validates('quantity')
def validate_quantity(self, value):
if value < 0:
raise ValidationError('Quantity must be greater than 0.')
if value > 30:
raise ValidationError('Quantity must not be greater than 30.')

通过定义方法并用 validates 修饰符,使得代码的书写更加简洁。

必填字段

如果要想定义必填字段,只需要在 fields 里面加入 required 参数并设置为 True 即可,另外我们还可以自定义错误信息,使用 error_messages 即可,例如:

from pprint import pprint
from marshmallow import Schema, fields, ValidationError

class UserSchema(Schema):
name = fields.String(required=True)
age = fields.Integer(required=True, error_messages={'required': 'Age is required.'})
city = fields.String(
required=True,
error_messages={'required': {'message': 'City required', 'code': 400}},
)
email = fields.Email()

try:
result = UserSchema().load({'email': 'foo@bar.com'})
except ValidationError as err:
pprint(err.messages)

默认字段

对于序列化和反序列化字段,marshmallow 还提供了默认值,而且区分得非常清楚!如 missing 则是在反序列化时自动填充的数据,default 则是在序列化时自动填充的数据。

例如:

from marshmallow import Schema, fields
import datetime as dt
import uuid

class UserSchema(Schema):
id = fields.UUID(missing=uuid.uuid1)
birthdate = fields.DateTime(default=dt.datetime(2017, 9, 29))

print(UserSchema().load({}))
print(UserSchema().dump({}))

这里我们都是定义的空数据,分别进行序列化和反序列化,运行结果如下:

{'id': UUID('06aa384a-570c-11ea-9869-a0999b0d6843')}
{'birthdate': '2017-09-29T00:00:00'}

可以看到,在没有真实值的情况下,序列化和反序列化都是用了默认值。

这个真的是解决了我之前在 cattrs 序列化和反序列化时候的痛点啊!

指定属性名

在序列化时,Schema 对象会默认使用和自身定义相同的 fields 属性名,当然也可以自定义,如:

class UserSchema(Schema):
name = fields.String()
email_addr = fields.String(attribute='email')
date_created = fields.DateTime(attribute='created_at')

user = User('Keith', email='keith@stones.com')
ser = UserSchema()
result, errors = ser.dump(user)
pprint(result)

运行结果如下:

{'name': 'Keith',
'email_addr': 'keith@stones.com',
'date_created': '2014-08-17T14:58:57.600623+00:00'}

反序列化也是一样,例如:

class UserSchema(Schema):
name = fields.String()
email = fields.Email(load_from='emailAddress')

data = {
'name': 'Mike',
'emailAddress': 'foo@bar.com'
}
s = UserSchema()
result, errors = s.load(data)

运行结果如下:

{'name': u'Mike',
'email': 'foo@bar.com'}

嵌套属性

对于嵌套属性,marshmallow 当然也不在话下,这也是让我觉得 marshmallow 非常好用的地方,例如:

from datetime import date
from marshmallow import Schema, fields, pprint

class ArtistSchema(Schema):
name = fields.Str()

class AlbumSchema(Schema):
title = fields.Str()
release_date = fields.Date()
artist = fields.Nested(ArtistSchema())

bowie = dict(name='David Bowie')
album = dict(artist=bowie, title='Hunky Dory', release_date=date(1971, 12, 17))

schema = AlbumSchema()
result = schema.dump(album)
pprint(result, indent=2)

这样我们就能充分利用好对象关联外键来方便地实现很多关联功能。

以上介绍的内容基本算在日常的使用中是够用了,当然以上都是一些基本的示例,对于更多功能,可以参考 marchmallow 的官方文档:https://marshmallow.readthedocs.io/en/stable/,强烈推荐大家用起来。

– EOF –