在Python中跟踪类实例变量的好方法是什么?

时间:2009-01-30 18:21:13

标签: python variables

我是一名刚开始学习Python的C ++程序员。我想知道如何在大型Python类中跟踪实例变量。我习惯有一个.h文件,它给了我一个整齐的列表(包括评论),所有班级的成员。但是,由于Python允许你动态添加新的实例变量,你如何跟踪它们呢?

我正在想象一个场景,当我已经有一个新的实例变量时,我错误地添加了一个新的实例变量 - 但它离我工作的地方有1000行。是否有避免这种做法的标准做法?

编辑:看来我对术语“成员变量”造成了一些困惑。我的意思是实例变量,我已经相应地编辑了我的问题。

10 个答案:

答案 0 :(得分:10)

我想说,避免这种情况的标准做法是不要编写类别,距离任何地方1000行!

说真的,对于任何有用的类来说,这太过分了,特别是在一种像Python一样富有表现力的语言中。使用标准库提供的更多内容并将代码抽象到单独的模块中应有助于保持LOC计数。

标准库中最大的类别远低于100行!

答案 1 :(得分:8)

首先:类属性或实例属性?或两者? =)

通常你只需要在__init__中添加实例属性,在类定义中添加类属性,通常在方法定义之前...这应该涵盖90%的用例。

如果代码动态添加属性,它可能(希望:-)有充分的理由这样做......利用动态功能,内省等等。除此之外,以这种方式添加属性可能不如你想象的那么常见

答案 2 :(得分:4)

应该在类的__init__()方法中初始化实例变量。 (一般而言)

如果那是不可能的。您可以使用__dict__在运行时获取对象的所有实例变量的字典。如果您真的需要在文档中跟踪它,请将您正在使用的实例变量列表添加到类的docstring中。

答案 3 :(得分:4)

pylint可以静态检测__init__中未检测到的属性,以及许多其他潜在错误。

我还建议编写单元测试并经常运行代码来检测这些类型的“whoopsie”编程错误。

答案 4 :(得分:3)

听起来你在谈论实例变量而不是类变量。请注意,在以下代码中,a是类变量,b是实例变量。

class foo:
  a = 0 #class variable

  def __init__(self):
    self.b = 0 #instance variable

关于你创建一个不需要的实例变量的假设,因为另一个是大约一千行之外:最好的解决方案是不要有一千行长的类。如果你无法避免长度,那么你的课程应该有一个明确的目的,这将使你能够立即保持头脑中的所有复杂性。

答案 5 :(得分:3)

文档生成系统(如Epydoc)可用作对象所具有的实例/类变量的参考,如果您担心通过拼写错误意外创建新变量,则可以使用{{3}检查你的代码。

答案 6 :(得分:2)

这是我从许多来自C,C ++或其他静态类型语言的程序员那里听到的常见问题,其中变量是预先声明的。事实上,当我们说服我们组织的程序员放弃C代替高级程序并使用Python时,这是我们听到的最大问题之一。

理论上,是的,您可以随时向对象添加实例变量。是的,它可能发生在拼写错误等。实际上,它很少会导致错误。当它发生时,通常不难发现错误。

只要您的类没有膨胀(1000行非常大!)并且您有足够的单元测试,您应该很少遇到真正的问题。如果你这样做,几乎可以随时放到Python控制台,并根据自己的意愿检查。

答案 7 :(得分:2)

在我看来,这里的主要问题是当你在python中工作时,你正在思考C ++。

拥有一个1000行的类在python中不是一个非常明智的东西,(我知道它在C ++中有很多发生),

学习利用python为您提供的动力,例如,您可以以非常有创意的方式组合列表和词典,并为您自己保存数百个无用的代码行。

例如,如果要将字符串映射到函数(用于调度),则可以利用函数是第一类对象并具有类似的字典:

d = {'command1' : func1, 'command2': func2, 'command3' : func3}
#then somewhere else use this list to dispatch
#given a string `str`
func = d[str]
func() #call the function!

C ++中的这类内容会占用很多行代码!

答案 8 :(得分:0)

最简单的方法是使用IDE。 PyDev是eclipse的插件。

我不是所有pythonic专家,但一般来说我在python的类定义下定义我的类成员,所以如果我添加成员,它们都是相对的。

我个人认为,出于这个特定原因,应该在一个部分宣布集体成员。

本地范围的变量otoh应该被定义为最接近它们的时候(C中除外 - 我认为仍然需要在方法的开头声明变量)。

答案 9 :(得分:-2)

考虑使用slots

例如:

   class Foo:
     __slots__ = "a b c".split()
   x = Foo()
   x.a =1    # ok
   x.b =1    # ok
   x.c =1    # ok
   x.bb = 1  # will raise "AttributeError: Foo instance has no attribute 'bb'"

任何动态编程语言 - 任何不需要变量声明的语言 - 通常都是一个问题 - 变量名中的拼写错误会创建一个新变量而不是引发异常或导致编译时错误。插槽有助于实例变量,但对模块范围变量,全局变量,局部变量等没有帮助。对此没有灵丹妙药;这是不必申报变量的权衡的一部分。