无论如何在任意传递对象之后使用对象的名称?

时间:2016-06-27 17:37:59

标签: python parameters

我需要将不同数量的船只传递给代码,但是当我在hit_or_miss函数中时仍然可以使用他们的名字。有没有办法传递任意数量的参数(作为对象),但仍然专门按名称访问它们?

hit_or_miss(ship_1, ship_2, ship_3)

def hit_or_miss(*args):    
# Everything from here on should go in your for loop!
# Be sure to indent four spaces!
    ships_sunk = 0
    for turn in range(4):
        print "Turn", turn + 1
        guess_row  = int(raw_input("Guess Row:"))
        guess_col  = int(raw_input("Guess Col:"))
        guess_loc  = ((guess_row,guess_col))
        # A correct guess congratulates and exits the game
        if guess_loc in ship_1.location or \
           guess_loc in ship_2.location or \
           guess_loc in ship_3.location:
            print "Congratulations! You sunk a battleship!"
            ships_sunk += 1
            board[guess_row - 1][guess_col - 1] = "H"

5 个答案:

答案 0 :(得分:1)

你可以尝试用你的args上的循环替换你的if语句。

hit_or_miss(ship_1, ship_2, ship_3)

def hit_or_miss(*args):    
    ships_sunk = 0
    for turn in range(4):
        print "Turn", turn + 1
        guess_row  = int(raw_input("Guess Row:"))
        guess_col  = int(raw_input("Guess Col:"))
        guess_loc  = ((guess_row,guess_col))
        # A correct guess congratulates and exits the game

        # Try something like this
        for ship in args:
            if guess_loc in ship.location:
                print("Congratulations! You sunk a {}".format(ship.ship_type))
                ships_sunk +=1
                board[guess_row - 1][guess_col - 1] = "H"

我假设args是你传入的类,你可以添加ship_type属性。 (我没有对此进行测试,因此您可能需要对其进行调整。)

请注意,在函数内部,* args现在是可迭代的args。只要在函数定义中包含*,名称args就是任意的。您可以使用def hit_or_miss(*args)然后循环ships。这允许您循环传递到函数中的所有内容。

您可能也对**kwargs感兴趣,但我认为这不是您的功能所必需的。

答案 1 :(得分:0)

你可以使用kwargs。它们基本上将您的键值参数转换为您可以在函数中访问的字典:

def hit_or_miss(**kwargs): 
    print kwargs

hit_or_miss(ship1=ship1, ship2=ship2)
>>> {'ship2': *yourshipobject*, 'ship1': *yourshipobject*}

答案 2 :(得分:0)

没有检查上部堆栈框架就无法做到这一点,检查堆栈框架通常是一个坏主意。

更好的方法是将一个属性(可能是ship._name)注入该类,然后将其映射到:

ships = {ship._name: ship for ship in args}

然后您可以将其作为普通字典进行访问:

ships["ship1"].location

或迭代它们:

for ship in ships.values():
    print(ship.location)

使用**kwargs仍然需要您传递名称,我相信在这种情况下它不会像注射一样模块化。

答案 3 :(得分:0)

1)为什么你不能使用船只清单?

def hit_or_miss(ships): 
  for ship in ships: pass

hit_or_miss([ship1, ship2, ship3]) 

2)或者使用可变数量的参数声明hit_or_miss

def hit_or_miss(*ships): 
  for ship in ships: pass

hit_or_miss(ship1, ship2, ship3) 

3)如果您需要命名参数,请将字典传递给函数

def hit_or_miss(**ships): 
  for ship in ships: pass
  # ships are accessed with ships['ship1'] etc. 
hit_or_miss(ship1=Ship(...), ship2=Ship(...))

4)不要这样做,但你可以通过动态评估新变量来获得所需的行为。这使您的代码难以阅读和调试,并可能暴露安全漏洞。除非你有充分的理由这样做,否则请使用前三个中的一个。

def hit_or_miss(ships): 
  for i in range(len(ships)): 
    exec(('ship{} = ships[{}]').format(i, i))
  # we can access `ship1` here now. 

hit_or_miss([ship1, ship2, ship3])

答案 4 :(得分:0)

我认为你误解了“任意”这个词。这意味着传递给函数的船舶数量可变,而不仅仅是3。

如果你的功能应该只按照名称引用3艘船,则该功能应该采用3个参数:

def hit_or_miss(ship1, ship2, ship3):

这不会允许可变数量的船舶,但会比您当前的版本效果更好!

当您编写函数时,您正在使用全局变量ship_1, ship_2, ship_3,所以如果我调用您的函数:

hit_or_miss(a,b,c)

您的函数会查找名为ship_1, ship_2, ship_3的全局定义变量,完全忽略参数!

同样,您如何期望按名称引用可变数量的船舶?如果你把这个函数称为:

hit_or_miss(ship_a, ship_b) #only 2 arguments, no ship_3

hit_or_miss(s1, s2, s3, s4) #4 arguments, how do you name the fourth?

所以没有办法取任意数量的参数并按名称引用所有参数。但是,您只在这一条件下使用船只:

    if guess_loc in ship_1.location or \
       guess_loc in ship_2.location or \
       guess_loc in ship_3.location:

看起来很像你想检查条件是否为any,所以具有可变数量的船只的等价物将是:

if any((guess_loc in ship.location) for ship in args):

这将检查参数中传递的any船只是否符合条件。