我问过两位以前的同事,如果我想学python,要怎么学?一位说,编程语言相通的地方很多,如果有一些其他语言的基础,比较着去学,会容易一些,还有一本很厚的《python学习手册》,也值得看一下。另一位说,廖雪峰的博客不错,可以参考。
其中一位同事大学期间被交换到瑞典,呆了五年。
有一次,我问他:你十几岁就开始写游戏程序,在国外是不是很厉害?
他说:不是的,那些德国程序员都是祖传的,几岁就开始写了。
另外一位同事,属于野生程序员,一个人可以搞定很多事情,就是一回头把事情搞定的那种程序员。
我最近也在学R语言的面向对象编程。顺便落实一下两位前同事的建议。
这里参考了张丹老师的R语言基于R6的面向对象编程和廖雪峰的Python面向对象高级编程。当然还有那本《Python学习手册》。
两种语言一起学,并不是一件容易的事情。首先,得有一个比较合适的学习环境。有些书上提到,初学者不要在IDE上学习编程语言,那是学不会的。不过,这事儿好像也没那么绝对。
这里推荐使用Rmarkdown工具。这个工具是谢益辉大神的得意之作。有点类似 Python的 Jupyter Notebook,我用 R用的比较多, 对Rmarkdown熟悉一些。
Jupyter Notebook跨语言使用还是要做一些配置工作,这个有点烦。Rmarkdown会好很多,只要安装Rstudio即可。
我的学习环境如下图所示,我用的是 Rstudio-server,这是一个服务器版本的Rstudio,在浏览器里就可以直接使用R语言。服务器版本的好处就是可以拉上几个人协同开发,只要服务器的资源充裕,再也不用要求程序员开发机必须4G内存了,现在内存是真贵啊!我想换电脑,都只能从二手的找起,各位如果有好的二手资源,帮助提供一下信息。
这张图里可见,我们可以新建很多类型的东西。我最常用的是R Script,然后是Rmarkdown。上周同学聚会的时候,同学特意问我用的是不是脚本语言,我解释地有点心虚,不过《Python学习手册》也有那么一节讨论“Python算不算脚本语言呢”,作者说“这取决你问的标准”。所以,把标准放低的话,R语言也算是一门脚本语言。
R语言也可以开发web应用,其中Rstudio公司提供的工具是Shiny。我用的不太好,设计的界面稍微丑了点,速度慢一些(怎么也不能和谷歌的V8比啊),但交互性还蛮好,用了一些图表工具,像echarts、plotly。我个人还是喜欢plotly多一点点,提供了R语言的接口,这样我就不用学JavaScript了,但是我觉着JavaSript还是要学一点的,如果想做一个强壮web应用的话。
再就是 “ C++ File ” ,由于Rcpp工具的出现,越来越多的R语言应用底层其实都是C++,这对提升运行速度、降低资源消耗是很有利的。
用Rstudio-server,还有另外一层意思,就是linux的Rstudio桌面版并不支持中文。这个蛋疼的事情,引发了中土大唐人士的极大不满,纷纷要求谢益辉大神向Rstudio公司提出抗议。谢大神无奈地说:“作为Rstudio公司唯一的华人工程师,实在是太微弱的声音了”。没办法,我只好安装Rstudio-server了,浏览器对中文的支持还是杠杠的。
我们再看一下Rmarkdown是如何同时使用Python和R语言的。如下图所示。
R代码用Rmarkdown的语法嵌入,即三个反引号开始一段代码```{r}
和三个反引号```
结束一段代码。
类似的,Python代码用Rmarkdown的语法嵌入,也是三个反引号开始一段代码```{python}
和三个反引号```
结束一段代码。
我们还可以嵌入bash和Python3,甚至数据库等等。
好了,我们回到R语言发展面向对象编程的主题。
R语言发展面向对象编程的过程比较曲折。从S3、S4、RC一路发展过来,到现在的R6。用Hadley Wickham的话就是,R6终于和Python、ruby、Java这些面向对象语言有点像了。
这里把张丹老师的R语言博客和廖雪峰老师的Python博客中相似的部分,拿出来学习一下。
张丹老师在R6类的主动绑定里这样讲:“主动绑定(Active bindings)是R6中一种特殊的函数调用方式,把对函数的访问表现为对属性的访问”。
廖雪峰老师在使用@property里这样讲:“还记得装饰器(decorator)可以给函数动态加上功能吗?对于类的方法,装饰器一样起作用。Python内置的@property装饰器就是负责把一个方法变成属性调用的”。
这么说,R语言的主动绑定和Python的使用@property,有些相似。
我们看一下张丹老师举的例子。
使用主动绑定之后,函数既可以像一个方法,也可以像一个属性。这个是很便利的。
如果使用Python的@property装饰器,根据张丹老师这段R代码,改写成Python代码如下:
如果仔细观察的话,R的主动绑定和Python的@property装饰器还是有一些差异的。特别是 'active' 传参那一块。代码看起来很像,实际用起来还是不一样的。
张丹老师在实例化对象的存储里这样讲:“实例化对象的存储还有另外一方面的考虑,由于类中的变量都是存在于一个环境空间中的,我们也可以通过手动的方式找到这个环境空间,从而进行变量的增加或修改。 如果随意地对环境空间中的变量进行修改,那么会给我们的程序带来一些安全上的风险,所以为了预防安全上的问题,可以通过R6Class()的lock参数所定环境空间,不允许动态修改,默认值为锁定状态不能修改。”
张丹老师提供了下面这个例子。'lock = TRUE'锁定后,就不可以对实例添加新的变量(属性)了。
廖雪峰老师在使用__ slots__里这样讲:“如果我们想要限制实例的属性怎么办?比如,只允许对Student实例添加name和age属性......为了达到限制的目的,Python允许在定义class的时候,定义一个特殊的__ slots__变量,来限制该class实例能添加的属性”。
用__ slots__ 改写上面这个例子,如下图所示:
张丹老师描述了R6类的对象的静态属性“用面向对象的方法进行编程,那么所有变量其实都是对象,我们可以把一个实例化的对象定义成另一个类的属性,这样就形成了对象的引用关系链。。。当属性赋值为另一个R6的对象时,属性的值保存了对象的引用,而非对象实例本身。利用这个规则就可以实现对象的静态属性,也就是可以在多种不同的实例中是共享对象属性,类似于Java中的static属性一样。”
张丹老师举了下面一个例子。
我在廖雪峰老师的博客里找了半天,并没有找到对应的对象的静态属性,但试着写了下面这段代码,发现python也有对象的静态属性。
廖雪峰老师在类和实例一节中提到“类是创建实例的模板,而实例则是一个一个具体的对象,各个实例拥有的数据都互相独立,互不影响”。如果考虑到对象的静态属性,各个实例之间可以共享相同的属性,修改其中一个实例的属性,也会影响其他实例的属性。所以“各个实例拥有的数据都互相独立,互不影响”这一结论是不太严谨的。
小结一下:
Rmarkdown可以提供同时学习多种编程语言的环境,通过比较学习,可以加深理解。
这里提到的R语言和python语言在面向对象编程方面存在一些相通的地方,讲的有点浅,没有举更多例子。
表姐有次问我:你都这么大了,怎么还学啊?
不学不行啊,我没有张仪的三寸不烂之舌,只能不停的敲打自己的饭碗,所谓笨手笨脚的饭碗,就是指这个吧,辛苦是肯定的。