【问题标题】:Calling a function with different object variables调用具有不同对象变量的函数
【发布时间】:2014-11-25 21:14:47
【问题描述】:

在 Python 中,我有一个对象列表,每个对象都有两个变量:

class a_object:
    def __init__(self, input1, input2):
        self.data1=input1
        self.data2=input2

a_list=[]

for i in range(5):
    a_list.append(a_object(i,i+5))

我希望能够使用此列表调用函数,并且该函数将有一个参数来确定是对 data1 还是 data2 进行操作。

例如:

def find_sum(list_name, variable_name):
    total=0
    for i in range(len(list_name)):
        total=total+list_name[i].variable_name
    return total

total1=find_sum(a_list,data1)  #0+1+2+3+4
total2=find_sum(a_list,data2)  #5+6+7+8+9

我可以将 variable_name 参数设为一个整数,并在 if 语句中为每个整数值包含一个函数代码版本,但这不太通用。

【问题讨论】:

  • 类a_object ??这有效吗?
  • 嗯,它是有效的,假设input1input2是全局变量,其值符合type协议,self是一个全局变量__dict__… 但它并不完全有用
  • @gosom - 我认为 OP 正在发布伪代码。我编辑了他的答案以获得正确的语法。

标签: python list function object


【解决方案1】:

我希望能够使用此列表调用函数,并且该函数将有一个参数来确定是对 data1 还是 data2 进行操作。

在这种情况下,您不需要名为 data1data2 的属性,您需要一个名为 data 的属性,它是两个值的列表或其他集合。

属性用于静态引用的事物,使用硬编码到代码中的名称。你可以看出你在应该使用属性的时候使用了元素,因为你最终不得不到处写spam['eggs']而不是spam.eggs,这很难看。

元素用于动态引用的东西,使用变量中传递的名称(或索引)。你可以说你在应该使用元素的时候使用了属性,因为你最终不得不到处写getattr(spam, 'eggs')而不是spam['eggs'],这更难看。 (或者,对于新手来说,你最终甚至不知道如何编写代码——但iCodez's answer 解释了如何编写代码。)

例如:

class AObject(object):
    def __init__(self, *data):
        self.data = data
    def find_sum(self, values, data_index):
        total=0
        for i in range(len(values)):
            total=total+values[i].data[data_index]
        return total

如果您想使用名称而不是索引,请使用字典而不是列表。例如:

def __init__(self, data1, data2):
    self.data = {'data1': data1, 'data2': data2}
def find_sum(self, values, data_name):
    total=0
    for i in range(len(values)):
        total=total+values[i].data[data_name]
    return total

或者也许使用索引,但命名它们:

data1, data2 = 0, 1

(或者,更好的是,使用enum.IntEnum。)

请参阅Keep data out of your variable namesWhy you don't want to dynamically create variables 了解更多说明。

【讨论】:

    【解决方案2】:

    您可以使用getattr 并将属性名称作为字符串传递:

    def find_sum(list_name, variable_name):
        total=0
        for i in range(len(list_name)):
            total += getattr(list_name[i], variable_name)
        return total
    

    或者,更简洁一点:

    def find_sum(list_name, variable_name):
        return sum(getattr(x, variable_name) for x in list_name)
    

    下面是一个演示:

    >>> class a_object:
    ...     def __init__(self, input1, input2):
    ...         self.data1=input1
    ...         self.data2=input2
    ...
    >>> a_list=[]
    >>> for i in range(5):
    ...     a_list.append(a_object(i,i+5))
    ...
    >>> def find_sum(list_name, variable_name):
    ...     return sum(getattr(x, variable_name) for x in list_name)
    ...
    >>> find_sum(a_list, 'data1')
    10
    >>> find_sum(a_list, 'data2')
    35
    >>>
    

    【讨论】:

    • 可以这样做,但你可能不应该
    • 我承认,您的回答更简洁。 :) 我发布了这个解决方案,因为我不知道 OP 是否可以/想要制作 find_sum 一种方法。如果不是这种情况并且他需要动态访问属性,那么他就会被getattr 卡住。
    • 对于合适的情况,我确实链接到了您的答案。但是很多人在他们真的不应该这样做的时候提出这个要求,我认为覆盖这部分很重要。
    猜你喜欢
    • 1970-01-01
    • 2015-12-07
    • 2018-10-06
    • 1970-01-01
    • 1970-01-01
    • 2011-01-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多