社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Python

Java帝国对Python的渗透能成功吗?

码农翻身 • 7 年前 • 811 次点击  

引子


Java 帝国已经成立20多年,经过历代国王的励精图治,可以说是地大物博,码农众多。 


可是国王依然不满足,整天想着如何继续开拓疆土, 这一天晚上他又把几个重臣招来商议了。 


IO大臣说:“陛下,现在天下大势初定,我Java帝国已经占据了后端开发,大数据,Android开发等重要地盘,再想拓展殊为不易!” 


 “是啊, 前端被JavaScript所盘踞,我们很难渗透啊。” 线程大臣补充。 


国王点点头,这话不错,JavaScript一统前端,Flash消失了,Applet不见了。想到Applet,国王就一阵心痛,当时Java是靠了Applet才引起码农的关注,一炮走红,后来怎么就不行了呢?


“那人工智能呢?” 国王狠狠地问道。 


“陛下明鉴,人工智能底层都是C/C++的地盘,应用层被Python等所侵占。 ”  JDBC大臣回答。 


“云计算呢?” 


“似乎是Go语言的地盘。” 


 “嘶——” 国王觉得有点牙疼。 


IO大臣赶紧为君主分忧:“陛下,现在群雄涿鹿,八分天下,边境战火连年不息,陛下不仅维持住祖宗的基业,还有不小的扩展,已经是一代圣主了,不过多年征战,民力维艰,老臣有一计,也许能换来奇效。” 


 “爱卿快讲!” 


“老臣以为不战而屈人之兵才是上策,作为世界最强之王国,不仅要武力上震慑群雄,更要输出我堂堂Java帝国之文化和价值观。” 


 “什么文化和价值观?” 


“首先我们要大肆宣扬静态语言的种种好处,比如编译期检查发现错误,代码适合阅读和维护,适合大规模团队合作,口号我都想好了,就叫‘动态一时爽,重构火葬场!’ ” 


“嗯,这口号不错!” 国王赞许,“爱卿真是老成谋国。”


“可是有些语言也是静态的啊!你怎么宣传?” 老对头线程大臣发难。 


“陛下您想想,我们有很多宝贝,” IO大臣根本不理线程大臣, 继续侃侃而谈:“ 比如IoC, AOP,反射、动态代理、泛型、注解、JDBC、JMS...... 还有我们引以为豪的JVM。这些东西,那些国家可不一定有,我们派出传教士,把这些东西灌输给他们的臣民,让他们体会到Java的种种好处,慢慢地就把他们给同化了!到时候他们的码农自然而然就会加入我Java帝国。”


“陛下万万不可,不同的语言有不同的特点,我们的文化别人是接受不了的,到时候只会引起群雄耻笑。” 线程大臣觉得IO大臣脑洞大开,简直是胡闹,非要误国不可。 


“可以一试嘛!” 国王牙不疼了,“此事由IO大臣全权负责,一年后看效果。”


泛型


作为被派往Python王国的传教士,吉森带着IO大臣的重托,风尘仆仆,终于来到了Python 王国。 


IO大臣在挑选人选的时候,有个重要的原则:是Java的死忠粉丝,最好是对其他语言根本不了解,省得思想被污染。 这吉森就是其中的佼佼者。


吉森先找到一个地方安顿下来,然后边四处闲逛, 他惊奇地发现,这里类方法中的self 满天飞, 还有强制代码缩进,果然和我大Java不同,颇有异域风情。  


前面是个茶馆,人声鼎沸, 吉森走了进去,看看能不能牛刀小试,宣扬一下Java的文化。 


 “小二,我观察了半天,你们这里怎么没有讨论泛型啊?” 吉森拉住上茶的店小二。 


 “泛型? 那是什么东西? ” 小二大惑不解。  


“你肯定是个外乡人,不是来自C++就是Java,我说得没错吧?” 旁边不知道什么时候来了一个老头儿。 


“老先生眼光不错,我确实从Java王国来,我很纳闷,这里怎么没有泛型啊,据我所知, 泛型可以在编译期做类型检查,码农们在写代码的时候也不需要做类型的转换,非常好用的啊。”  吉森开始灌输Java的种种好处。 


List files = new ArrayList(); 

String file = files.get(0);  //不必做强制类型转换 

files.add(new File(.....)) ;  // 编译错误  


“外乡人,我们Python中的变量是不需要声明类型的,不会做编译期类型检查,只有在运行时才会检查这个变量到底是什么类型,能否调用它的方法, 你说,我们要泛型有什么用?” 


吉森大惊,卧槽,这IO大臣怎么没告诉自己啊, 人家根本就没这个需求! 


想想我大Java费了那么大劲儿去实现泛型,没想到在Python这里完全无用武之地, 还输出什么文化! 传什么教!




反射


吉森觉得有点被IO大臣坑了! 不过多年的历练只是让他稍微慌乱,他马上稳住神,转移话题: “先生所言极是,晚生还有一个问题,这Python能支持反射吗? ” 


在Java王国,人们经常通过反射的方式来获取一个类的属性,方法,然后根据一个字符串的名称来调用某个类的方法。 


比如有个url :   /user?action=login 


系统根据约定解析它,确定类是User, 方法是login 。 然后就可以把User对象创建起来,通过反射调用login 方法。 


public class User{
    public void login(...){
    ......
    }
}



“哈哈哈,你这个外乡人啊,你知道为什么我们Python是动态语言吗? 我们Python的反射功能不知道比你们Java强到哪里去了!来来来,我给你看个例子。” 


class User:
    def login(self):
        print("this is login")


“现在我打印他所有的方法:”  


methods = [x for x, y in User.__dict__.items() if type(y) == FunctionType]

print(methods)  #输出 ['login']


“接下来我通过反射调用login 方法, 老夫很久没写代码了,可能不太严谨,你明白意思就行。”


url = "/user?action=login"
#从url解析得到类和action,代码略
clz = "User"  
action = "login"


#根据名称获得User对象和方法
user = globals()[clz]()
func = getattr(user,action) #获取login方法
func() #输出This is login


吉森看到这么寥寥几行代码,就实现了基本的反射, 真是灵活啊,这Python真是不错,他都有点羡慕了。


动态代理


不, 我肩负IO大臣的重托, 我是来传教的,不能让这老头儿给洗脑了! 


吉森想起来了一个大杀器:动态代理,这可是Java的一个非常基础的技术,可以在运行时实现类和方法的增强,比如在调用业务方法的前后加上事务管理,日志管理等功能,没有动态代理,AOP就别想了。



吉森说道:“老先生,Python怎么去实现动态代理啊?”


老头儿微微一笑:“Java Class有个缺点, 一旦被装入Java虚拟机,就没法修改了,想对他做增强,只能修改字节码创建新的类,对老的类做封装,就是代理。但是Python是个动态语言,在运行时就可以修改啊,比如我可以动态地给User类增加一个新的属性,这一点你的Java做不到吧?”


setattr(User,"name",'andy')
print(user.name) #andy


吉森看得目瞪口呆,这真是颠覆了自己从小养成的世界观: 一个类在运行期是不能改变的,更不可能去增加什么属性。


老头儿又接着说:“你看看这个User类,和Proxy类,每次调用login方法的时候,我都可以动态地创建一个新的方法出来,在这个新的方法中,就可以做各种手脚了。”


class


    
 User:
    def login(self):
        print('user login')
    def logout(self):
        print('user logout')

class Proxy:

    def __init__(self, target):
        self.target = target

    def __getattribute__(self, name):
        target = object.__getattribute__(self, "target")
        attr = object.__getattribute__(target, name)

        if name == 'login'  :
            def newFunc(*args, **kwargs):  
                print ("login start")
                result = attr(*args, **kwargs)
                print( "login end")
                return result
            return newFunc
        else :
            return attr


u = User()
p = Proxy(u)

p.login() #实际上调用的是动态创建的方法
p.logout() #调用的是原来的方法


“你那个Proxy中的__getattribute__是什么东西啊? ” 吉森看到魔法都在这里,不由得发问。


“每当你去调用一个方法(如login/logout),或者访问一个字段的时候,Python都会通过__getattribute__先找到这个方法或者字段,然后才是真正的调用。”


“奥,原来如此,你通过__getattribute__做了手脚,如果名称是login,就创建新的方法,在新的方法中除了调用老方法之外,还输出了日志。”


“不错,孺子可教!”


吉森现在是真心佩服动态语言了,在Java中必须得在运行时通过操纵字节码来增强,字节码啊,那可不是一般人能玩的。这Python居然在源码级别就把功能给增强了!




锦囊妙计


吉森有点怀疑自己此次Python王国之行的效果了,这可如何是好? 怎么回去向IO大臣复命? 当初可是立下军令状的!


他突然想起临行前,IO大臣曾经送给自己三个锦囊,嘱咐自己只有到了最危急的时刻才能打开,现在不开,更待何时?


往怀中一摸,就发现锦囊只剩下了两个,丢了一个,这回去估计要杀头, 管不了那么多了, 吉森迅速掏出一个,只见上面写着一段话: GIL  (全局解释锁), GIL是Python的命门, 这把超级大锁只允许一个线程获得Python解释器的控制权, 简单来说,同一时刻,只有一个线程能运行!


没想到老头儿淡淡一笑:“Python确实有GIL,可是这程序的瓶颈啊,它不在CPU, 而在于IO, 就是用户的输入,数据库的查许,网络的访问, 线程等到有IO操作的时候,放弃GIL这个超级大锁,让别的线程去执行就是了。再说了,你真想利用多核的时候可以用多个进程啊!”


第一个锦囊妙计被轻松化解, 吉森赶紧掏出第二个,上面几个字:“动态一时爽,重构火葬场。”


“哈哈哈,”老头儿狡黠地笑了起来:“这都是不了解情况的外人的误解,听说过Quora没有? 奥,上不了是吧! 这Quora就是Python写的,人家那测试用例写得非常充分,重构也不怕! 所以啊关键是测试用例!”


第二个妙计又被化解, 吉森彻底没辙了。



真相大白


看到吉森的神色变化,老头儿开始表明身份:“实不相瞒,老夫乃是Python国王的特使,我们的探子早就听说你们Java那什么破传教士计划了,你一进入我国,就被盯上了,国王特地派我来,看看能不能说服你,留在我国。”


吉森想想,回去也无法交差,这Python似乎还不错,进退两难之际,不妨先妥协,以图将来,于是点点头答应了。


一年以后, IO大臣开始盘点传教士计划,发现回来复命的寥寥无几,尤其是去Python王国的吉森, 他怎么一点消息都没有呢? 是时候再派一个人去了......




个人广告时间, 知识星球“码农翻身”特价优惠中,原价128元/年, 优惠价:99元(截止到2月28号)。


星球详细介绍猛戳: 码农翻身知识星球


对于加入知识星球的同学提供特别的福利,即 编程提高群第一季第二季的部分“加餐”视频:


漫谈计算机组成原理和计算机编程语言

程序的机器级表示

漫谈操作系统之虚拟内存

进程和线程

新人在职场

Java 并发编程

如何用 Antlr 实现自定义的简单脚本语言

缓存

BTree 及其在数据库的应用

分布式文件系统 FastDFS


今年会再额外送5个


Web安全

字节码和AOP

Web SSO

微服务入门

漫谈文件系统


相信这些视频就能值回大部分票价了, 想加入的要尽快了,优惠二月底截止。

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/29164