7

Python is ugly

 3 years ago
source link: http://maskray.me/blog/2012-12-26-python-is-ugly
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

False values

这些都是false value:None, False, 0, [], {}, ''。判断empty的应用场景可能多些,如果像Ruby那样只让nilfalse为false就好了。

Trailing colons

if True:
print 'hello'

写成这样如何?

if True
print 'hello'

Single/double quotes

Python不区分单/双引号,失去了string interpolation的好处,另外就是需要尽可能少escape字符时也带来了麻烦,当然可以用triple-quoted string和raw string来代替,但毕竟繁琐了些。Raw string的设计还能接受,但为什么不引入这个:

%w(zero one two three)
=> ["one", "two", "three"]

dunder

  • __len__: 为什么使用len(obj)而不是def len():obj.len()呢?
  • __mul__: def *(self, rhs):会更清晰些吧

随处可见的lowercase的标准库类名和函数名。

  • CamelCase:collections.OrderedDict
  • nocase:collections.defaultdict, collections.namedtuple

map/filter/zip

  • 产生序列的:map|filter|zip
  • 产生iterator的:itertools.i(map|filter|zip)

为什么对于listiterator要有两套功能相近的函数呢?如果把map设计成这样:参数为list就返回list,参数为iterator就返回iterator。这样就不需要另成一套的itertools.i(map|filter|zip)了。

Context manager和with statement

with可能借鉴自Lisp的with-* macro,实现的功能是wrap一段代码,在其执行前后执行自定义的操作。功能和这个Haskell函数类似:

bracket :: IO a -> (a -> IO b) -> (a -> IO c) -> IO c
-- Defined in `Control.Exception.Base

我一直觉得这个feature是不值得成为关键字的。如果改造一下变成Smalltalk/Ruby的block那种形式会好很多。比如如下Ruby风格的代码:

def pre():
print('hello')
def post():
print('world')
with pre, post do
print(', ')

再注意__exit__的类型签名:

def __exit__(self, type, value, traceback):

后三个参数都是用来表示异常的,异常是不是special enough以至于可以break the rules了?

One-expression lambda

因为Python强制的off-side rule,超过一个表达式的语法确实很难设计。我想到的是Ruby风格的block。

List comprehensions

体现语言表达能力的结构,不过顺序和习惯有些差异:先写出操作,后写出执行操作的对象。Smalltalk/Ruby风格的cascading加上block可能更自然些:

(1..100).select {|x| x % 3 == 0 }.reverse
list(reversed([x for x in range(1,101) if x % 3 == 0]))

如果Python能采用Haskell的简约写法也不错:

reverse [x | x <- [1..100], x `mod` 3 == 0]

yield

Python的yield用于实现iterator,给callee提供值。如果像Ruby那样,yield的作用是调用一个callback会更加灵活一些。

幸好有PEP 342把yield改成双向的了,实现了coroutine,可以实现一些比较强大(花哨)的结构如Monad

Python设计很丑陋,但是还得用。scapy、scrapy、scipy、matplotlib、pil都是以后打算了解的东西,而它们都没有成熟的同等功能的Ruby替代品。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK