草庐IT

python - "and"和 "or"如何处理非 bool 值?

coder 2023-05-20 原文

我正在尝试学习 python 并且遇到了一些很好且简短但并不完全有意义的代码

上下文是:

def fn(*args):
    return len(args) and max(args)-min(args)

我明白它在做什么,但为什么 python 这样做 - 即返回值而不是 True/False?
10 and 7-2

返回 5。同样,将 and 更改为 or 将导致功能发生变化。所以
10 or 7 - 2

会返回 10。

这是合法/可靠的风格,还是有任何问题?

最佳答案

TL;博士
我们首先总结了两个逻辑运算符 and 的两个行为。和 or .这些习语将构成我们下面讨论的基础。

and

Return the first Falsy value if there are any, else return the last value in the expression.



or

Return the first Truthy value if there are any, else return the last value in the expression.


该行为也在 the docs 中进行了总结。 ,尤其是在这张表中:

无论操作数如何,返回 bool 值的唯一运算符是 not运营商。

“真实”与“真实”评价
声明
len(args) and max(args) - min(args)
是一种非常pythonic的简洁(并且可以说可读性较差)的说法“如果args不为空,则返回max(args) - min(args)的结果”,否则返回0 .一般来说,它是 if-else 的更简洁的表示。表达。例如,
exp1 and exp2
应该(大致)翻译为:
r1 = exp1
if r1:
    r1 = exp2
或者,等效地,
r1 = exp2 if exp1 else exp1
相似地,
exp1 or exp2
应该(大致)翻译为:
r1 = exp1
if not r1:
    r1 = exp2
或者,等效地,
r1 = exp1 if exp1 else exp2
哪里exp1exp2是任意的 Python 对象,或返回某个对象的表达式。理解逻辑用法的关键andor这里的运算符理解它们不限于操作或返回 bool 值。任何具有真实值的对象都可以在这里测试。这包括 int , str , list , dict , tuple , set , NoneType , 和用户定义的对象。短路规则仍然适用。
但什么是真实?
它指的是在条件表达式中使用对象时如何评估对象。 @Patrick Haugh 在 this post 中很好地总结了真实性.

All values are considered "truthy" except for the following, which are "falsy":

  • None
  • False
  • 0
  • 0.0
  • 0j
  • Decimal(0)
  • Fraction(0, 1)
  • [] - an empty list
  • {} - an empty dict
  • () - an empty tuple
  • '' - an empty str
  • b'' - an empty bytes
  • set() - an empty set
  • an empty range, like range(0)
  • objects for which
    • obj.__bool__() returns False
    • obj.__len__() returns 0

A "truthy" value will satisfy the check performed by if or while statements. We use "truthy" and "falsy" to differentiate from the bool values True and False.



如何and作品
我们以 OP 的问题为基础,继续讨论这些操作符在这些情况下的表现。

Given a function with the definition

def foo(*args):
    ...

How do I return the difference between the minimum and maximum value in a list of zero or more arguments?


找到最小值和最大值很容易(使用内置函数!)。这里唯一的障碍是适当处理参数列表可能为空的极端情况(例如,调用 foo() )。多亏了 and,我们可以在一行中完成这两项工作运营商:
def foo(*args):
     return len(args) and max(args) - min(args)
foo(1, 2, 3, 4, 5)
# 4

foo()
# 0
and使用时,如果第一个表达式是 True,则还必须计算第二个表达式。 .请注意,如果第一个表达式被评估为真,则返回值始终是第二个表达式的结果。如果第一个表达式的计算结果为 Falsy,则返回的结果是第一个表达式的结果。
在上面的函数中,如果foo接收一个或多个参数,len(args)大于 0 (一个正数),所以返回的结果是 max(args) - min(args) . OTOH,如果没有传递参数,len(args)0这是假的,和 0被退回。
请注意,编写此函数的另一种方法是:
def foo(*args):
    if not len(args):
        return 0
    
    return max(args) - min(args)
或者,更简洁地说,
def foo(*args):
    return 0 if not args else max(args) - min(args)
当然,这些函数都不执行任何类型检查,所以除非您完全信任所提供的输入,否则不要依赖这些结构的简单性。

如何or作品
我解释了 or 的工作原理以类似的方式与一个人为的例子。

Given a function with the definition

def foo(*args):
    ...

How would you complete foo to return all numbers over 9000?


我们使用 or在这里处理角落案例。我们定义 foo如:
def foo(*args):
     return [x for x in args if x > 9000] or 'No number over 9000!'

foo(9004, 1, 2, 500)
# [9004]

foo(1, 2, 3, 4)
# 'No number over 9000!'
foo对列表执行过滤以保留所有超过 9000 的数字.如果存在任何这样的数字,则列表推导的结果是一个非空列表,即Truthy,因此将其返回(此处是短路操作)。如果不存在这样的数字,则列表 comp 的结果是 []这是假的。所以现在计算第二个表达式(一个非空字符串)并返回。
使用条件,我们可以将这个函数重写为,
def foo(*args):
    r = [x for x in args if x > 9000]
    if not r:
        return 'No number over 9000!' 
    
    return r
和以前一样,这种结构在错误处理方面更加灵活。

关于python - "and"和 "or"如何处理非 bool 值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47007680/

有关python - "and"和 "or"如何处理非 bool 值?的更多相关文章

  1. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  2. ruby-on-rails - rails : "missing partial" when calling 'render' in RSpec test - 2

    我正在尝试测试是否存在表单。我是Rails新手。我的new.html.erb_spec.rb文件的内容是:require'spec_helper'describe"messages/new.html.erb"doit"shouldrendertheform"dorender'/messages/new.html.erb'reponse.shouldhave_form_putting_to(@message)with_submit_buttonendendView本身,new.html.erb,有代码:当我运行rspec时,它失败了:1)messages/new.html.erbshou

  3. ruby-on-rails - 由于 "wkhtmltopdf",PDFKIT 显然无法正常工作 - 2

    我在从html页面生成PDF时遇到问题。我正在使用PDFkit。在安装它的过程中,我注意到我需要wkhtmltopdf。所以我也安装了它。我做了PDFkit的文档所说的一切......现在我在尝试加载PDF时遇到了这个错误。这里是错误:commandfailed:"/usr/local/bin/wkhtmltopdf""--margin-right""0.75in""--page-size""Letter""--margin-top""0.75in""--margin-bottom""0.75in""--encoding""UTF-8""--margin-left""0.75in""-

  4. ruby - 检查 "command"的输出应该包含 NilClass 的意外崩溃 - 2

    为了将Cucumber用于命令行脚本,我按照提供的说明安装了arubagem。它在我的Gemfile中,我可以验证是否安装了正确的版本并且我已经包含了require'aruba/cucumber'在'features/env.rb'中为了确保它能正常工作,我写了以下场景:@announceScenario:Testingcucumber/arubaGivenablankslateThentheoutputfrom"ls-la"shouldcontain"drw"假设事情应该失败。它确实失败了,但失败的原因是错误的:@announceScenario:Testingcucumber/ar

  5. ruby-on-rails - rails : save file from URL and save it to Amazon S3 - 2

    从给定URL下载文件并立即将其上传到AmazonS3的更直接的方法是什么(+将有关文件的一些信息保存到数据库中,例如名称、大小等)?现在,我既不使用Paperclip,也不使用Carrierwave。谢谢 最佳答案 简单明了:require'open-uri'require's3'amazon=S3::Service.new(access_key_id:'KEY',secret_access_key:'KEY')bucket=amazon.buckets.find('image_storage')url='http://www.ex

  6. ruby-on-rails - Enumerator.new 如何处理已通过的 block ? - 2

    我在理解Enumerator.new方法的工作原理时遇到了一些困难。假设文档中的示例:fib=Enumerator.newdo|y|a=b=1loopdoy[1,1,2,3,5,8,13,21,34,55]循环中断条件在哪里,它如何知道循环应该迭代多少次(因为它没有任何明确的中断条件并且看起来像无限循环)? 最佳答案 Enumerator使用Fibers在内部。您的示例等效于:require'fiber'fiber=Fiber.newdoa=b=1loopdoFiber.yieldaa,b=b,a+bendend10.times.m

  7. ruby-on-rails - 迷你测试错误 : "NameError: uninitialized constant" - 2

    我遵循MichaelHartl的“RubyonRails教程:学习Web开发”,并创建了检查用户名和电子邮件长度有效性的测试(名称最多50个字符,电子邮件最多255个字符)。test/helpers/application_helper_test.rb的内容是:require'test_helper'classApplicationHelperTest在运行bundleexecraketest时,所有测试都通过了,但我看到以下消息在最后被标记为错误:ERROR["test_full_title_helper",ApplicationHelperTest,1.820016791]test

  8. ruby-on-rails - 相关表上的范围为 "WHERE ... LIKE" - 2

    我正在尝试从Postgresql表(table1)中获取数据,该表由另一个相关表(property)的字段(table2)过滤。在纯SQL中,我会这样编写查询:SELECT*FROMtable1JOINtable2USING(table2_id)WHEREtable2.propertyLIKE'query%'这工作正常:scope:my_scope,->(query){includes(:table2).where("table2.property":query)}但我真正需要的是使用LIKE运算符进行过滤,而不是严格相等。然而,这是行不通的:scope:my_scope,->(que

  9. 使用 ACL 调用 upload_file 时出现 Ruby S3 "Access Denied"错误 - 2

    我正在尝试编写一个将文件上传到AWS并公开该文件的Ruby脚本。我做了以下事情:s3=Aws::S3::Resource.new(credentials:Aws::Credentials.new(KEY,SECRET),region:'us-west-2')obj=s3.bucket('stg-db').object('key')obj.upload_file(filename)这似乎工作正常,除了该文件不是公开可用的,而且我无法获得它的公共(public)URL。但是当我登录到S3时,我可以正常查看我的文件。为了使其公开可用,我将最后一行更改为obj.upload_file(file

  10. ruby - 安装 Ruby 时遇到问题(无法下载资源 "readline--patch") - 2

    当我尝试安装Ruby时遇到此错误。我试过查看this和this但无济于事➜~brewinstallrubyWarning:YouareusingOSX10.12.Wedonotprovidesupportforthispre-releaseversion.Youmayencounterbuildfailuresorotherbreakages.Pleasecreatepull-requestsinsteadoffilingissues.==>Installingdependenciesforruby:readline,libyaml,makedepend==>Installingrub

随机推荐