【问题标题】:Simulating Lisp's :keywords in Python在 Python 中模拟 Lisp 的 :keywords
【发布时间】:2013-01-22 07:32:03
【问题描述】:

我想做这样的事情:

action = :default

if some_condition1:
    action = :do_something

if some_condition2:
    action = :do_other_thing

...

if action == :default:
   one_reaction()
elif action == :do_something:
   other_reaction()
...

我应该用什么来表示动作选择?

想到的变体:

  • 创建枚举

    class MyActions:
        DEFAULT=1
        SO_SOMETHING=2
        SO_OTHER_THING=3
    

    不方便,需要来回滚动并“注册”新的操作选择。

  • 使用幻数。不好。

  • 使用字符串。

【问题讨论】:

标签: python


【解决方案1】:

从概念上讲,Lisp 中的“符号”可以被认为是内部字符串。

action = 'default'

if some_condition1:
    action = 'do_something'

if some_condition2:
    action = 'do_other_thing'

...

if action == 'default':
   one_reaction()
elif action == 'do_something':
   other_reaction()
...

只要你在 Lisp 中使用符号,Python 就会使用字符串。 Lisp 必须做出区分,因为它是同形的,但由于 Python 不是同形的,所以区分是不必要的。

替代方案

如果您改用数字,那么您将失去 REPL 能力。例如,

default = 1
do_something = 2
do_other_thing = 3

>>> x = default
>>> x
1 # is 1 default? I can't remember...

有更复杂的方法可以做到这一点,比如创建特殊的类,但小小的好处不值得增加复杂性。

【讨论】:

    【解决方案2】:

    以下类的实例将返回您从中调用的任何属性的名称。创建一个变量k 或其他东西会使访问它变得简单。

    class LispKeyword(object):
        def __getattribute__(self, name):
            return name
    
    >>> k = LispKeyword()
    >>> k.blarg
    'blarg'
    >>> k.what
    'what'
    

    【讨论】:

      【解决方案3】:

      对于您提供的代码,您可以将变量设置为需要调用的函数。对于更通用的解决方案,您可以使用字符串或枚举。另见https://stackoverflow.com/a/3743555/113586

      【讨论】:

        【解决方案4】:

        在python-ideas 列表"constant/enum type in stdlib" 上正在讨论向语言添加类似枚举的想法,多种设计和纯Python 实现被辗转反侧。在上一轮讨论中,Guido 和几乎所有其他人都同意有些东西值得添加,但没有人决定要添加什么。

        所以,我想你可以说,做枚举常量的惯用方法实际上还没有被发明出来。

        值得浏览该线程以了解什么被认为是惯用的,如果您是荷兰人,那么明显的做法是什么,等等。如果您确实想要使用枚举,那么在选择实现之前更值得略读。

        同时,如果您想知道在遥远的过去(例如 2013 年 2 月)的惯用语,我同意 Dietrich Epp 的观点,即字符串几乎总是解决此类问题的正确选择。

        他解释了为什么性能问题在 Python 中不是问题,但还有一件人们总是提出来但我想忽略的事情:

        thingy = 'mokney'
        # ...
        if thingy == 'gorilla': do_gorilla()
        elif thingy == 'monkey': do_monkey()
        else: do_default()
        

        如果您使用某种严格的枚举,则不会发生这种情况——或者,至少,您可以通过在 if/elif 链之前放置一个 assert isinstance(thingy, Primate) 来防止它发生。

        这一切听起来都很棒,直到你看到这一行:

        thigny == 'monkey'
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-05-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-03-15
          相关资源
          最近更新 更多