What is the difference between declaring data attributes inside or outside __init__
Possible Duplicate:
Python: Difference between class and instance attributes
我试图在Python中了解OOP,当它在类中声明变量时,我有点困惑。我应该在
以下代码工作正常:
1 2 3 4 5 6 7 8 9 10 11 12 | # Declaring variables within __init__ class MyClass: def __init__(self): country ="" city ="" def information(self): print"Hi! I'm from %s, (%s)"%(self.city,self.country) me = MyClass() me.country ="Spain" me.city ="Barcelona" me.information() |
但是在
1 2 3 4 5 6 7 8 9 10 11 | # Declaring variables outside of __init__ class MyClass: country ="" city ="" def information(self): print"Hi! I'm from %s, (%s)"%(self.city,self.country) me = MyClass() me.country ="Spain" me.city ="Barcelona" me.information() |
在第一个示例中,您定义的是实例属性。第二,类属性。
类属性在该类的所有实例之间共享,实例属性由该特定实例"拥有"。
示例差异
为了理解这些差异,我们使用一个例子。
我们将定义一个具有实例属性的类:
1 2 3 4 5 | class MyClassOne: def __init__(self): self.country ="Spain" self.city ="Barcelona" self.things = [] |
一个具有类属性:
1 2 3 4 | class MyClassTwo: country ="Spain" city ="Barcelona" things = [] |
以及一个打印这些对象信息的函数:
1 2 3 | def information(obj): print"I'm from {0}, ({1}). I own: {2}".format( obj.city, obj.country, ','.join(obj.things)) |
让我们创建2个
1 2 3 4 5 6 | foo1 = MyClassOne() bar1 = MyClassOne() foo1.city ="Milan" foo1.country ="Italy" foo1.things.append("Something") |
当我们在
1 2 3 4 5 | >>> information(foo1) I'm from Milan, (Italy). I own: Something >>> information(bar1) I'm from Barcelona, (Spain). I own: |
但是,如果我们要做完全相同的事情,但是使用
1 2 3 4 5 6 | foo2 = MyClassTwo() bar2 = MyClassTwo() foo2.city ="Milan" foo2.country ="Italy" foo2.things.append("Something") |
然后打电话给
1 2 3 4 | >>> information(foo2) I'm from Milan, (Italy). I own: Something >>> information(bar2) I'm from Barcelona, (Spain). I own: Something |
如您所见,
之所以在字符串变量中看不到这种行为,是因为实际上您正在为实例分配一个新的变量。在这种情况下,引用由实例"拥有",而不是在类级别共享。为了举例说明,让我们为
1 | bar2.things = [] |
这将导致:
1 2 3 4 | >>> information(foo2) I'm from Milan, (Italy). I own: Something >>> information(bar2) I'm from Barcelona, (Spain). I own: |
你的两个版本的代码是非常不同的。在Python中,有两个不同的实体:类和类实例。实例是在执行以下操作时创建的:
1 | new_instance = my_class() |
您可以通过
1 2 3 | class MyClass(object): def __init__(self): self.country ="" #every instance will have a `country` attribute initialized to"" |
关于
1 | a.method() #-> Inside the class where `method` is defined, `a` gets passed in as `self` |
这里唯一特别的是,在构造类时调用
1 | a = MyClass() #implicitly calls `__init__` |
还可以将属性绑定到类(将其放在
1 2 | class MyClass(object): country ="" #This attribute is a class attribute. |
在任何时候,您都可以通过以下方法将新属性绑定到实例:
1 2 | my_instance = MyClass() my_instance.attribute = something |
或类的新属性,方法是:
1 | MyClass.attribute = something |
现在它变得有趣了。如果一个实例没有被请求的属性,那么python将查看该属性的类并返回它(如果它在那里)。因此,类属性是类的所有实例共享一段数据的一种方式。
考虑:
1 2 3 4 5 6 7 8 9 10 11 12 | def MyClass(object): cls_attr = [] def __init__(self): self.inst_attr = [] a = MyClass() a.inst_attr.append('a added this') a.cls_attr.append('a added this to class') b = MyClass() print (b.inst_attr) # [] <- empty list, changes to `a` don't affect this. print (b.cls_attr) # ['a added this to class'] <- Stuff added by `a`! print (a.inst_attr) #['a added this'] |
在类作用域中定义变量(在任何方法之外)时,它将成为类属性。在方法范围中定义值时,它将成为方法局部变量。如果将值赋给