2012-06-13 241 views
59

学习python,并且有一些基本的疑问。Python变量声明

1.I看到变量声明(路径这里)作为

class writer: 
    path = "" 

有时,没有明确的声明,而是通过__init__初始化。

def __init__(self, name): 
    self.name = name 

我明白__init__的目的,但它是最好的任何其他职能声明变量。

2.如何创建变量来保存自定义类型?

class writer: 
    path = "" # string value 
    customObj = ?? 
+10

而且,关于第二个问题:在Python中,变量没有类型:值做。所以任何变量都可以容纳自定义对象。 – jpaugh

+3

如果您不再将名称/标识符视为_variables_,它将有所帮助。他们是_references_对象 –

+2

@gnibbler或他们的名字... – detly

回答

148

好的,首先要做的事情。

Python中没有“变量声明”或“变量初始化”这样的事情。

简而言之,我们称之为“分配”,但应该只是称为“命名”。

分配意味着“现在左侧的这个名称指的是评估右侧的结果,不管之前(如果有的话)引用了什么”。因此,Python的名称(可以说比“变量”更好的一个术语)没有关联的类型;但是,值的确如此。无论其类型如何,您都可以将相同的名称重新应用于任何事物,但事物仍然具有取决于其类型的行为。该名称只是一种引用值(对象)的方法。这回答你的第二个问题:你不要创建变量来保存自定义类型。您不会创建变量来保存任何特定的类型。你根本不“创造”变量。你给对象命名。

观点二:Python中遵循一个非常简单的规则,当涉及到的类,它实际上是比什么语言如Java,C++和C#做的更加一致:一切宣告内class块是类的一部分。因此,这里编写的函数(def)是方法,即类对象的一部分(不是以每个实例为基础存储),就像在Java,C++和C#中一样;但这里的其他名称是也是的一部分。同样,这些名称只是名称,它们没有关联类型,并且函数也是Python中的对象。因此:

class Example: 
    data = 42 
    def method(self): pass 

类是对象太,在Python。

所以现在我们创建了一个名为Example对象,它代表了所有事物的类别Example s。这个对象有两个用户提供的属性(在C++中,“成员”;在C#中,“字段或属性或方法”;在Java中,“字段或方法”)。其中一个名为data,它存储整数值42。另一个名为method,它存储一个函数对象。(还有几个Python自动添加的属性。)

虽然这些属性仍然不是对象的一部分。从根本上讲,一个对象只是一堆更多的名称(属性名称),直到你找到不能再分开的东西。因此,如果您有意设置这些值,则可以在类的不同实例之间共享值,甚至可以在不同类的对象之间共享值。

让我们创建一个实例:

x = Example() 

现在我们有一个名为x一个单独的对象,这是Example一个实例。 datamethod实际上并不是对象的一部分,但我们仍然可以通过x查找它们,因为Python在幕后有一些神奇的功能。特别是当我们查询method时,我们将取而代之得到一个“绑定方法”(当我们称之为x时,将自动作为self参数通过,如果我们直接查找Example.method则不会发生)。

当我们尝试使用x.data时会发生什么?

当我们检查它时,首先在对象中查找它。如果在对象中找不到它,Python将在该类中查找。

但是,当我们将分配给x.data时,Python将在该对象上创建一个属性。它将不是替换类的属性。

这使我们可以做对象初始化。如果存在,Python会在新实例创建时自动调用类'__init__方法。在这种方法中,我们可以简单地分配给属性为每个对象上的属性设置初始值:

class Example: 
    name = "Ignored" 
    def __init__(self, name): 
     self.name = name 
    # rest as before 

现在,当我们创建了一个Example,我们必须指定一个name,每个实例都有自己的name。无论何时查找实例的.name,Python都将忽略类属性Example.name,因为将首先找到实例的属性。

最后一条警告:修改(突变)和分配是不同的事情!

在Python中,字符串是不可变的。他们不能被修改。当你这样做:

a = 'hi ' 
b = a 
a += 'mom' 

不改变原来的“喜”字符串。在Python中这是不可能的。相反,您将创建字符串'hi mom',并导致a停止为'hi '的名称,而是开始为'hi mom'而不是名称。我们还为'hi '创建了名称b,并且在重新应用a名称后,b仍然是'hi '的名称,因为'hi '仍然存在并且未被更改。

但名单可以更改:

a = [1, 2, 3] 
b = a 
a += [4] 

现在b为[1,2,3,4]为好,因为我们同样的事情做b的名称a命名,然后我们改变那个东西。我们没有为a创建一个新名单,因为Python只是简单地将+=视为列表。

这对于对象很重要,因为如果您有一个列表作为类属性,并且使用实例修改列表,那么在所有其他实例中将会“看到”更改。这是因为(a)数据实际上是类对象的一部分,而不是任何实例对象; (b)因为你修改了列表而没有做简单的赋值,所以你没有创建一个隐藏类属性的新实例属性。

+8

这就是我们称之为['标识符'](http://docs.python.org/2/reference/lexical_analysis.html#identifiers)的原因。 :-) –

+0

@Karl_Knechtel在最后的字符串示例中,如果我们从未将其命名为'b',会发生什么情况?这是内存泄漏吗? – heretoinfinity

+1

@heretoinfinity:no; Python使用垃圾收集来释放无法访问的对象 –

1

变量有范围,所以是适当的变量是特定于您的函数。你并不总是必须明确他们的定义;通常你可以使用它们。只有当你想做一些特定于变量类型的事情时,比如追加列表,你是否需要在开始使用它们之前定义它们。这是典型的例子。

list = [] 
for i in stuff: 
    list.append(i) 

顺便说一下,这不是一个真正的设置列表的好方法。最好是说:

list = [i for i in stuff] # list comprehension 

......但我离题了。

您的其他问题。 自定义对象应该是一个类本身。

class CustomObject(): # always capitalize the class name...this is not syntax, just style. 
    pass 
customObj = CustomObject() 
18

有没有必要在Python中声明新的变量。如果我们正在讨论函数或模块中的变量,则不需要声明。只需将值分配给您需要的名称即可:mymagic = "Magic"。 Python中的变量可以保存任何类型的值,并且不能限制它。

虽然您的问题具体询问类,对象和实例变量。创建实例变量的惯用方法是在__init__方法和其他地方 - 而你可能创建新的实例变量在其他方法,甚至在不相关的代码,这只是一个坏主意。它会让你的代码难以推理或维护。

因此,例如:

class Thing(object): 

    def __init__(self, magic): 
     self.magic = magic 

容易。现在,这个类的实例有一个magic属性:

thingo = Thing("More magic") 
# thingo.magic is now "More magic" 

创建本身就导致不同的行为完全的类的命名空间的变量。它在功能上是不同的,如果你有特定的理由,你应该只做它。例如:

class Thing(object): 

    magic = "Magic" 

    def __init__(self): 
     pass 

现在试试:

thingo = Thing() 
Thing.magic = 1 
# thingo.magic is now 1 

或者:

class Thing(object): 

    magic = ["More", "magic"] 

    def __init__(self): 
     pass 

thing1 = Thing() 
thing2 = Thing() 
thing1.magic.append("here") 
# thing1.magic AND thing2.magic is now ["More", "magic", "here"] 

这是因为类本身的命名空间是从它创建的对象的命名空间不同。我会留给你去研究一下。

这是一个习惯用语,是(a)在你的__init__方法中初始化对象属性,(b)根据需要记录你的类的行为。你不需要为你写过的所有东西写出完整的狮身人面像级文档的麻烦,但至少对你或其他人可能需要的任何细节进行评论。

2

对于作用域的目的,我使用 -

custom_object =无