<p>您的功能基本上是这样:</p>
<pre><code>if all parameters are 'All':
return df
else:
Take all the non-'All' parameters
Test if each one is equal to df['name_of_parameter']
Bitwise-AND them together
Return df[result of previous line]
</code></pre>
<p>让我们先从所有非“all”参数的列表开始重写:</p>
<pre><code>notall = [x for x in [a,b,c] if x != 'All']
if not notall:
return df
else:
???
</code></pre>
<p>障碍1:我们现在已经不知道哪个值与哪个参数匹配了。为什么我们要知道这些?这样我们就可以将参数与<code>df</code>的正确元素进行比较。我们可以通过将参数值和名称存储在<code>notall</code>中来解决这个问题:</p>
<pre><code>notall = [(x, name) for (x, name) in [(a, 'a'), (b, 'b'), (c, 'c')] if x != 'All']
if not notall:
return df
else:
???
</code></pre>
<p>将每个参数的名称写两次是很难看的,但要么是这样,要么就是用<code>locals</code>和/或<code>**kwargs</code>调皮。你知道吗</p>
<p>考虑到这一点,与<code>df</code>元素的比较很容易:</p>
<pre><code> compared = [df[name] == x for (x, name) in notall]
</code></pre>
<p>现在,我们如何和他们在一起?我们可以使用<a href="https://docs.python.org/3/library/functools.html#functools.reduce" rel="nofollow noreferrer">^{<cd6>}</a>和<a href="https://docs.python.org/3/library/operator.html#operator.and_" rel="nofollow noreferrer">^{<cd7>}</a>,但是(除非您重载了<code>==</code>以返回一个非布尔值,我希望您没有这样做),<code>compared</code>的元素都是布尔值,这意味着将它们与按位and组合与将它们与逻辑and组合相同,Python已经有了一个函数:<a href="https://docs.python.org/3/library/functions.html#all" rel="nofollow noreferrer">^{<cd10>}</a>。你知道吗</p>
<pre><code>return df[all(compared)]
</code></pre>
<p>综合起来:</p>
<pre><code>def view(a='', b='', c=''):
notall = [(x, name) for (x, name) in [(a, 'a'), (b, 'b'), (c, 'c')] if x != 'All']
if not notall:
return df
else:
compared = [df[name] == x for (x, name) in notall]
return df[all(compared)]
</code></pre>
<p>或者更紧凑:</p>
<pre><code>def view(a='', b='', c=''):
notall = [(x, name) for (x, name) in [(a, 'a'), (b, 'b'), (c, 'c')] if x != 'All']
if not notall:
return df
else:
return df[all(df[name] == x for (x, name) in notall)]
</code></pre>
<p>现在,关于前面提到的调皮行为:如果所有参数都在<code>dict</code>中,那么<code>notall</code>可以只包含键,这将允许我们查找参数值和<code>df</code>值,而不会重复我们自己(太多)。如何获得<code>dict</code>中的所有参数?使用<code>**kwargs</code>:</p>
<pre><code>def view(**kwargs):
notall = [name for name in NAMES if kwargs.get(name, '') != 'All']
</code></pre>
<p>(注意使用<code>get</code>为参数提供默认值)但是<code>NAMES</code>应该是什么?它不能是<code>kwargs.keys()</code>,因为它只包含用户传入的参数,可能不是所有参数(甚至可能包含我们不期望的键!)。选项1是在某处写出一个参数名列表,并使用:</p>
<pre><code>NAMES = ['a', 'b', 'c']
</code></pre>
<p>或者,如果<code>df</code>的键恰好与函数参数的所需名称相同,我们可以使用<code>df.keys()</code>:</p>
<pre><code> notall = [name for name in df.keys() if kwargs.get(name, '') != 'All']
</code></pre>
<p>或者,稍微短一点:</p>
<pre><code> notall = [name for name in df if kwargs.get(name, '') != 'All']
</code></pre>
<p>在此之后,我们只需要更新<code>notall</code>元素的使用方式,更改如下:</p>
<pre><code>return df[all(df[name] == x for (x, name) in notall)]
</code></pre>
<p>对此:</p>
<pre><code>return df[all(df[name] == kwargs.get(name, '') for name in notall)]
</code></pre>
<p>(注意,我们仍然需要继续使用<code>get</code>来设置默认值。)</p>
<p>把一切重新组合起来:</p>
<pre><code>NAMES = ['a', 'b', 'c']
def view(**kwargs):
notall = [name for name in NAMES if kwargs.get(name, '') != 'All']
if not notall:
return df
else:
return df[all(df[name] == kwargs.get(name, '') for name in notall)]
</code></pre>
<p>或者,如果参数名与<code>df</code>的键相同:</p>
<pre><code>def view(**kwargs):
notall = [name for name in df if kwargs.get(name, '') != 'All']
if not notall:
return df
else:
return df[all(df[name] == kwargs.get(name, '') for name in notall)]
</code></pre>
<p>编辑:根据下面的注释,<code>df</code>的值显然是覆盖<code>==</code>的值,因此它不会返回布尔值。幸运的是,如上所述,这只需要改变这一点:</p>
<pre><code>return df[all(df[name] == kwargs.get(name, '') for name in notall)]
</code></pre>
<p>对此:</p>
<pre><code>import functools
import operator
return functools.reduce(operator.and_, [df[name] == kwargs.get(name, '') for name in notall])
</code></pre>