Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/283.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python:使用局部变量初始化编程类实例变量()_Python_Class_Micropython - Fatal编程技术网

Python:使用局部变量初始化编程类实例变量()

Python:使用局部变量初始化编程类实例变量(),python,class,micropython,Python,Class,Micropython,我有一个类,它有许多具有默认值的实例变量,可以在Instantiation中选择性地重写这些变量(注意:没有可变的默认参数) 由于多次编写self.x=x等都是多余的,所以我以编程方式初始化变量 以举例说明,考虑这个例子(为了简洁起见,它仅包含5个实例变量和省略< /强>的任何方法): 示例: # The "painful" way class A: def __init__(self, a, b=2, c=3, d=4.5, e=5): self.a = a

我有一个类,它有许多具有默认值的实例变量,可以在Instantiation中选择性地重写这些变量(注意:没有可变的默认参数)

由于多次编写
self.x=x
等都是多余的,所以我以编程方式初始化变量

以举例说明,考虑这个例子(为了简洁起见,它仅包含5个实例变量和<强>省略< /强>的任何方法):

示例:

# The "painful" way
class A:
    def __init__(self, a, b=2, c=3, d=4.5, e=5):
        self.a = a
        self.b = b
        self.c = c
        self.d = d
        self.e = e

# The "lazy" way
class B:
    def __init__(self, a, b=2, c=3, d=4.5, e=5):
        self.__dict__.update({k: v for k, v in locals().items() if k!='self'})

# The "better lazy" way suggested
class C:
    def __init__(self, a, b=2, c=3, d=4.5, e=5):
            for k, v in locals().items():
                if k != 'self':
                    setattr(self, k, v)

x = A(1, c=7)
y = B(1, c=7)
z = C(1, c=7)

print(x.__dict__)  # {'d': 4.5, 'c': 7, 'a': 1, 'b': 2, 'e': 5}
print(y.__dict__)  # {'d': 4.5, 'c': 7, 'a': 1, 'b': 2, 'e': 5}
print(z.__dict__)  # {'d': 4.5, 'c': 7, 'a': 1, 'b': 2, 'e': 5}
因此,为了让我的生活更轻松,我使用了B类中所示的习惯用法,其结果与A类相同

这是坏习惯吗?有什么陷阱吗

附录
使用这个习惯用法的另一个原因是为了节省一些空间——我打算在中使用它。无论出于何种原因,只有A类中所示的方法在其中起作用。

尝试一种更具python风格的方法:

class C:
  def __init__(self,a,b=2,c=3,d=4.5,e=5):
    for k,v in locals().iteritems():
      setattr(self,k,v)
c = C(1)
print c.a, c.b
1 2
这种方法可能长一两行,但行的长度较短,并且您的意图不太复杂。此外,任何试图重用您的代码的人都可以按预期访问对象的属性

希望这有帮助

编辑:删除了使用kwargs bc的第二种方法。它不满足默认变量要求


这里重要的一点是,如果像示例B类所示那样操作,代码用户将无法按预期访问对象的属性。

我建议使用
类a
中所示的代码。您拥有的是重复代码,而不是冗余代码,重复代码并不总是坏事。您只需编写一次
\uuuuu init\uuuu
,每个实例变量保留一个赋值是一个很好的文档(明确且清晰)说明您的类所期望的实例变量


不过,需要记住的一点是,太多可以初始化为不同参数的变量可能表明需要重新设计类。将一些单独的参数分组到单独的列表、DICT甚至其他类中是否更有意义?

是的。这是个坏习惯。为什么不使用
dict()
?它们一定是类属性吗?相关:。我想不出任何明显的陷阱,但我确实觉得这很糟糕。在我写的时候,我确实有方法,我只是把它们留作例子。我想类属性的自动完成在IDE中不会很有用。使用这种方法
kwargs
在这种情况下没有用处:不能保证传递所有需要的变量,不需要的变量可以作为实例变量传入和存储。第二种方法不允许默认值,这显然是问题中需要的。在第一种方法中,从迭代中排除
self
。如果需要默认值,请使用第一种方法@donkopotamus:setattr需要3个参数。第一个需要是对象的实例。如果在类定义内操作,则此实例必须是self。@donkopotamus oops,我的错,我明白你的意思。好的观点。他的意思是
self
包含在
locals()
中,因为它是方法签名的一部分,所以有效地创建了实例变量
self.self
指向,
self
Alex Martelli说了一些避免重复的话。然而,7年后,什么都没有了。所以¯\_(ツ)_/“…在这里,有一个+1。