天问

浅谈Python多奇葩

行内人员都知道,现在很多培训机构大肆吹捧python多牛,爬虫用python,数据分析用python,大数据开发用python,网站开发用python。其实,一般厉害的人,都不在培训机构。。 ------------------引

(1)奇葩main函数

和java/C++一样,Python也提出main函数概念。java中main函数是一个程序的唯一入口,一个程序只能有一个main函数。程序首先执行main函数中的代码!这个很好理解。

if __name__ == "__main__":

python最开始和R语言类似,一行一行执行。程序入口就是第一行!那么加入main函数概念,那python就是要首先执行main函数吗?NO!!!main函数居然不是入口函数的作用。。那具体有什么作用,自己google!特奇葩!特鸡肋!

(2)一个文件里面多个main函数

我去!一个项目中,每个.py文件都写一个main函数,这都不算,有些.py文件里面,居然还有两个main函数!!对于程序阅读来说,简直无语了,我有洁癖。。。

这是在xx-net“大型”项目中看到了一幕,这代码写的太恶心了。

(3)tab严格对齐

仔细看,下面代码有什么区别,左边是错误代码,右边正确代码:

代码都一样咯,那就是python中最低级的错误,空格多了和少了的问题。下面揭晓答案:

左边有16个点,也就是16个空格,右边20个空格。作为洁癖的我,这种规则我当然可以接受了。

对比java/R/Scala/Ruby/Kotlin等所有语言,Python开了先河。即使go语言这种精简语言都不做这个限制,因为代码复制的时候,会出现一些变化。所以也就奇葩了。

(4)包发布命名问题

在其他所有语言中,java采用maven管理依赖,js采用npm管理依赖,C++使用nuget管理以来。php使用composer管理依赖。docker采用docker hub管理依赖。这些都一个共同特点,每个包由 "username/packagename:version"组成,而python包则“package=version”。没有用户名,那么就有一个问题,我不知道这个包是谁开发的!这个包的使用说明也没有!!

pip install numpy

执行完了之后,你知道怎么用这个包吗?NO!!!可以说和R语言包管理一样,但是R语言至少有一个help方法:

help(package='ggplot')

(5)Python也仿了一个ggplot

做R语言分析的都是数学同学,而用Python语言的绝大数可能是个培训班出来的大专生。这里我不是瞧不起大专生,我想说的是,python中ggplot的开发者不是R语言ggplot的开发者。所以两者是完全不一样的。可以说是山寨再好不过了。Python中可视化用的多的是matplotlib,而 ggplot 要作图,还得依赖Pandas!!

(6)Python2,python3你分得清吗

新学习Python的人,建议直接跳过Python2!因为Python十分不稳定,改动特大!python2中有很多非人类的奇葩规则:比如

1/2=0 #假除法 1//2=0 #真除法

print xxx 改为: print("xxx")

Except E e:xxx 改为 Except E as e:

不比如了,如果你深入学习。在使用python2实际用中会发现很多奇葩地方。。。

(7)httplib, urllib(urllib2,urllib3)你们分得清吗

在做爬虫开发的时候,用的最多的包就是urllib,你到国内某搜索引擎可以找到很多重复的“教程”。复制代码一跑,就出错!

原因就是 urllib 包不稳定呀,更新频繁,又要兼容老用户,所以干脆推出一个urllib2,又想到新功能了,又搞出一个urllib3出来。。。我的建议:

python3:urllib3

python2:urllib,urllib2

类似的 ggplot和ggplot2有啥区别知道了吧,类似的还有:Httplib和Httplib2,Pypdf和Pypdf2,Markdown和Markdown2。。。。。

哪天我心血来潮,搞一个urllib4上传上去,然后在国内某搜索引擎推广一下。。说不定大家都以为 urllib 又更新了呢。

(8)普通变量真假赋值

首先定义age=12,然后改变其值age=1。结果发现没改变!

真正做法呢,为了解决这个奇葩,python引入 global 声明:

没错,每次改变全局变量的时候,都需要加global,global,global。。。

(9)对象(list/set)真假赋值

定义ages;然后ages赋值给ages2;改变ages2的值,则ages也会改变吗?

你可能会说,肯定不会改变了,ages和ages2是两个不同变量。怎么可能会同时变?上面的结果确实是没有变,然后你看下面改变ages2的值:

ages2.append(66) 改变的是ages2的值,可事实却连ages也改变了!!严重bug!!为了挽留点面子,python提出对象赋值不能用等号,需要用copy()!

(10)沙雕copy.copy()

上面执行ages.copy()的时候,copy方法是list的方法。但是其实python3还自带了一个copy包!提出一个深浅复制的奇葩概念!

我们已经知道对象赋值不能用等号 b=a是错误的,那么使用b=a.copy()就一定对吗?也是错的!!! a[3].append('cccc') 之后你就会发现同样的bug!!a改变了,b也改变了。。。。

我改变a的值,关你b半毛钱关系呀???然后python3扯出一个深复制概念,叫copy.deepcopy()。。。所以注意,以后对象赋值,要深复制!!deepcopy!!

(11)奇葩函数:函数里面写函数

这是一个奇葩程序员的代码,功能就是打印当前时间戳,其实一行代码就可以解决的:

一行代码:t1= int(round(time.time() * 1000))

非要搞个函数的话,正规写法:

(12)奇葩函数: 函数链式写法

java中就有链式写法,比如对象User.add(1).add(1).mix(2)...每次调用函数都返回User对象,而User对象又可以调用add()方法。这样就可以一直写。。python也想学学链式写法,不过写法就奇葩了:

这是一个所谓的“牛人”写了一段奇葩的代码,函数里面写类!写类也就算了,返回的居然是自己,然后又返回自己!返回两次。其实思想也就是java中的User对象调用子方法,然后返回User对象,循环调用。。但是正确调用不应该是:

add(2).add(3).add(5)吗?怎么写成add(2)(3)(4)。上面这位小子可能add(2)返回整数,而add()不是AddNum()类的方法,所以虽然Return了两次AddNum(),但都只能调一次。。。

add(2)(3)(4) 这种写法怎么理解?add()是一个函数,函数后面()带参数就会返回一个结果,比如2。然后再括号,又表示返回的值也是一个函数!函数带一个变量还是带3个变量????正确写法应该是:

所以,网文少看,认真做学问的很少。大多数学点皮毛就出来卖弄了。。由于python语言不像java/C++等严谨,入门又简单,于是就会出现各种奇门遁甲之术。。。

(13)奇葩类

讲了这么多才讲到类。看看类有什么奇葩的:

修改子类,父类不变。这个没问题。修改父类,某些子类变了!!!这也太奇葩了,和之前的list赋值类似,list赋值还可以deepcopy解决,父子类赋值的话。。。没救啦。。

问题出在哪呢?python是一门脚本语言,本不该又开发web,又开发爬虫,又开发数据分析。每一门语言都有各自的特长,比如go语言在服务器端开发十分高效,php语言写web最好用,java做企业级系统。nodejs写一些漂亮的跨平台应用。

Python就用在数据分析上,回归最开始的初心,结合pandas,numpy,tensorflow,基于jupyter notebook。代码一行一行跑。啥奇葩问题都不会存在!!

博客地址:http://blog.yoqi.me/?p=15985
扫我捐助哦
喜欢 1

这篇文章还没有评论

发表评论