【问题标题】:implicit item assignment in python objectspython对象中的隐式项分配
【发布时间】:2020-02-11 22:25:46
【问题描述】:

我希望能够在不指定类的属性的情况下为其赋值。

想要做什么

A)


class HoldingStuff(object):

    def __init__(self, **args):
        self.a = 1
        self.b = '1'
        self.c = 2
        self.d = '3'
        self.e = 4
        for arg in args:
            self[arg] = args[arg]

first = HoldingStuff(a=5)
second = HoldingStuff(d=2, e='2')

当然,我可以在保存值的类中使用 dictionary。然而,这有一个很大的缺点,因为那时我不能对属性使用 代码完成。这使得它们难以重复使用和查找。 (属性是模拟的可变参数的扩展列表。)

什么有效(但不切实际)

B)


class HoldingStuff(object):

    def __init__(self, **args):
        self['a'] = 1
        self['b'] = '1'
        self['c'] = 2
        self['d'] = '3'
        self['e'] = 4
        for arg in args:
            self[arg] = args[arg]

有点作用

C)


class HoldingStuff(MutableMapping):

    def __init__(self, **args):
        self.a = 1
        self.b = '1'
        self.c = 2
        self.d = '3'
        self.e = 4
        for arg in args:
            self[arg] = args[arg]

    def __setitem__(self, k, v) -> None:
        if k =='a':
            self.a = v
        elif k =='b':
            self.b = v
        elif k =='c':
            self.c = v
        elif k =='d':
            self.d = v
        elif k =='e':
            self.e = v
        else:
            print(k, "Not available for class.")

    def __delitem__(self, v) -> None:
        pass

    def __getitem__(self, k) -> _VT_co:
        if k =='a':
            return self.a
        elif k =='b':
            return self.b
        elif k =='c':
            return self.c
        elif k =='d':
            return self.d
        elif k =='e':
            return self.e
        else:
            print(k, "Not available for class.")

    def __len__(self) -> int:
        return 5

    def __iter__(self):
        print("Not implemented")

函数__setitem____getitem__ 看起来很明显且重复!

问题 有没有办法减少示例 C) 的源代码以隐式方式工作 A)

【问题讨论】:

  • 你为什么要使用**args?如果您只是正常地写出参数列表并正常地从参数值中分配属性,则永远不会出现此问题。
  • 看起来你甚至 想要 支持任意额外的用户提供的名称,从那些 __getitem____setitem__ 方法(以及任意用户提供的名称也不适用于您所追求的代码完成)。允许调用者指定任意关键字是**的整个设计目的。

标签: python python-3.x


【解决方案1】:

使用setattr

for name, value in args.items():
    setattr(self, name, value)

【讨论】:

  • ee = HoldingStuff(e='2354345') throws ValueError: not enough values to unpack (expected 2, got 1)
  • 第一行应该是for name, value in args.items():
  • @Dion 谢谢工作得很好!我相应地编辑了答案并接受了它。
【解决方案2】:

感谢您的 cmets,帮助我找到了:

https://stackoverflow.com/a/6760593/3707039

提供了一个优雅的解决方案


class HoldingStuff(object):

    def __init__(self, **args):
        self.a = 1
        self.b = '1'
        self.c = 2
        self.d = '3'
        self.e = 4
        vars(self).update(args)

【讨论】:

    【解决方案3】:

    无法发表评论,因为我的声望低于 50。 在选项a中,

    class HoldingStuff(object):
    
        def __init__(self, **args):
            self.a = 1
            self.b = '1'
            self.c = 2
            self.d = '3'
            self.e = 4
            for arg in args:
                self[arg] = args[arg]
    
    first = HoldingStuff(a=5)
    second = HoldingStuff(d=2, e='2')
    

    你有线条:

    for arg in args:
        self[arg] = args[arg]
    

    但是你插入一个字符串并试图找到它的 args 索引

    second  = HoldingStuff(d=2, e='2') #e='2'
    

    我认为你应该尝试使用:

    for arg in range(len(args)):
        self[args[arg]] = args[arg]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-05-12
      • 2013-12-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-22
      • 1970-01-01
      相关资源
      最近更新 更多