关于python:__init__()函数内部和外部的变量

Variables inside and outside of a class __init__() function

我试着去理解,除了名字,这些课程之间还有什么区别吗?如果我在声明变量"value"时使用或不使用uuu in i t_uu()函数,会有什么不同吗?

1
2
3
4
5
6
7
8
9
10
11
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)

我主要担心的是,我将以一种方式使用它,当这将导致我的问题进一步发展(目前我使用的是init调用)。


__init__之外设置的变量属于该类。它们由所有实例共享。

__init__中创建并以self.开头的变量(以及所有其他方法函数)属于对象实例。


没有自我

创建一些对象:

1
2
3
4
class foo(object):
    x = 'original class'

c1, c2 = foo(), foo()

我可以更改c1实例,它不会影响c2实例:

1
2
3
c1.x = 'changed instance'
c2.x
>>> 'original class'

但如果我更改foo类,该类的所有实例也将更改:

1
2
3
foo.x = 'changed class'
c2.x
>>> 'changed class'

请注意python作用域是如何工作的:

1
2
c1.x
>>> 'changed instance'

用自己

更改类不会影响实例:

1
2
3
4
5
6
7
8
class foo(object):
    def __init__(self):
        self.x = 'original self'

c1 = foo()
foo.x = 'changed class'
c1.x
>>> 'original self'


我想在这个线程和这个线程(引用这个线程)中读到的响应中添加一些内容。

免责声明:这句话来自我做的实验

__init__以外的变量:

实际上,这些是静态类变量,因此可以访问类的所有实例。

__init__中的变量:

这些实例变量的值只能访问手头的实例(通过self引用)

我的贡献:

程序员在使用静态类变量时必须考虑的一件事是,它们可以被实例变量(如果您是通过self引用访问静态类变量)隐藏。

说明:

以前,我认为声明变量的两种方法完全相同(我很傻),部分原因是我可以通过self引用访问这两种变量。现在,当我遇到麻烦时,我研究了这个话题并把它澄清了。

通过访问静态类变量的问题self引用是指它只在没有同名实例变量的情况下引用静态类变量,更糟的是,试图通过self引用重新定义静态类变量不起作用,因为创建了一个实例变量,该实例变量随后隐藏了以前可访问的静态类变量。艾贝尔。

为了解决这个问题,应该始终通过类的名称引用静态类变量。

例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#!/usr/bin/env python

class Foo:
    static_var = 'every instance has access'

    def __init__(self,name):
        self.instance_var = 'I am ' % 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()

输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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

我希望这对某人有帮助


在S.lott的回复中,类变量被传递到元类新方法,并且在定义元类时可以通过字典访问。因此,即使在创建和实例化类之前,也可以访问类变量。

例如:

1
2
3
4
5
6
7
8
9
10
class meta(type):
    def __new__(cls,name,bases,dicto):
          # two chars missing in original of next line ...
          if dicto['class_var'] == 'A':
             print 'There'
class proxyclass(object):
      class_var = 'A'
      __metaclass__ = meta
      ...
      ...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class User(object):
    email = 'none'
    firstname = 'none'
    lastname = 'none'

    def __init__(self, email=None, firstname=None, lastname=None):
        self.email = email
        self.firstname = firstname
        self.lastname = lastname

    @classmethod
    def print_var(cls, obj):
        print ("obj.email obj.firstname obj.lastname")
        print(obj.email, obj.firstname, obj.lastname)
        print("cls.email cls.firstname cls.lastname")
        print(cls.email, cls.firstname, cls.lastname)

u1 = User(email='abc@xyz', firstname='first', lastname='last')
User.print_var(u1)

在上面的代码中,用户类有3个全局变量,每个变量的值为"none"。U1是通过实例化此类创建的对象。方法print_var打印类用户的类变量值和对象u1的对象变量。在下面的输出中,类变量User.emailUser.firstnameUser.lastname中的每一个都有值'none',而对象变量u1.emailu1.firstnameu1.lastname都有值'abc@xyz''first''last'

1
2
3
4
obj.email obj.firstname obj.lastname
('abc@xyz', 'first', 'last')
cls.email cls.firstname cls.lastname
('none', 'none', 'none')