Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/315.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 我们能在条件允许的情况下完成任务吗?_Python - Fatal编程技术网

Python 我们能在条件允许的情况下完成任务吗?

Python 我们能在条件允许的情况下完成任务吗?,python,Python,有可能在某种条件下进行赋值吗 例如 if (a=some_func()): # Use a 为什么不试试呢 >>> def some_func(): ... return 2 ... >>> if (a = some_func()): File "<stdin>", line 1 if (a = some_func()): ^ SyntaxError: invalid syntax

有可能在某种条件下进行赋值吗

例如

if (a=some_func()):
    # Use a
为什么不试试呢

>>> def some_func():
...   return 2
... 
>>> if (a = some_func()):
  File "<stdin>", line 1
    if (a = some_func()):
          ^
SyntaxError: invalid syntax

否。Python中的赋值是语句,而不是表达式。

UPDATE-原始答案在底部附近 Python3.8将引入

摘要
这是一个关于创建一种分配给变量的方法的建议 在表达式中使用符号
NAME:=expr
。一个新的例外, 添加了
TargetScopeError
,并对评估进行了一次更改 秩序

“PEP572混乱”是2018年Python语言峰会的主题 由仁慈的终身独裁者(BDFL)Guido van Rossum领导的会议。 PEP 572试图添加赋值表达式(或“内联赋值”) 对语言,但它已经看到了一个长期的讨论,在多个方面 python-dev邮件列表上的大量线程,即使在多次发送之后也是如此 关于python思想。这些线索往往是有争议的,而且很明显 数量庞大,很多人可能只是对其进行了调整。在 在峰会上,Van Rossum概述了专题提案,其中 他似乎倾向于接受,但他也想讨论如何接受 以避免将来出现这种线程爆炸

Python标准库中的示例

site.py env_base仅用于这些行,将其指定放在if上,并将其作为块的“标题”移动。 当前:

env_base = os.environ.get("PYTHONUSERBASE", None)
if env_base:
    return env_base
if self._is_special:
    ans = self._check_nans(context=context)
    if ans:
        return ans
reductor = dispatch_table.get(cls)
if reductor:
    rv = reductor(x)
else:
    reductor = getattr(x, "__reduce_ex__", None)
    if reductor:
        rv = reductor(4)
    else:
        reductor = getattr(x, "__reduce__", None)
        if reductor:
            rv = reductor()
        else:
            raise Error(
                "un(deep)copyable object of type %s" % cls)
s = _format_time(self._hour, self._minute,
                 self._second, self._microsecond,
                 timespec)
tz = self._tzstr()
if tz:
    s += tz
return s
while True:
    line = fp.readline()
    if not line:
        break
    m = define_rx.match(line)
    if m:
        n, v = m.group(1, 2)
        try:
            v = int(v)
        except ValueError:
            pass
        vars[n] = v
    else:
        m = undef_rx.match(line)
        if m:
            vars[m.group(1)] = 0
改进:

if env_base := os.environ.get("PYTHONUSERBASE", None):
    return env_base
_pydecimal.py
if self._is_special and (ans := self._check_nans(context=context)):
    return ans
if reductor := dispatch_table.get(cls):
    rv = reductor(x)
elif reductor := getattr(x, "__reduce_ex__", None):
    rv = reductor(4)
elif reductor := getattr(x, "__reduce__", None):
    rv = reductor()
else:
    raise Error("un(deep)copyable object of type %s" % cls)
datetime.py
s = _format_time(self._hour, self._minute,
                 self._second, self._microsecond,
                 timespec)
if tz := self._tzstr():
    s += tz
return s
while line := fp.readline():
    if m := define_rx.match(line):
        n, v = m.group(1, 2)
        try:
            v = int(v)
        except ValueError:
            pass
        vars[n] = v
    elif m := undef_rx.match(line):
        vars[m.group(1)] = 0
避免嵌套if并删除一个缩进级别

当前:

env_base = os.environ.get("PYTHONUSERBASE", None)
if env_base:
    return env_base
if self._is_special:
    ans = self._check_nans(context=context)
    if ans:
        return ans
reductor = dispatch_table.get(cls)
if reductor:
    rv = reductor(x)
else:
    reductor = getattr(x, "__reduce_ex__", None)
    if reductor:
        rv = reductor(4)
    else:
        reductor = getattr(x, "__reduce__", None)
        if reductor:
            rv = reductor()
        else:
            raise Error(
                "un(deep)copyable object of type %s" % cls)
s = _format_time(self._hour, self._minute,
                 self._second, self._microsecond,
                 timespec)
tz = self._tzstr()
if tz:
    s += tz
return s
while True:
    line = fp.readline()
    if not line:
        break
    m = define_rx.match(line)
    if m:
        n, v = m.group(1, 2)
        try:
            v = int(v)
        except ValueError:
            pass
        vars[n] = v
    else:
        m = undef_rx.match(line)
        if m:
            vars[m.group(1)] = 0
改进:

if env_base := os.environ.get("PYTHONUSERBASE", None):
    return env_base
_pydecimal.py
if self._is_special and (ans := self._check_nans(context=context)):
    return ans
if reductor := dispatch_table.get(cls):
    rv = reductor(x)
elif reductor := getattr(x, "__reduce_ex__", None):
    rv = reductor(4)
elif reductor := getattr(x, "__reduce__", None):
    rv = reductor()
else:
    raise Error("un(deep)copyable object of type %s" % cls)
datetime.py
s = _format_time(self._hour, self._minute,
                 self._second, self._microsecond,
                 timespec)
if tz := self._tzstr():
    s += tz
return s
while line := fp.readline():
    if m := define_rx.match(line):
        n, v = m.group(1, 2)
        try:
            v = int(v)
        except ValueError:
            pass
        vars[n] = v
    elif m := undef_rx.match(line):
        vars[m.group(1)] = 0
copy.py代码看起来更规则,如果需要,可以避免多重嵌套。(本例来源见附录A。) 当前:

env_base = os.environ.get("PYTHONUSERBASE", None)
if env_base:
    return env_base
if self._is_special:
    ans = self._check_nans(context=context)
    if ans:
        return ans
reductor = dispatch_table.get(cls)
if reductor:
    rv = reductor(x)
else:
    reductor = getattr(x, "__reduce_ex__", None)
    if reductor:
        rv = reductor(4)
    else:
        reductor = getattr(x, "__reduce__", None)
        if reductor:
            rv = reductor()
        else:
            raise Error(
                "un(deep)copyable object of type %s" % cls)
s = _format_time(self._hour, self._minute,
                 self._second, self._microsecond,
                 timespec)
tz = self._tzstr()
if tz:
    s += tz
return s
while True:
    line = fp.readline()
    if not line:
        break
    m = define_rx.match(line)
    if m:
        n, v = m.group(1, 2)
        try:
            v = int(v)
        except ValueError:
            pass
        vars[n] = v
    else:
        m = undef_rx.match(line)
        if m:
            vars[m.group(1)] = 0
改进:

if env_base := os.environ.get("PYTHONUSERBASE", None):
    return env_base
_pydecimal.py
if self._is_special and (ans := self._check_nans(context=context)):
    return ans
if reductor := dispatch_table.get(cls):
    rv = reductor(x)
elif reductor := getattr(x, "__reduce_ex__", None):
    rv = reductor(4)
elif reductor := getattr(x, "__reduce__", None):
    rv = reductor()
else:
    raise Error("un(deep)copyable object of type %s" % cls)
datetime.py
s = _format_time(self._hour, self._minute,
                 self._second, self._microsecond,
                 timespec)
if tz := self._tzstr():
    s += tz
return s
while line := fp.readline():
    if m := define_rx.match(line):
        n, v = m.group(1, 2)
        try:
            v = int(v)
        except ValueError:
            pass
        vars[n] = v
    elif m := undef_rx.match(line):
        vars[m.group(1)] = 0
tz仅用于s+=tz,将其赋值移动到if帮助中 显示其范围

当前:

env_base = os.environ.get("PYTHONUSERBASE", None)
if env_base:
    return env_base
if self._is_special:
    ans = self._check_nans(context=context)
    if ans:
        return ans
reductor = dispatch_table.get(cls)
if reductor:
    rv = reductor(x)
else:
    reductor = getattr(x, "__reduce_ex__", None)
    if reductor:
        rv = reductor(4)
    else:
        reductor = getattr(x, "__reduce__", None)
        if reductor:
            rv = reductor()
        else:
            raise Error(
                "un(deep)copyable object of type %s" % cls)
s = _format_time(self._hour, self._minute,
                 self._second, self._microsecond,
                 timespec)
tz = self._tzstr()
if tz:
    s += tz
return s
while True:
    line = fp.readline()
    if not line:
        break
    m = define_rx.match(line)
    if m:
        n, v = m.group(1, 2)
        try:
            v = int(v)
        except ValueError:
            pass
        vars[n] = v
    else:
        m = undef_rx.match(line)
        if m:
            vars[m.group(1)] = 0
改进:

if env_base := os.environ.get("PYTHONUSERBASE", None):
    return env_base
_pydecimal.py
if self._is_special and (ans := self._check_nans(context=context)):
    return ans
if reductor := dispatch_table.get(cls):
    rv = reductor(x)
elif reductor := getattr(x, "__reduce_ex__", None):
    rv = reductor(4)
elif reductor := getattr(x, "__reduce__", None):
    rv = reductor()
else:
    raise Error("un(deep)copyable object of type %s" % cls)
datetime.py
s = _format_time(self._hour, self._minute,
                 self._second, self._microsecond,
                 timespec)
if tz := self._tzstr():
    s += tz
return s
while line := fp.readline():
    if m := define_rx.match(line):
        n, v = m.group(1, 2)
        try:
            v = int(v)
        except ValueError:
            pass
        vars[n] = v
    elif m := undef_rx.match(line):
        vars[m.group(1)] = 0
sysconfig.py在while条件中调用fp.readline(),并在if行中调用.match(),使代码更加紧凑,而无需 使它更难理解

当前:

env_base = os.environ.get("PYTHONUSERBASE", None)
if env_base:
    return env_base
if self._is_special:
    ans = self._check_nans(context=context)
    if ans:
        return ans
reductor = dispatch_table.get(cls)
if reductor:
    rv = reductor(x)
else:
    reductor = getattr(x, "__reduce_ex__", None)
    if reductor:
        rv = reductor(4)
    else:
        reductor = getattr(x, "__reduce__", None)
        if reductor:
            rv = reductor()
        else:
            raise Error(
                "un(deep)copyable object of type %s" % cls)
s = _format_time(self._hour, self._minute,
                 self._second, self._microsecond,
                 timespec)
tz = self._tzstr()
if tz:
    s += tz
return s
while True:
    line = fp.readline()
    if not line:
        break
    m = define_rx.match(line)
    if m:
        n, v = m.group(1, 2)
        try:
            v = int(v)
        except ValueError:
            pass
        vars[n] = v
    else:
        m = undef_rx.match(line)
        if m:
            vars[m.group(1)] = 0
改进:

if env_base := os.environ.get("PYTHONUSERBASE", None):
    return env_base
_pydecimal.py
if self._is_special and (ans := self._check_nans(context=context)):
    return ans
if reductor := dispatch_table.get(cls):
    rv = reductor(x)
elif reductor := getattr(x, "__reduce_ex__", None):
    rv = reductor(4)
elif reductor := getattr(x, "__reduce__", None):
    rv = reductor()
else:
    raise Error("un(deep)copyable object of type %s" % cls)
datetime.py
s = _format_time(self._hour, self._minute,
                 self._second, self._microsecond,
                 timespec)
if tz := self._tzstr():
    s += tz
return s
while line := fp.readline():
    if m := define_rx.match(line):
        n, v = m.group(1, 2)
        try:
            v = int(v)
        except ValueError:
            pass
        vars[n] = v
    elif m := undef_rx.match(line):
        vars[m.group(1)] = 0
简化列表理解通过捕获条件,列表理解可以有效地映射和过滤: 类似地,子表达式可以在主表达式中重用, 第一次使用时给它起一个名字:

stuff = [[y := f(x), x/y] for x in range(5)]
请注意,在这两种情况下,变量y都绑定在包含 范围(即与结果或内容处于同一级别)

捕获条件值赋值表达式可以在if或while语句的标头中发挥良好效果: 特别是对于while循环,这可以消除对 无限循环、赋值和条件。它还创建了一个 循环之间的平滑并行,该循环仅使用函数调用作为 它的条件,一个使用它作为条件,但也使用 实际值

从低级UNIX世界中选出一个例子: 原始答案

请注意,在Python中,与C不同, 分配不能发生在内部 表达。C程序员可能会抱怨 关于这一点,但它避免了一个常见的问题 C语言中遇到的一类问题 程序:在表达式中键入= 当==是预定的

另见:


不,BDFL不喜欢这个功能

在我坐的地方,Guido van Rossum,“一生仁慈的独裁者”,一直在努力让Python尽可能简单。我们可以质疑他所做的一些决定——我更希望他更经常地说“不”。但事实上,没有一个设计Python的委员会,而是一个值得信赖的“咨询委员会”“主要基于优点,通过过滤一位设计师的敏感度,产生了一种非常好的语言,IMHO。

不是直接的,per——但正如食谱所说,很容易建立语义等价物,例如,如果你需要直接从C编码的参考算法进行音译(当然,在重构到更惯用的Python之前;-)。即:

顺便说一句,如果您确切知道falsish值
somefunc
在返回falsish值(例如
0
)时可能返回的值,那么这是一种非常惯用的python形式

因此,在这种特定情况下,重构将非常容易;-)

如果返回值可以是任何类型的falsish值(0,
None
'
,…),一种可能性是:

import itertools

for a in itertools.takewhile(lambda x: x, iter(somefunc, object())):
    # use a
但您可能更喜欢简单的自定义生成器:

def getwhile(func, *a, **k):
    while True:
      x = func(*a, **k)
      if not x: break
      yield x

for a in getwhile(somefunc):
    # use a

条件下的赋值是非法的原因之一是容易出错并赋值为真或假:

some_variable = 5

# This does not work
# if True = some_variable:
#   do_something()

# This only works in Python 2.x
True = some_variable

print True  # returns 5

在Python 3中,True和False是关键字,因此不再存在任何风险。

您可以定义一个函数来为自己赋值:

def assign(name, value):
    import inspect
    frame = inspect.currentframe()
    try:
        locals_ = frame.f_back.f_locals
    finally:
        del frame 
    locals_[name] = value
    return value

if assign('test', 0):
    print("first", test)
elif assign('xyz', 123):
    print("second", xyz)
多亏了它,在这个版本中可以做这样的事情,虽然不使用
=
,但使用类似Ada的赋值操作符
:=
。文档中的示例:

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

是的,但仅限于Python3.8及以后版本

建议赋值表达式,并已被接受

引用政治公众人物部分:

# 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]
在您的具体情况下,您将能够编写

if a := some_func():
    # Use a

分配操作员(也称为海象操作员)于2018年2月28日成立

为了完整起见,我将发布相关部分,以便您可以比较3.7和3.8之间的差异:

3.7
---
if_stmt: 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite]
suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT
test: or_test ['if' or_test 'else' test] | lambdef
test_nocond: or_test | lambdef_nocond
lambdef: 'lambda' [varargslist] ':' test
lambdef_nocond: 'lambda' [varargslist] ':' test_nocond
or_test: and_test ('or' and_test)*
and_test: not_test ('and' not_test)*
not_test: 'not' not_test | comparison
comparison: expr (comp_op expr)*

3.8
---
if_stmt: 'if' namedexpr_test ':' suite ('elif' namedexpr_test ':' suite)* ['else' ':' suite]
namedexpr_test: test [':=' test]                         <---- WALRUS OPERATOR!!!
test: or_test ['if' or_test 'else' test] | lambdef
or_test: and_test ('or' and_test)*
and_test: not_test ('and' not_test)*
not_test: 'not' not_test | comparison
comparison: expr (comp_op expr)*
3.7
---
if stmt:'if'test':'suite('elif'test':'suite)*['else':'suite]
套件:简单|换行缩进stmt+DEDENT
测试:或|测试['if'或|测试'else'测试]| lambdef
测试无约束:或测试无约束
lambdef:'lambda'[varargslist]':'test
lambdef_nocond:'lambda'[varargslist]':'test_nocond
or_测试:and_测试('or'and_测试)*
and_测试:not_测试(‘and’not_测试)*
非|测试:非|非|测试|比较
比较:expr(comp_op expr)*
3.8
---
if_stmt:'if'namedexpr_test':'suite('elif'namedexpr_test':'suite)*['else':'suite]

namedexpr_test:test[':=“test]和Guido不会有任何其他方法。@markransem所有人都向Guido欢呼。正确的。。唉。@javadba这家伙说得对的次数比以前多得多