我上周接受了一次采访,在那里我学到了一些我不知道的关于python的东西(或者更确切地知道它们是如何被使用的),首先是这个问题的内容是使用{{1出于分支控制的目的。
因此,例如,如果我们运行:
or
然后,如果def f():
# do something. I'd use ... but that's actually a python object.
def g():
# something else.
f() or g()
计算到某个真实条件,则返回该值,否则,将评估f()
并返回它产生的任何值,无论是真还是假。这使我们能够使用g()
关键字实现if
语句。
我们还可以使用or
,and
如果f() and g()
为真,则g()
将返回f()
的值,如果f()
则返回g()
的值是假的。
我被告知这个(使用or
进行分支控制)在lisp等语言中很常见(因此是lisp标记)。我目前正在关注SICP学习计划,因此我可以看到(or (f x) (g x))
会返回(g x)
的值,假设(f x)
为#f
。
我对这项技术是否有任何优势感到困惑。它显然实现了分支控制,但对我来说,内置关键字似乎更加不言自明。
我也很困惑这是否“功能性”?我对纯函数式编程的理解是你使用这样的结构(我最近的erlang实验中的一个例子):
makeeven(N,1) -> N+1;
makeeven(N,0) -> N;
makeeven(N) -> makeeven(N,N rem 2).
使用template meta-programming in C++(通过cpp-next.com发现)更好,更复杂的示例。我的思维过程是函数式编程的一个方面归结为piecewise defined functions in code用于分支控制(如果你可以管理它,尾递归)。
所以,我的问题:
我为跳过这么多语言而道歉;我只是想把我对它们的理解联系在一起。随意用任何语言回答。如果我误解了任何定义或遗漏了一些重要的东西,我也很抱歉,我从未正式学过计算机科学。
答案 0 :(得分:12)
你的面试官必须有一个“功能背景”的方式。曾经常见的是写
(or (some-condition) (some-side-effect))
但是在CL和支持它的Scheme实现中,使用unless
写得更好。 and
与when
相同。
所以,更具体一点 - 它不是更具功能性(事实上,这些东西的常见用途是单方面条件,这些条件起初不起作用);没有任何优势(当你知道事情是以宏的形式实现时,这些语言变得非常明显 - 例如,大多数or
和and
实现扩展为if
);任何可能的用例都应该使用when
和unless
,如果你的实现中有它们,否则最好将它们定义为宏而不是不使用它们。
哦,你可以使用它们的组合而不是双面的if
,但那会很混乱。
答案 1 :(得分:6)
我不知道这个代码的执行方式会有任何问题,但是对于没有经验的人来说,这是令人困惑的。事实上,这种语法就像一个Python反模式:你可以做到,但它绝不是Pythonic。
答案 2 :(得分:5)
condition and true_branch or false_branch
适用于所有具有短循环逻辑运算符的语言。另一方面,在值具有布尔值的语言中使用它并不是一个好主意。
例如
zero = (1==0) and 0 or 1 # (1==0) -> False
zero = (False and 0) or 1 # (False and X) -> X
zero = 0 or 1 # 0 is False in most languages
zero = False or 1
zero = 1
答案 3 :(得分:2)
正如以利所说;此外,纯粹使用逻辑运算符执行控制流程往往会在介绍性的FP类中进行教学 - 更多的是作为一个心灵练习,实际上,不是你必须要使用IRL的东西。能够将任何控制运算符转换为if
总是好的。
现在,FP和其他语言之间的最大区别在于,在更多功能语言中,if
实际上是一个表达式,而不是语句。 if
块总是有值! C语言系列有一个宏版本 - test? consequent : alternative
构造 - 但如果你嵌套更多的表达式,它就变得非常难以理解了。
在Python 2.5之前,如果您想在Python中使用控制流表达式,则可能必须使用逻辑运算符。但是在Python 2.5中,是类似于FP的if-expression语法,所以你可以这样做:
(42 if True else 7) + 35
请参阅PEP 308
答案 4 :(得分:2)
您只提到了需要评估的2个表达式的情况。如果有5个会怎么样?
;; returns first true value, evaluating only as many as needed
(or (f x) (g x) (h x) (i x) (j x))
你会嵌套if语句吗?我不确定我是如何用Python做的。这是几乎:
any(c(x) for c in [f, g, h, i, j])
除了Python的any
抛弃了值,只返回True
。 (可能有一种方法可以用itertools.dropwhile
来做,但对我来说似乎有点尴尬。或者我可能只是错过了明显的方法。)
(顺便说一下:我发现Lisp的内置不会相当对应于他们的名字在其他语言中的含义,这可能会令人困惑.Lisp的IF
就像C的三元运算符例如,?:
或Python的条件表达式,而不是它们的if语句。同样,Lisp的OR
在某种程度上更像(但不完全像)Python的any()
,只需2由于普通IF
已经返回一个值,因此没有必要单独使用不能像这样使用的“if”,或者只使用两个值的单独的“or”。它已经像其他语言中不太常见的变体一样灵活。)
我恰好正在编写这样的代码,巧合的是,其中一些功能是“去问一些服务器的答案”,我想在得到肯定回复后立即停止。我永远不会在我真正想说OR
的地方使用IF
,但我宁愿说:
(setq did-we-pass (or (try-this x)
(try-that x)
(try-some-other-thing x)
(heck-maybe-this-will-work x))
而不是制作一棵大树的IF。这有资格作为“流量控制”还是“功能性”?我想这取决于你的定义。
答案 5 :(得分:0)
在功能语言中首选的编程风格可能被认为是“功能性的”。否则就没有任何功能。
这只是语法。
有时可能更具可读性,例如:
def foo(bar=None):
bar = bar or []
...
return bar
def baz(elems):
print "You have %s elements." % (len(elems) or "no")
您可以使用bar if bar else []
,但它非常详细。