当前位置:  开发笔记 > 编程语言 > 正文

Python宏:用例?

如何解决《Python宏:用例?》经验,为你挑选了5个好方法。

如果Python有一个类似于Lisp/Scheme的宏设施(比如MetaPython),你会如何使用它?

如果你是一个Lisp/Scheme程序员,你会使用什么样的宏(除了在Python中有明确的语法并行的东西,比如while循环)?



1> RossFabrican..:

我相信宏与Python的文化背道而驰.Lisp中的宏允许大球接近泥 ; 您可以重新定义语言,使其更适合您的问题域.相反,Pythonic代码使用Python最自然的内置功能来解决问题,而不是以一种在不同语言中更自然的方式解决问题.

宏本质上是unpythonic.


但这有点乞求这个问题,不是吗?如果通过该逻辑将宏添加到语言中,它们将变为"pythonic",就像装饰器,列表推导,条件表达式,元类等在将它们添加为内置之前不会被视为"pythonic"在语言的功能.什么使得宏比使用sys._getframe()和元类更不像pythonic?
你是对的,但这通常是参考PEP 20 http://www.python.org/dev/peps/pep-0020/等概述语言的一般哲学.在这种情况下,我认为宏可能会违反几个链接指南.

2> Li Haoyi..:

这是一个稍晚的答案,但MacroPy是我的一个新项目,它将宏带入Python.我们有一个非常重要的演示列表,所有这些都是需要宏来实现的用例,例如提供一种非常简洁的方式来声明类:

@case
class Point(x, y)

p = Point(1, 2)
print p.x   # 1
print p     # Point(1, 2)

MacroPy已被用于实现以下功能:

案例类,Scala中易于使用的代数数据类型

功能编程世界中的模式匹配

尾调优化

Quasiquotes,一种操纵程序片段的快速方法

字符串插值,许多语言的常见功能,以及Pyxl.

跟踪和智能断言

PINQ到SQLAlchemy,来自C#的LINQ to SQL的克隆

来自Scala和Groovy的Quick Lambdas,

Parser Combinators,受到Scala的启发.

查看链接页面以了解更多信息; 我想我可以自信地说,我们展示的用例远远超过了迄今为止在这个主题= D上的任何建议



3> dmitry_vk..:

lisp宏的一些示例:

ITERATE是一个有趣且可扩展的循环工具

CL-YACC/FUCC是在编译时生成解析器的解析器生成器

CL-WHO允许使用静态和动态部分指定html文档

Parenscript是一个javascript代码生成器

各种简单的代码包装器,例如错误处理程序(我有一个执行代码并显示GtkMessageDialog,如果发生未处理的错误的with-gtk-error-message-handler),执行程序(例如,给定代码,在不同的线程中执行它; I有一个主内线程宏,它在不同的线程中执行代码; PCall库使用宏来包装要同时执行的代码)

具有宏的GUI构建器(例如,指定窗口小部件层次结构和窗口小部件的属性,并具有用于创建所有窗口小部件的宏生成代码)

在编译期间使用外部资源的代码生成器.例如,处理C头并生成FFI代码的宏或基于数据库模式生成类定义的宏

声明性FFI.例如,指定外部结构,函数,它们的参数类型和具有宏来生成相应的lisp结构,具有类型映射和编组代码的函数

基于Continuations的Common Lisp Web框架使用宏将代码转换为CPS(延续传递样式)形式.


S.Lott:问题不是关于用例的适用性,而是关于实际用例.严格来说,当你有eval()时,你可以在没有宏的情况下完成所有工作.我认为这种论点会适得其反.我不认为所提到的每个示例都可以在Python中完成,而不会丢失重要的功能(例如,最小/小的运行时开销,编译时错误检测,与其他语言的集成).
-1:来自lisp的示例不适用于Python.如果这些可以在没有宏的情况下在Python中完成,那么这些不是Python的用例吗?
我在Python中看到的大部分内容的唯一方法是扩展语法.但这总是正确的:如果你让语言维护者为你可能想要的每个功能扩展语言,那基本上就是宏所做的.只有使用宏设施,您不需要每次都使用语言或询问Guido.
"你可以用eval()来做所有事情"只有你愿意将所有代码放在字符串中,并编写自己的解析器/翻译器时才会这样.但如果这些都是真的,你甚至不需要eval():任何与图灵相当的语言就足够了.
肯:没有解析器就可以得到eval.一些lisps(例如,newlisp)有F-Exprs.Fexpr是一种函数,它接受未评估的参数作为表达式(AST子树),它可以决定如何处理它们:eval,change和eval,discard等.当然,fexprs存在很大的问题.

4> vsedach..:

这是我遇到的一个真实世界的例子,它可以通过宏或真正的元编程支持来实现,但由于Python中缺少两者,因此必须使用CPython字节码操作:

http://www.aminus.net/dejavu/chrome/common/doc/2.0a/html/intro.html#cpython

这是使用常规宏和读取宏的组合在Common Lisp中解决问题的方法,以扩展语法(可以在没有后者的情况下完成,但不是前者):

http://clsql.b9.com/manual/csql-find.html

使用闭包和元编程在Smalltalk中解决了同样的问题(Smalltalk是少数实际上正确传递消息的单调度OO语言之一):

http://people.csail.mit.edu/gregs/ll1-discuss-archive-html/msg02096.html

在这里,我尝试在Common Lisp中实现Smalltalk方法,这很好地说明了元编程如何在后者中得到很好的支持:

http://carcaddar.blogspot.com/2009/04/closure-oriented-metaprogramming-via.html



5> bigmonachus..:

简而言之,宏只是抽象思想的另一种方法。

这是用clojure编写的不完整的光线跟踪器的示例:

(defmacro per-pixel
  "Macro.
Excecutes body for every pixel. Binds i and j to the current pixel coord."
  [i j & body]
  `(dotimes [~i @width]
     (dotimes [~j @height]
       ~@body)))

如果您想对坐标为(i,j)的每个像素做某事,例如,如果我是偶数,则绘制一个黑色像素,则可以这样写:

(per-pixel i,j
  (if (even? i)
    (draw-black i,j)))

如果没有宏,这是不可能的,因为@body可以表示内部的任何内容(每像素ij @body)

像这样的东西在python中也是可能的。您需要使用装饰器。您不能使用lisp宏做所有事情,但是它们非常强大

Check out this decorator tutorial: http://www.artima.com/weblogs/viewpost.jsp?thread=240808


在Lisp中:编写一个函数PER-PIXEL并将主体作为另一个函数传递。不需要宏。
推荐阅读
周扒pi
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有