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

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

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

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


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

  1. 如何实现:读取函数定义时的形式参数名?不使用关键词参数时获取传入的参数名?
  2. 当用装饰器装饰一个类方法时,如何获取该类方法所属的类呢?
5198 次点击
所在节点    Python
30 条回复
xierch
2015-08-17 00:07:46 +08:00
monkey patch 算魔幻么
wyxfcy
2015-08-17 00:52:02 +08:00
难道不是hylang?: http://docs.hylang.org/en/latest/
xiaket
2015-08-17 09:19:10 +08:00
顺着这个主题推荐Pro Python和Fluent Python这两本书
saber000
2015-08-17 13:14:42 +08:00
> 如何实现:读取函数定义时的形式参数名?不使用关键词参数时获取传入的参数名?
[n for i, n in zip (
range (func.func_code.co_argcount ),
func.func_code.co_varnames
)]
# func 是个函数

> 当用装饰器装饰一个类方法时,如何获取该类方法所属的类呢?
装饰器模式不是能拿到 self 吗?self.__class__不就是了?或者改成 descriptor
poke707
2015-08-17 13:43:17 +08:00
解答 LZ 的最后提到的问题
1.在 function 定义内调用 inspect.getargspec (<function_name>),
2.在类定义时,类方法还只是普通 function ,类定义完成后才加工成类方法(有 im_class,im_self 等属性),所以在装饰器拿到的并不包含类信息。个人认为无法,若有望告之。
msg7086
2015-08-17 15:10:49 +08:00
rubyu 和 python 的理念相差太远。
写 py 就应该代码干净清晰易懂,写 ruby 就应该写得魔幻然后让测试代码来保证正确性。
xiazi
2015-08-17 20:13:50 +08:00
@Feiox
我觉得抽象层会让以后添加新功能很麻烦(因为新功能一般需要改动底层的东西),还有就是抽象层多了 call stack 会很深,对于代码的非原作者了解代码很费时间(因为大部分情况除了看 API 的文档外,还要看源代码才能理解这个函数的具体作用)。我觉得这篇 blog 的观念很好: http://www.yinwang.org/blog-cn/2015/06/14/dry-principle/

对于代码的复用我觉得 reactjs 里面的 component specs 的方式就比 subclass 的好, component 定义的任何变量或方法都不会跟父类冲突,父类决定了那些方法能被子 component override ,那些是被 chained call 等.

一般魔幻的东西会隐藏很多内部的 call ,这一点我觉得有背于 explicit is better than implicit 。比如 with 的作用大部分相当于 try finally ,我宁愿直接用 try finally 。大部分 OOP 语言的 this 也是,而 python 里的 self 就比 this 灵活得多。

问题 1. 可以参考: https://github.com/geertj/gruvi/blob/master/lib/gruvi/util.py#L52 其中的 wrap 函数。
invite
2015-08-18 07:28:44 +08:00
看完回复,果断学 python
Feiox
2015-08-18 09:22:05 +08:00
@xiazi 哈哈,感谢你提供高质量讨论。
在我有限的职业生涯中高手菜鸟都见过,对于 DRY 、 KISS 这些编程箴言我个人觉得更多的是指导菜鸟,因为他们的代码往往重复、混杂。对于合格工程师,自然不必太强调这些,而对于他们,优雅的接口设计和稳健的代码实现才是他们关注的重点。对于抽象的层次,我们目前采用的方式是对非业务的通用功能抽象、对业务代码少抽象。比如,在目前项目中,我们的业务逻辑部分大多是直白的代码描述和接口调用,但对在权限管理、处理缓存、数据处理、异步操作(请求其他接口)、计数器等操作往往都是抽象出来。但同时,为了避免过度抽象,我们还要求在模型定义、业务接口调用等方面禁止使用继承。(对于王垠,在我学识尚浅的时候还是很崇拜他的,但后来玩的多了,发现他虽然还是正确的,但他讨论的层次(除编译优化)往往并不深入)

对于 with 等语言元素,用不用我想是属于个人风格的问题吧。大家喊了 lambda 这么多年 GvR 就是不改,他也算偏执的追求简洁吧,但 with enum 这些关键词、标准库,我想他们一定是经过设计者深思熟虑的存在的非常有意义的。对于 explicit is better than implicit 这个,我看过有些人写的代码,使用 value[n] 引用的方式修改不该修改的内容,在业务代码里写多层嵌套,滥用装饰器、闭包等特性,我也是反对的。

reactjs 所倡导的组件化,我也是支持的。多用接口,少用继承。接口可以保证调用明确,继承往往存在隐式转换(这也是我不喜欢 C++ Java 的原因)

我不喜欢 Ruby 的魔幻,热爱 Python 的简洁。 P.S 我是支持 Python 3 的。
Feiox
2015-08-18 09:33:57 +08:00
@poke707 我发现了,取到的都是函数对象 ~
@lcqtdwj 并不是这样的,你可以自己试一试。原因是 @poke707 所说的。

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

https://tanronggui.xyz/t/213529

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

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

© 2021 V2EX