许多if语句的替代方案?

5

我有三个不同的变量。

model是一个字符串,定义了iPhone的型号。

storage是一个整数,定义了手机的存储容量。

最后是价格,是一个整数,定义了手机的价格。

例如:

model = iPhone 7
storage = 64 (GB)
price = 700 ($)

另一个例子:
model = iPhone 5s
storage = 16
price = 150

现在我希望我的程序能够提醒我是否可以通过购买和转售来获得好的交易,我的问题是如何以最有效的方式实现这一点?我知道我可以使用if语句,但有没有什么方法可以避免编写大量不同的if或elif语句呢?
示例:
if model == "iPhone 7" and storage == 64 and price <= 700:
print("do_something")

仅为一个模型和存储选项而写这么多代码,真是太多了。如果我要使用这种方法,我还得再写29个。


1
除非您可以比您的示例规则更具体,否则您必须编写那些if语句。但是,您可以找到更好的编写方式。例如,为每个模型封装不同类别的信息,并让这些类别具有返回任何适当的存储/价格组合的“真”方法,这种方式怎么样? - Alvae
@Denkan,请看一下我的“字典”方法,如果有帮助请告诉我。 - Devendra Lattu
8个回答

1

您需要创建一个“决策规则”,并使其能够被程序访问,这是很正常的。

1-2个提示:

您可能只指定了必须采取行动的条件,而没有指定不采取任何行动的条件。

您可以像这样使用字典来代替“and”,从而减少代码量:

deal2action = {
('iphone 7', '64', '700'):'ACT'
}

使用方法:

my_deal = ('iphone 7', '64', '700')
my_action = deal2action[my_deal]

0
在这种情况下,我更喜欢使用字典。
创建不同的处理程序(函数),根据传递的项和数据执行特定任务。请参见以下代码:
# Different handlers, each takes keyword args and can work specific task
def fun1(**kwargs):
    print (kwargs)
    print("fun1")


def fun2(**kwargs):
    print("fun2")

def fun3(**kwargs):
    print("fun3")

def fun4(**kwargs):
    print("fun4")


# Example data. key is phoneModel_storage
a = {
    'iPhone1_64': {
        "storage": 64,
        "action": fun1,
        "price":1235
    },
    'iPhone1_32': {
        "storage": 64,
        "action": fun3,
        "price":1235
    },
    'iPhone2_16': {
        "storage": 16,
        "action": fun1,
        "price":1235
    },
    'iPhone3_32': {
        "storage": 32,
        "action": fun3,
        "price":1235
    },
    'iPhone4_128': {
        "storage": 128,
        "action": fun4,
        "price":1235
    },
}

model = "iPhone1"
storage = 64

data = a.get(model + "_" + str(storage), None)
if data:
    data['action'](**data)

在函数参数中使用可变对象作为默认值通常会引起一些问题,需要注意。 - Adam Smith
这只是 def foo(some_arg = something_mutable):,因为 something_mutable 只被调用一次,所以那些意外改变它的函数会影响函数的全局状态。 - Adam Smith
我尝试在函数中更改kwargs,但它并没有更改实际数据(在函数调用后得到相同的数据)。 - Priyesh Kumar
请查看此例子和这个著名的 SO 问题。 - Adam Smith

0
你可以利用类来减少代码重复:
  class Phone():
    BEST_MODELS = ["IPHONE7", "IPHONE 5S", "Galaxy S3"]
    MIN_STORAGE = 100
    MAX_STORAGE = 200
    MIN_PRICE = 1000
    MAX_PRICE = 3000
    def __init__(self, model, storage, price):
        self.model = model
        self.storage = storage
        self.price = price

    def is_good_deal(self):
        return (self.model in Phone.BEST_MODELS
            and Phone.MIN_STORAGE <= self.storage <= Phone.MAX_STORAGE
            and Phone.MIN_PRICE <= self.price <= Phone.MAX_PRICE)

p1 = Phone("IPHONE7", 150, 1700)
p2 = Phone("LG G1", 150, 700)

print(p1.is_good_deal()) # True
print(p2.is_good_deal()) # False

比如说,如果你有一个手机的集合,你可以这样做:

lots_of_phones = [p1, p2]

good_deal_phones = (phone for phone in lots_of_phones if phone.is_good_deal())

这里的一个类似乎过于复杂了。在我看来,使用namedtuples和更多的函数式方法会更好。 - Adam Smith

0
if model, storage, price == "iPhone 7", 64, 700:
     print("do_something")

通常我会使用一些小型领域特定语言,并在字符串或csc文件中定义价格。
table =
"""Iphone 7, 64, 700
Iphone 6, 34, 500"""

lines = table.split('\n)  # for wider tables use standard csv package, but or for 3 columns
dico = dict( (r[0], r[1]), r[2]) for r in line.split(', ') for line in lines))
def good_deal(model, memory, price):
    return dico.get( (model, memory), 10000000 ) > price

0
如果你只关心检查特定模型是否完全匹配你拥有的数据,那么比较字典是一种方法。
>>> reference = {"model": "iPhone 5s", "storage": 16, "price": 550}
>>> tested = {"model": "iPhone 5s", "storage": 16, "price": 550}
>>> reference == tested
True

然而,如果您想要更广泛的标准,例如价格在某个范围内下降,则此方法将失败。

那么,您可以将参考字典存储在列表中,而不是编写29个if语句,并检查您测试的模型是否在该列表中,以实现最简单的操作。

tested in reference_list:
    # do something

0

你的使用情况非常适合使用哈希表(字典),可以使用元组或更好地使用命名元组。

from collections import namedtuple

Phone = namedtuple("Phone", "model storage price")

funcmap = {Phone("iPhone 7", 64, 700): \
             lambda p: print("Do something to ", p),
           Phone(...):  # etc
             ...,
           ... }

phone = Phone("iPhone 7", 64, 700)
f = funcmap[phone]  # maybe funcmap.get(phone, lambda _: None) in case it's new?
f(phone)

话虽如此,决策算法似乎更好。

def is_good_deal(phone: Phone) -> (bool, None):
    value_dict = {Phone("iPhone 7", 64, 700): 600,
                  ...}
    try:
        return phone.value < value_dict[phone]
    except KeyError:
        # phone isn't in value_dict
        return None

0

定义打印某些内容的方法

def method1():
    print "Yippee I have best iPhone 7 :)"

def method2():
    print "Oh! still it is an iPhone 7"

def method3():
    print "Yeah! I have best iPhone 5 :)"

def method4():
    print "Oh! base iPhone 5"    

if-else语句的字典

stuff = {'iPhone 7' : {'64GB' : { '$700' : method1}, '32GB' : { '$500' : method2}}, 'iPhone 5' : {'32GB' : { '$250' : method3}, '16GB' : { '$150' : method4}}}

访问语句并根据需要添加异常处理

stuff['iPhone 7']['64GB']['$700']()

enter image description here

参考 如何避免大量的if else条件语句


0

这里有很多答案,但仍然没有被接受的,所以我会再整理一个:

# Prepare a list of what you know will be good deals: 
dctGoodDeals = {}
dctGoodDeals[('iPhone 7',  64)] = 700
dctGoodDeals[('iPhone 5s', 16)] = 150

# You have got at that point in your code from somewhere: 
model = 'iPhone 7'; storage=64; price=500
# model = 'iPhone S'; storage=64; price=500

# 所以你可以在代码中放置以下内容: try: if (price <= dctGoodDeals[(model, storage)]): print("做某事") except: print("尚未在dctGoodDeals中:", model, "with", storage, "GB")

这样,您就可以获得所有要执行的打印输出,并节省编写所有if语句的输入工作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接