如何为 Python 添加魔幻语言特性?

2015-08-16 13:59:01 +08:00
 Feiox

Ruby 魔幻的语法对于写抽象轮子(如 ORM、Web 框架)似乎如鱼得水。
很多魔幻特性对于 Python 这样一个简约语言好像难以实现,那么各位在造轮子时如何模拟实现这些魔幻特性的呢?
(我很同意 RoR 的观点,外部接口要简单、内部实现要魔幻 ~)

或者,你贴出一段高度抽象、玄机、黑魔法、充分利用 Python 自身语言特点的代码?
(如:利用 yield 、利用 Magic method、利用元类、利用函数也是一个对象、扩展语言自带对象、利用装饰圈等等等)


另外,我想请教一下我遇到的这两个问题要如何解决:

  1. 如何实现:读取函数定义时的形式参数名?不使用关键词参数时获取传入的参数名?
  2. 当用装饰器装饰一个类方法时,如何获取该类方法所属的类呢?
5126 次点击
所在节点    Python
30 条回复
bingwenshi
2015-08-16 14:08:09 +08:00
> 或者,你贴出一段高度抽象、玄机、黑魔法、充分利用 Python 自身语言特点的代码?

除了装逼,还有什么意义么? 真正好的代码是可读的代码
GPU
2015-08-16 14:09:56 +08:00
先收藏 。看能不能养肥。
Feiox
2015-08-16 14:12:46 +08:00
@bingwenshi 比如,这样做是不是装?

用装饰器将一个函数标记,初始化模块的时候遍历该模块中这部分被标记的函数,并对其做进一步操作
形如:
@ my_decorate
def func(): pass
这功能利用了 function 也是对象这一特点,动态添加其属性 func.__dict__['be_add'] = True
AlexaZhou
2015-08-16 14:13:56 +08:00
个人认为实现要优雅,顺带着可以魔幻一把,然而为了魔幻而魔幻并没有意义
justahappy
2015-08-16 14:14:16 +08:00
@bingwenshi
> 真正好的代码是可读的代码
搞得你是大神一样。。。。
这种套话就跟“语言只是工具”一样,你有资格说这种话?你设计过几门语言?
装逼?你有资格装么?装个我看看?
Feiox
2015-08-16 14:21:18 +08:00
@AlexaZhou
动态语言大多有自省这一神奇的语言特性,很久看过一个帖子 http://www.cnblogs.com/huxi/archive/2011/01/02/1924317.html 将 Python 自省的,感觉不错,现在工作了用的也多。
我们团队在写各种抽象工具的时候,代码确实魔幻了一些,但那些库对外的接口一般的经过多轮讨论确定规范、无歧义、完全解耦、简单才会放给开发组用。(尤其是上了 DSL 之后,内部实现更魔幻了哈哈)所以,我们经常维护的业务代码确实可读性很有必要,但工具库的实现,咱 Python 到底可以完成什么样子呢?
@justahappy 这帖子 ~ 额 ~ 咱是好孩子不吵架的 :P
nkssai
2015-08-16 14:25:00 +08:00
其实你的意思就是用Python写DSL嘛。Python写DSL的能力应该和Ruby相当,不过有些地方写起来不那么漂亮而已。简短的例子的话,前两天正好用了https://github.com/michaelliao/sinaweibopy/blob/master/weibo.py
这个挺简单的,依靠__getattr__等函数,简化了使用库的成本。
gamexg
2015-08-16 14:27:16 +08:00
并不魔幻的一个例子

socket5代理实例 提供的接口 = socket module。也就是完全把代理实例当作 socket module 使用,多重代理嵌套也不需要特殊操作。

如果一只鸟走起来像鸭子,叫起来像鸭子,那我们就可以把它当作是鸭子了
mengzhuo
2015-08-16 15:10:15 +08:00
至今见过最魔幻的应该算pony ORM:
select(c for c in Customer if sum(c.orders.price) > 1000)
直接转成SQL

从业三年表示楼主算典型的做太少,想太多
现实团队中web、game server所有用Python的,都是趋向于原始的做法
因为连列表推导都会debug困难,没办法trace,虽然不牛,但是朴实,明确,
也正是this中的:Readability counts.

每当团队里有人写了不明确的推导,不合理地使用metaclass,我都会苦口婆心地劝他多读读this
Feiox
2015-08-16 15:22:45 +08:00
@mengzhuo 额,您所说的问题我也听说过、见过。最原始的做法,是不是就是指的仅用基本的语句,高级特性(如自省、迭代器、生成器、装饰器)都不用呢?
不过我个人认为,可读性并不一定是指这样的。我们在工作中,规范上明确讲业务实现要代码、命名明确,抽象工具库的接口要简单易懂,抽象工具库的实现要多注释和文档、多测试。这样最容易出错和更改的业务部分保持代码的易读,接口调用明确。这样的代码可读性也是非常好的。
额,我从业时间短不敢多说,但,感觉还是和团队风格是不是有一些关系?
neoblackcap
2015-08-16 15:47:00 +08:00
同理,用Python写DSL肯定不如ruby好看(语法上,ruby解析器可忽略括号导致DSL看起来可以更接近自然语言),若是要像ruby一样看起,那么久要用ast包。
yakczh
2015-08-16 16:51:43 +08:00
求1-4之间的整数加起来之和等于5的全排列
----------------------
for a in (0..4) do
for b in (0..4) do
for c in (0..4) do
for d in (0..4) do

if a+b+c+d ==5 then
print a,b,c,d
puts
end

end
end
end
end

vs
------------------------
(0..4).each{|i| (0..4).to_a.permutation(i).map{|x| print x if x.inject(&:+)==5 ;puts } }
virusdefender
2015-08-16 16:51:44 +08:00
meta
9hills
2015-08-16 17:56:46 +08:00
@Feiox 不是不用,而是不要刻意用。

Pythonic
xiazi
2015-08-16 18:58:12 +08:00
不要用继承来当接口,不要有很多的抽象层

内部实现尽量扁平化,方便debug,方便测试
Feiox
2015-08-16 19:56:25 +08:00
@xiazi 抽象层的问题,我看到有很多人批评《重构》那本书中的观点,同样的有很多人反对设计模式。
但,至少我看到过的很多代码,将业务逻辑放给新员工,抽象层放给优秀的员工,这样可以更好的解决团队代码质量的问题。并且,很多包含技巧、重复的代码出现在业务层面,难道不是更容易犯错吗。对于 debug 和 测试,良好的构架和抽象可以分离不同层级的代码,降低耦合性,低耦合之后不是反而更容易测试吗?
不过,Python 的函数调用开销很多,这也是我一直头疼的。
chengzhoukun
2015-08-16 19:56:49 +08:00
http://pycon.b0.upaiyun.com/ppt/shell909090-meta-class.html

这是一篇介绍Python元编程讲得比较好的
lcqtdwj
2015-08-16 20:22:15 +08:00
1.感觉要分使用的场景
2.类方法第一个参数就是class,在decorate里应该能轻易捕获吧

我跟LZ想法一样,内部的魔幻是为了使用接口的简便。python之所以这么容易上手,就是因为有那么多现成的接口简单的库。库作者都很伟大呢
mengzhuo
2015-08-16 21:42:24 +08:00
@9hills 对的呢

@Feiox

刻意在不需要的场合用这些“高级货”,有点像内功不够,偏学最高级的武功,会走火入魔的

但是不是说现实编程中不需要
比如:
1. 一个实例中某个属性,必须通过计算得出,但又不是每次调用实例都需要,那么你就需要lazy object
2. 某个函数接口需要调权限校验,那么你就需要decorator
3. web中最常见的,session的读写、函数执行计时,需要middleware、singleton、local.local
4. 如果要编写ORM,那么metaclass是必须要会的
5. 如果做网络编程,那么协程是必须要要会的

最重要的其实还是算法,数据结构( ´ ▽ ` )ノ(算法苦手……)

比如,最近工作中我在实现一个函数:抽奖N次(>200),每次抽奖大于指定概率就发奖。
有同事就用了yield做生成器循环并用gevent.sleep(0)切出协程,看起来节省时间,并且了解了gevent协程的特性
但是实际上……
因为是二项分布,所以只需要python的一次random.gauss就可以算出来了( ̄▽ ̄)
nightv2
2015-08-16 23:05:10 +08:00
过两天看看有没有什么不认识的东西

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/213529

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX