我来自Java背景。我正在阅读官方Python教程,但似乎无法找到与Python源文件名和类相关的信息。
在Java中,文件名与主类名和.java扩展名相同。在Python中是什么情况?在官方教程的示例中,他们正在编写多个类,并且没有提到文件名。我很丢失。
我有一个名为test_pie.py的文件名。内容是 -
class ListTest:
list1 = [2, 'a', 'ab', 'c', 'aa', 0]
list2 = ['b', list1[-2:-5]]
def PrintList(self):
print list1
print list2
对于list1和list2:我得到 -
未定义的变量:list1 list发现于:test_pie
未定义的变量:list2 list发现于:test_pie
答案 0 :(得分:10)
有一个档案。期。它包含的内容对导入没有兴趣,文件名或位置对包含的代码没有任何影响(通常 - 在执行期间 可访问,因此一些元编程使用它应该与实际价值无关。)
文件的内容不仅限于一个类,很少有人对自己施加这样的限制。 Python并不仅仅是一种OO语言,只要它是合理的,你就可以并且应该有免费的函数,并且模块在代码组织的类之上被看作一级 - 如果几个类紧密相关,它们应该可以放在一个模块中。
您的示例代码/问题与此无关,这是在给定文件中确定范围的问题。类确实有自己的作用域,但你不能也不应该在这样的方法(直接)中使用包含类的类变量 - 它会使代码无视子类中的新值集。相反,你要么使用类方法(顺便说一下,你应该阅读http://dirtsimple.org/2004/12/python-is-not-java.html),要么利用实例继承类的所有成员并只用self.
作为前缀的事实。
答案 1 :(得分:9)
在Python中,单个文件构成模块,类似于Java中的命名空间,因此您可以在同一文件中拥有单个命名空间的所有类。
答案 2 :(得分:3)
Java不是Python。 Python不是Java。您刚才发现很多差异;比你期望的更多。
在Java中,文件名与主类名和.java扩展名相同。在Python中是什么情况?
相反:文件名不一定与任何内容相同。
在官方教程的示例中,他们正在编写多个类,并且没有提到文件名。我很丢失。
因为没关系。 (请注意,在Java中,每个文件仍然可以有多个类,只要只有一个具有相应名称的类是public
。在Python中,public
实际上并不存在。)
对于list1和list2:我得到 -
未定义变量:list1 list找到:test_pie
未定义变量:list2 list发现于:test_pie
这是因为那些属性(在Java中称为“字段”)属于类,而不是对象。
该方法(与Java同名)仍然“属于”类,在Python中认为,但它是通过对象访问的。这就是为什么你需要一个明确的self
参数用于Python方法:因为my_object.do_something(x, y, z)
被隐式翻译成MyClass.do_something(my_object, x, y, z)
(或多或少;幕后有一些带有“绑定”的诡计,这允许你将my_object.do_something
视为一个对象。是的,在Python中,一切都是一个对象,甚至是函数。你认为Java是OO。哈。)
如果告诉Python在哪里查找它,您仍然可以通过对象访问类属性。在PrintList
内,list1
和list2
在范围内不 - 因为Python实际上只有两个范围:本地和全局。但是self
在范围内(它是一个参数,所以它在本地范围内),你可以访问self.list1
,因为在Python中查找对象的属性会回到类属性,如果有的话不是对象属性。 (实际上,它比这更复杂;你可以在进程中插入几个不同的特殊方法名钩子,更不用说如何处理继承了。)
所以你现在可能想知道如何将属性转换为实际的Python对象而不是类。答案是:你只需要分配它们。如果您没有任何限制,那么您可以随时使用任何名称分配它们。该对象基本上只是一本字典。如果您熟悉Java * 脚本 *(一种与Java完全无关的语言),那么它的工作方式相同。但是,为了控制疯狂,在特殊命名的方法__init__
中分配起始属性值是正常的,在创建对象时会立即自动调用(如果找到)(但是不是通常意义上的构造函数;该角色由__new__
扮演,但您几乎从未在Python中实际需要,然后只重新分配给那里设置的属性而不是创建新的属性
你可以设置限制,如果你有一个新式的类(在3.x中自动;在2.x中你必须至少间接地从内置类型object
继承),通过指定一个值对于名为__slots__
的特殊命名类属性。这应该是有效标识符名称的字符串列表。有了这个,Python将(a)使用这些信息来优化对象的内部数据存储; (b)禁止您向对象添加带有其他名称的属性; (c)禁止为对象实例创建特殊__dict__
属性,该属性是将属性名称映射到属性值的字典。 (你认为Java支持反射。哈。)它将不自动为命名属性赋值;在分配之前尝试访问它们将raise AttributeError
。