我试图找到一种pythonic的方法来根据变量所在的位置来分配数值。即:
variable = 23
if variable < -100:
return_value = -15
elif variable <= -5:
return_value = -4
elif variable <= 5:
return_value = 18
else:
return_value = 88
我当然可以创建一个包含存储桶/值的列表,并在找到正确的值时进行遍历并返回:
bucket_values = [(-100, -15), (-5, -4), (5, 18)]
default = 88
variable = 100
for lower_bound, value in bucket_values:
if variable < lower_bound:
return_value = value
break
else:
return_value = default
但是然后我需要检查上下限和相等性,即如果是循环的第一次迭代,则必须检查下级(<),然后下一个循环必须检查下级和等于(<=)
我正在寻找这样的东西(Ruby):
buckets = [
[:<, -90, -57],
[:<=, 5, -10],
[:<=, 10, 3],
[:>, 60, 40]]
# Pass bucket to a method
我的问题是: 是否存在使用可变范围和值的Python方法?
答案 0 :(得分:1)
使用模块operator
非常简单。这是一个示例:
>>> import operator
>>> bucket = (operator.ge, -100, operator.le, -5)
>>> def in_bucket(value, bucket): return bucket[0](value, bucket[1]) and bucket[2](value, bucket[3])
...
>>> in_bucket(-101, bucket)
False
>>> in_bucket(-100, bucket)
True
>>> in_bucket(-5, bucket)
True
>>> in_bucket(-4, bucket)
False
但是,通过定义一个更通用的结构,您可以做得更好:
>>> conditions = ((operator.ge, -100), (operator.le, -5))
>>> def match_conditions(value, conditions): return all(c[0](value, c[1]) for c in conditions)
...
>>> match_conditions(-101, conditions)
False
>>> match_conditions(-100, conditions)
True
>>> match_conditions(-5, conditions)
True
>>> match_conditions(-4, conditions)
False
如果满足所有条件,则all
运算符将返回true。 bucket
和conditions
之间的主要区别在于,您可以添加不涉及边界的条件,例如,值必须成对:
>>> conditions = ((operator.ge, -100), (operator.le, -5), (lambda v, _: v%2==0, None))
>>> match_conditions(-7, conditions)
False
>>> match_conditions(-6, conditions)
True
>>> match_conditions(-5, conditions)
False
现在,您可以使用字典来总结您的情况(您给出的第一个示例):
>>> value_by_conditions = {
... ((operator.lt, -100),): -15,
... ((operator.ge, -100), (operator.le, -5)): -4,
... ((operator.gt, -5), (operator.le, 5)): 18,
... ((operator.gt, 5),): 88,
... }
>>> next((v for cs, v in value_by_conditions.items() if match_conditions(23, cs)), None)
88
>>> next((v for cs, v in value_by_conditions.items() if match_conditions(-101, cs)), None)
-15
>>> next((v for cs, v in value_by_conditions.items() if match_conditions(-100, cs)), None)
-4
注意:
next((x for x in xs if <test>), None)
采用xs
中通过测试的第一个元素。如果没有任何元素通过测试,它将返回默认值None
; value < 100
,然后是value >= 100
,等等。这真的是pythonic吗?我不确定。看看https://www.python.org/dev/peps/pep-0020/来提出自己的想法。
答案 1 :(得分:0)
我认为这是非常pythonic的,但是我不推荐
>>> variable = 23
>>> return_value = -5 if variable<-100 else -4 if variable<=-4 else 18 if variable<= 5 else 88
>>> print(return_value)
88
请注意,88
是默认值。
您可以创建一个基于与上面显示的if... else
相同的概念的函数。该功能将是这样的:
def pythonic(variable, bucket_values, default):
for k,v in bucket_values:
return_value = v if variable<k else "---"
if return_value != "---":
return return_value
return default
您可以像这样使用它:
>>> variable = 23
>>> bucket_values = [(-100, -15), (-5, -4), (5, 18)]
>>> print(pythonic(variable, bucket_values, 88))
88
>>> variable = 1
>>> print(pythonic(variable, bucket_values, 88))
18
答案 2 :(得分:0)
如果我对您的理解很好,那么每个“桶”都有一个间隔。要检查值是否属于某个间隔,可以定义一个函数:
def check_value(value, interval):
if value in range(interval[0], interval[1]+1):
print('Value ', value)
print('Interval ', interval)
else:
pass
现在只需遍历间隔列表以查找值所属位置:
for interval in list_of_intervals:
check_value(value, interval)