【问题标题】:How to avoid writing request.GET.get() twice in order to print it?如何避免两次写入 request.GET.get() 以打印它?
【发布时间】:2010-12-12 10:46:22
【问题描述】:

我来自 PHP 背景,想知道是否有办法在 Python 中做到这一点。

在 PHP 中,你可以像这样用一块石头杀死 2 只鸟:

代替:

if(getData()){
    $data = getData();
    echo $data;
}

我可以这样做:

if($data = getData()){
    echo $data;
}

您检查getData() 是否存在,如果存在,则在一个语句中将其分配给一个变量。

我想知道是否有办法在 Python 中做到这一点?所以不要这样做:

if request.GET.get('q'):
    q = request.GET.get('q')
    print q

避免两次写request.GET.get('q')

【问题讨论】:

  • 只是官方的:docs.python.org/tutorial
  • 谢天谢地,Python 没有这个 C 错误特性,一般来说,在大多数从 C/C++ 继承它的语言中,出于可读性和清晰的原因,它的使用是不受欢迎的。
  • @S.Lott 这不是重复的,因为另一个问题询问了while,这使得所有答案都集中在迭代上,从而完全绕过了流控制语句中的赋值问题。
  • 不是那么“错误”,例如clojure甚至有特殊的if-let宏。

标签: python if-statement dictionary


【解决方案1】:

请参阅我 8 年前的食谱 here 来完成这项任务。

# In Python, you can't code "if x=foo():" -- assignment is a statement, thus
# you can't fit it into an expression, as needed for conditions of if and
# while statements, &c.  No problem, if you just structure your code around
# this.  But sometimes you're transliterating C, or Perl, or ..., and you'd
# like your transliteration to be structurally close to the original.
#
# No problem, again!  One tiny, simple utility class makes it easy...:

class DataHolder:
    def __init__(self, value=None): self.value = value
    def set(self, value): self.value = value; return value
    def get(self): return self.value
# optional but handy, if you use this a lot, either or both of:
setattr(__builtins__,'DataHolder',DataHolder)
setattr(__builtins__,'data',DataHolder())

# and now, assign-and-set to your heart's content: rather than Pythonic
while 1:
    line = file.readline()
    if not line: break
    process(line)
# or better in modern Python, but quite far from C-like idioms:
for line in file.xreadlines():
    process(line)
# you CAN have your C-like code-structure intact in transliteration:
while data.set(file.readline()):
    process(data.get())

【讨论】:

  • 你有一个非常聪明的 8 岁孩子! ;)
  • @unutbu,呵呵——那将是我的(大一点的)猫,因为我的孩子年纪大了一点……我的小女儿刚刚开始攻读电信工程博士学位(主要是高级无线电系统)…… .;-)
【解决方案2】:

可能不完全是你的想法,但是......

q = request.GET.get('q')
if q:
    print q

这个?

【讨论】:

  • 是的,没错。模式是当且仅当它存在时才使用变量(意味着它给出一个有效值,即除了 False 之外的任何值)。
  • 谢谢,看起来这是最好的方法。正如@Adam 所说,在 Python 中不可能做到这一点。谢谢。
  • 此解决方案的局限性在于,如果您想在一系列 if-elif-elif-elif 等中使用它。例如,请参阅另一个 SO 问题:stackoverflow.com/questions/122277/…
  • @Amber,其中一个小问题是当q==0q==0. 时,if 条件失败。 If 将其条件表达式转换为 bool00. 都转换为 False
  • @hob 当然。如果您希望有时会出现这种情况(例如if q is not None:),您总是可以使用更明确的条件。
【解决方案3】:

Alex's answer 的变体:

class DataHolder:
    def __init__(self, value=None, attr_name='value'):
        self._attr_name = attr_name
        self.set(value)
    def __call__(self, value):
        return self.set(value)
    def set(self, value):
        setattr(self, self._attr_name, value)
        return value
    def get(self):
        return getattr(self, self._attr_name)
save_data = DataHolder()

用法:

if save_data(get_input()):
    print save_data.value

或者如果您更喜欢其他界面:

if save_data.set(get_input()):
    print save_data.get()

我会发现这有助于在 if-elif-elif-elif 等结构中测试一系列正则表达式,例如 this SO question:

import re

input = u'test bar 123'
save_match = DataHolder(attr_name='match')
if save_match(re.search('foo (\d+)', input)):
    print "Foo"
    print save_match.match.group(1)
elif save_match(re.search('bar (\d+)', input)):
    print "Bar"
    print save_match.match.group(1)
elif save_match(re.search('baz (\d+)', input)):
    print "Baz"
    print save_match.match.group(1)

【讨论】:

  • 我喜欢您将__call__() 添加到DataHolder,但我不明白为什么指定attr_name 很有用。如果 DataHolder 是一个单例,或者如果它的一个实例可以包含多个值,每个值都具有不同的属性,我会理解,但它在这里似乎没有强烈的目的。
  • @LS:是的,我本可以将其固定为valuex。但是good variable names 提高了可读性。这就是它的精髓。
【解决方案4】:

PEP 572 引入了赋值表达式。从 Python 3.8 起,您可以编写:

if q := request.GET.get('q'):
    print q

以下是 PEP 的 Syntax and semantics 部分的更多示例:

# Handle a matched regex
if (match := pattern.search(data)) is not None:
    # Do something with match

# A loop that can't be trivially rewritten using 2-arg iter()
while chunk := file.read(8192):
   process(chunk)

# Reuse a value that's expensive to compute
[y := f(x), y**2, y**3]

# Share a subexpression between a comprehension filter clause and its output
filtered_data = [y for x in data if (y := f(x)) is not None]

【讨论】:

    【解决方案5】:
    q = request.GET.get('q')
    if q:
        print q
    else:
        # q is None
        ...
    

    没有办法一次性完成赋值和条件...

    【讨论】:

    • 显式优于隐式。可读性很重要。特殊情况不足以打破规则。您在代码中节省了如此多的垂直空间,而不是只用右括号编写所有这些行,那么为什么不在 Python 中保持清晰呢?就我个人而言,我开始学习 C 并且已经编写了 12 年的 Python 代码,但我从未意识到缺少这个功能。您只是不需要这样做。
    • @Michael:我几乎在所有情况下都同意。我只是在测试多个正则表达式的特定用例中错过了它,如另一个 SO 问题中所述:stackoverflow.com/questions/122277/…
    • @MichaelDillon 在你写 python 的 12 年(现在是 24 年,如果你一直坚持的话),我想你已经有好几次写级联正则表达式匹配语句了,就像在另一个Craig McQueen 提到的问题。当你有10个时,你怎么写?嵌套和进一步缩进 10 次?
    【解决方案6】:

    如果 get() 在不存在时抛出异常,你可以这样做

    try:
       q = request.GET.get('q')
       print q
    except :
       pass
    

    【讨论】:

      【解决方案7】:
      config_hash = {}
      tmp_dir = ([config_hash[x]  for x in ["tmp_dir"] if config_hash.has_key(x)] or ["tmp"])[0]
      print tmp_dir
      config_hash["tmp_dir"] = "cat"
      tmp_dir = ([config_hash[x]  for x in ["tmp_dir"] if config_hash.has_key(x)] or ["tmp"])[0]
      print tmp_dir
      

      【讨论】:

        【解决方案8】:

        一种可能的方法,无需事先设置变量,可能是:

        if (lambda x: globals().update({'q':x}) or True if x else False)(request.GET.get('q')):
            print q
        

        .. 这只是为了好玩-不应该使用这种方法,因为它是丑陋的 hack,乍一看很难理解,并且它创建/覆盖了一个全局变量(但只有在满足条件的情况下)

        【讨论】:

          【解决方案9】:

          嗯,这是一种方式

          q = request.GET.get('q')
          if q:
              print q
          

          一个更简洁(但不是更好,由于什么都没有打印的调用)的方式是

          print request.GET.get('q') or '',
          

          【讨论】:

            【解决方案10】:

            试试吧:

            print(request.GET.get('q', ''))
            

            如果第一个参数不存在,它基本上什么也不打印(参见dict.get)。


            另一种解决方案是在 Python 中使用条件表达式:

            <expression1> if <condition> else <expression2>
            

            但你最终会重复变量两次,例如:

            print(request.GET.get('q') if request.GET.get('q') else '')
            

            对于循环中的变量赋值,签入here

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2018-03-10
              • 1970-01-01
              • 2020-04-08
              相关资源
              最近更新 更多