__init__()内外变量的区别(类属性和实例属性)
这些类之间除了名字以外,真的有区别吗?
class WithClass ():
def __init__(self):
self.value = "Bob"
def my_func(self):
print(self.value)
class WithoutClass ():
value = "Bob"
def my_func(self):
print(self.value)
如果我在声明变量 value
时使用或不使用 __init__
方法,会有什么不同吗?
我最担心的是,我可能会用一种方式,但这样会在以后给我带来更多麻烦。
12 个回答
我想在这里补充一些我在这个讨论串和这个讨论串中看到的内容。
声明: 这些观点来自我自己的实验。
在 __init__
外的变量:
这些实际上是 静态类变量,因此可以被这个类的所有实例访问。
在 __init__
内的变量:
这些 实例变量 的值只能被当前的实例访问(通过 self
引用)。
我的补充:
程序员在使用 静态类变量 时需要考虑的一点是,它们可能会被 实例变量 盖掉(如果你通过 self
引用来访问 静态类变量)。
解释:
之前我以为这两种声明变量的方式是完全一样的(真是傻),部分原因是我可以通过 self
引用访问这两种变量。直到我遇到问题,才开始研究这个话题并弄清楚了。
通过 self
引用访问 静态类变量 的问题在于,只有当没有同名的 实例变量 时,它才会引用 静态类变量。更糟糕的是,试图通过 self
引用重新定义一个 静态类变量 是不行的,因为这会创建一个 实例变量,然后把之前可以访问的 静态类变量 盖掉。
为了解决这个问题,你应该始终通过类的名称来引用 静态类变量。
示例:
#!/usr/bin/env python
class Foo:
static_var = 'every instance has access'
def __init__(self,name):
self.instance_var = 'I am %s' % name
def printAll(self):
print 'self.instance_var = %s' % self.instance_var
print 'self.static_var = %s' % self.static_var
print 'Foo.static_var = %s' % Foo.static_var
f1 = Foo('f1')
f1.printAll()
f1.static_var = 'Shadowing static_var'
f1.printAll()
f2 = Foo('f2')
f2.printAll()
Foo.static_var = 'modified class'
f1.printAll()
f2.printAll()
输出:
self.instance_var = I am f1
self.static_var = every instance has access
Foo.static_var = every instance has access
self.instance_var = I am f1
self.static_var = Shadowing static_var
Foo.static_var = every instance has access
self.instance_var = I am f2
self.static_var = every instance has access
Foo.static_var = every instance has access
self.instance_var = I am f1
self.static_var = Shadowing static_var
Foo.static_var = modified class
self.instance_var = I am f2
self.static_var = modified class
Foo.static_var = modified class
希望这些对某些人有帮助。
没有 Self
先创建一些对象:
class foo(object):
x = 'original class'
c1, c2 = foo(), foo()
我可以改变 c1 这个实例,但这不会影响到 c2 这个实例:
c1.x = 'changed instance'
c2.x
>>> 'original class'
但是如果我改变了 foo 这个类,所有这个类的实例都会受到影响:
foo.x = 'changed class'
c2.x
>>> 'changed class'
请注意这里 Python 的作用域是怎么工作的:
c1.x
>>> 'changed instance'
有了 Self
改变类并不会影响到实例:
class foo(object):
def __init__(self):
self.x = 'original self'
c1 = foo()
foo.x = 'changed class'
c1.x
>>> 'original self'
在类的外面定义的变量属于这个类,所有的实例都会共享这些变量。
在__init__
(还有其他方法)里面创建的变量,如果前面有self.
,那么这些变量就属于这个对象的实例。