简体   繁体   English

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

[英]What's a good way to keep track of class instance variables in Python?

I'm a C++ programmer just starting to learn Python. 我是一名刚开始学习Python的C ++程序员。 I'd like to know how you keep track of instance variables in large Python classes. 我想知道如何在大型Python类中跟踪实例变量。 I'm used to having a .h file that gives me a neat list (complete with comments) of all the class' members. 我习惯有一个.h文件,它给了我一个整齐的列表(包括评论)所有类的成员。 But since Python allows you to add new instance variables on the fly, how do you keep track of them all? 但是,由于Python允许您动态添加新的实例变量,您如何跟踪它们?

I'm picturing a scenario where I mistakenly add a new instance variable when I already had one - but it was 1000 lines away from where I was working. 我正在想象一个场景,当我已经有一个新的实例变量时,我错误地添加了一个新的实例变量 - 但它离我工作的地方有1000行。 Are there standard practices for avoiding this? 是否有避免这种情况的标准做法?

Edit: It appears I created some confusion with the term "member variable." 编辑:看起来我对术语“成员变量”产生了一些困惑。 I really mean instance variable, and I've edited my question accordingly. 我的意思是实例变量,我已经相应地编辑了我的问题。

I would say, the standard practice to avoid this is to not write classes where you can be 1000 lines away from anything! 我想说,避免这种情况的标准做法是不要写类,你可以在1000行以外的任何地方!

Seriously, that's way too much for just about any useful class, especially in a language that is as expressive as Python. 说真的,对于任何有用的类来说,这太过分了,特别是在与Python一样富有表现力的语言中。 Using more of what the Standard Library offers and abstracting away code into separate modules should help keeping your LOC count down. 使用标准库提供的更多内容并将代码抽象到单独的模块中应该有助于保持LOC的倒计时。

The largest classes in the standard library have well below 100 lines! 标准库中最大的类别远低于100行!

First of all: class attributes, or instance attributes? 首先:类属性还是实例属性? Or both? 或两者? =) =)

Usually you just add instance attributes in __init__ , and class attributes in the class definition, often before method definitions... which should probably cover 90% of use cases. 通常,您只需在__init__添加实例属性,在类定义中添加类属性,通常在方法定义之前...这应该涵盖90%的用例。

If code adds attributes on the fly, it probably (hopefully :-) has good reasons for doing so... leveraging dynamic features, introspection, etc. Other than that, adding attributes this way is probably less common than you think. 如果代码动态添加属性,它可能(希望:-)有充分的理由这样做......利用动态特性,内省等。除此之外,以这种方式添加属性可能不像你想象的那么常见。

Instance variables should be initialized in the class's __init__() method. 实例变量应该在类的__init__()方法中初始化。 (In general) (一般来说)

If that's not possible. 如果那是不可能的。 You can use __dict__ to get a dictionary of all instance variables of an object during runtime. 您可以使用__dict__在运行时获取对象的所有实例变量的字典。 If you really need to track this in documentation add a list of instance variables you are using into the docstring of the class. 如果您真的需要在文档中跟踪它,请将您正在使用的实例变量列表添加到类的docstring中。

pylint can statically detect attributes that aren't detected in __init__ , along with many other potential bugs. pylint可以静态检测__init__中未检测到的属性,以及许多其他潜在的错误。

I'd also recommend writing unit tests and running your code often to detect these types of "whoopsie" programming mistakes. 我还建议编写单元测试并经常运行代码来检测这些类型的“whoopsie”编程错误。

It sounds like you're talking about instance variables and not class variables. 听起来你在谈论实例变量而不是类变量。 Note that in the following code a is a class variable and b is an instance variable. 请注意,在以下代码中,a是类变量,b是实例变量。

class foo:
  a = 0 #class variable

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

Regarding the hypothetical where you create an unneeded instance variable because the other one was about one thousand lines away: The best solution is to not have classes that are one thousand lines long. 关于你在哪里创建一个不需要的实例变量的假设,因为另一个是大约一千行;最好的解决方案是不要有一千行长的类。 If you can't avoid the length, then your class should have a well defined purpose and that will enable you to keep all of the complexities in your head at once. 如果你无法避免长度,那么你的课程应该有一个明确的目的,这将使你能够立刻保持头脑中的所有复杂性。

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

This is a common concern I hear from many programmers who come from a C, C++, or other statically typed language where variables are pre-declared. 这是我从许多程序员那里听到的一个常见问题,他们来自C,C ++或其他静态类型语言,其中变量是预先声明的。 In fact it was one of the biggest concerns we heard when we were persuading programmers at our organization to abandon C for high-level programs and use Python instead. 事实上,当我们说服我们组织的程序员放弃C用于高级程序并使用Python时,这是我们听到的最大问题之一。

In theory, yes you can add instance variables to an object at any time. 理论上,是的,您可以随时向对象添加实例变量。 Yes it can happen from typos, etc. In practice, it rarely results in a bug. 是的,它可能发生在拼写错误等。实际上,它很少会导致错误。 When it does, the bugs are generally not hard to find. 当它发生时,通常不难发现错误。

As long as your classes are not bloated (1000 lines is pretty huge!) and you have ample unit tests, you should rarely run in to a real problem. 只要你的类没有膨胀(1000行是非常巨大的!)并且你有足够的单元测试,你应该很少遇到真正的问题。 In case you do, it's easy to drop to a Python console at almost any time and inspect things as much as you wish. 如果你这样做,几乎可以随时放到Python控制台,并根据需要检查事物。

It seems to me that the main issue here is that you're thinking in terms of C++ when you're working in python. 在我看来,这里的主要问题是当你在python中工作时,你正在思考C ++。

Having a 1000 line class is not a very wise thing anyway in python, (I know it happens alot in C++ though), 拥有一个1000行的类在python中不是一个非常明智的东西,(我知道它在C ++中有很多发生),

Learn to exploit the dynamism that python gives you, for instance you can combine lists and dictionaries in very creative ways and save your self hundreds of useless lines of code. 学习利用python为您提供的动力,例如,您可以以非常有创意的方式组合列表和词典,并为您自己保存数百个无用的代码行。

For example, if you're mapping strings to functions (for dispatching), you can exploit the fact that functions are first class objects and have a dictionary that goes like: 例如,如果要将字符串映射到函数(用于调度),则可以利用函数是第一类对象并具有如下字典的事实:

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!

Something like this in C++ would take up sooo many lines of code! 在C ++中这样的东西会占用很多行代码!

The easiest is to use an IDE. 最简单的方法是使用IDE。 PyDev is a plugin for eclipse. PyDev是eclipse的插件。

I'm not a full on expert in all ways pythonic, but in general I define my class members right under the class definition in python, so if I add members, they're all relative. 我不是所有方式pythonic的专家,但一般来说我在python的类定义下定义我的类成员,所以如果我添加成员,他们都是相对的。

My personal opinion is that class members should be declared in one section, for this specific reason. 我个人认为,由于这个特殊原因,应该在一个部分宣布集体成员。

Local scoped variables, otoh, should be defined closest to when they are used (except in C--which I believe still requires variables to be declared at the beginning of a method). 本地范围的变量otoh应该被定义为最接近它们的时候(C中除外 - 我认为仍然需要在方法的开头声明变量)。

Consider using slots . 考虑使用插槽

For example: 例如:

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'"

It is generally a concern in any dynamic programming language -- any language that does not require variable declaration -- that a typo in a variable name will create a new variable instead of raise an exception or cause a compile-time error. 它通常是任何动态编程语言中的一个问题 - 任何不需要变量声明的语言 - 变量名中的拼写错误会创建一个新变量而不是引发异常或导致编译时错误。 Slots helps with instance variables, but doesn't help you with, module-scope variables, globals, local variables, etc. There's no silver bullet for this; 插槽有助于实例变量,但对模块范围变量,全局变量,局部变量等没有帮助。对此没有灵丹妙药; it's part of the trade-off of not having to declare variables. 这是不必申报变量的权衡的一部分。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM