__init__()函数类内外的变量

时间:2022-09-07 11:20:42

I'm trying to understand, is there any difference at all between these classes besides the name? Does it make any difference if I use or don't use the __init__() function in declaring the variable "value"?

我在努力理解,这些类除了名字之外还有什么区别吗?如果我在声明变量“value”时使用或不使用__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)

My main worry is that I'll be using it one way when that'll cause me problems further down the road (currently I use the init call).

我主要担心的是,我将以一种方式使用它,而这将在以后的道路上给我带来问题(目前我使用init调用)。

5 个解决方案

#1


156  

Variable set outside __init__ belong to the class. They're shared by all instances.

__init__外的变量集属于类。它们由所有实例共享。

Variables created inside __init__ (and all other method functions) and prefaced with self. belong to the object instance.

在__init__(和所有其他方法函数)中创建的变量,并预先面对self。属于对象实例。

#2


58  

Without Self

没有自我

Create some objects:

创建一些对象:

class foo(object):
    x = 'original class'

c1, c2 = foo(), foo()

I can change the c1 instance, and it will not affect the c2 instance:

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

c1.x = 'changed instance'
c2.x
>>> 'original class'

But if I change the foo class, all instances of that class will be changed as well:

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

foo.x = 'changed class'
c2.x
>>> 'changed class'

Please note how Python scoping works here:

请注意这里Python的作用域是如何工作的:

c1.x
>>> 'changed instance'

With Self

与自我

Changing the class does not affect the instances:

更改类不会影响实例:

class foo(object):
    def __init__(self):
        self.x = 'original self'

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

#3


5  

further to S.Lott's reply, class variables get passed to metaclass new method and can be accessed through the dictionary when a metaclass is defined. So, class variables can be accessed even before classes are created and instantiated.

进一步的年代。Lott的回复是,类变量被传递给元类新方法,并且可以在定义元类时通过字典进行访问。因此,即使在创建和实例化类之前,也可以访问类变量。

for example:

例如:

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
      ...
      ...

#4


4  

I would like to add something to the responses that I read in this thread and this thread (which references this one).

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

Disclaimer: this remarks come from the experiments I ran

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

Variables outside __init__:

__init__以外的变量:

These are, in fact, static class variables and are, therefore, accesible to all instances of the class.

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

Variables inside __init__:

__init__内变量:

The value of these instance variables are only accesible to the instance at hand (through the self reference)

这些实例变量的值只能与当前的实例相适应(通过自引用)

My contribution:

我的贡献:

One thing that programmers must consider when using static class variables is that they can be shadowed by instance variables (if you are accessing the static class variables through the self reference).

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

Explanation:

解释:

Previously, I thought that both ways of declaring the variables were exactly the same (silly me), and that was partly because I could access both kind of variables through the self reference. It was now, when I ran into trouble, that I researched the topic and cleared it up.

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

The problem with accessing static class variables through the self reference is that it only references the static class variable if there is no instance variable with the same name, and to make things worse, trying to redefine a static class variable through the self reference does not work because an instance variable is created which then shadows the previously-accesible static class variable.

的问题通过自我引用访问静态类变量,它只引用静态类变量如果没有同名的实例变量,而更糟的是,试图重新定义一个静态类变量通过自我参考不工作,因为一个实例变量创建阴影previously-accesible静态类变量。

To get around this problem, you should always reference static class variables through the name of the class.

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

Example:

例子:

#!/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()

Output:

输出:

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

I hope this is helpful to someone

我希望这对某人有帮助

#5


0  

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)

In the above code, the User class has 3 global variables, each with value 'none'. u1 is the object created by instantiating this class. The method print_var prints the value of class variables of class User and object variables of object u1. In the output shown below, each of the class variables User.email, User.firstname and User.lastname has value 'none', while the object variables u1.email, u1.firstname and u1.lastname have values 'abc@xyz', 'first' and 'last'.

在上面的代码中,User类有3个全局变量,每个变量的值为“none”。u1是通过实例化这个类而创建的对象。方法print_var打印对象u1的类用户和对象变量的类变量的值。在下面的输出中,每个类变量都是User。电子邮件、用户。firstname和用户。lastname值为“none”,对象变量为u1。电子邮件,u1。firstname和u1。lastname有“abc@xyz”、“first”和“last”的值。

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

#1


156  

Variable set outside __init__ belong to the class. They're shared by all instances.

__init__外的变量集属于类。它们由所有实例共享。

Variables created inside __init__ (and all other method functions) and prefaced with self. belong to the object instance.

在__init__(和所有其他方法函数)中创建的变量,并预先面对self。属于对象实例。

#2


58  

Without Self

没有自我

Create some objects:

创建一些对象:

class foo(object):
    x = 'original class'

c1, c2 = foo(), foo()

I can change the c1 instance, and it will not affect the c2 instance:

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

c1.x = 'changed instance'
c2.x
>>> 'original class'

But if I change the foo class, all instances of that class will be changed as well:

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

foo.x = 'changed class'
c2.x
>>> 'changed class'

Please note how Python scoping works here:

请注意这里Python的作用域是如何工作的:

c1.x
>>> 'changed instance'

With Self

与自我

Changing the class does not affect the instances:

更改类不会影响实例:

class foo(object):
    def __init__(self):
        self.x = 'original self'

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

#3


5  

further to S.Lott's reply, class variables get passed to metaclass new method and can be accessed through the dictionary when a metaclass is defined. So, class variables can be accessed even before classes are created and instantiated.

进一步的年代。Lott的回复是,类变量被传递给元类新方法,并且可以在定义元类时通过字典进行访问。因此,即使在创建和实例化类之前,也可以访问类变量。

for example:

例如:

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
      ...
      ...

#4


4  

I would like to add something to the responses that I read in this thread and this thread (which references this one).

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

Disclaimer: this remarks come from the experiments I ran

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

Variables outside __init__:

__init__以外的变量:

These are, in fact, static class variables and are, therefore, accesible to all instances of the class.

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

Variables inside __init__:

__init__内变量:

The value of these instance variables are only accesible to the instance at hand (through the self reference)

这些实例变量的值只能与当前的实例相适应(通过自引用)

My contribution:

我的贡献:

One thing that programmers must consider when using static class variables is that they can be shadowed by instance variables (if you are accessing the static class variables through the self reference).

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

Explanation:

解释:

Previously, I thought that both ways of declaring the variables were exactly the same (silly me), and that was partly because I could access both kind of variables through the self reference. It was now, when I ran into trouble, that I researched the topic and cleared it up.

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

The problem with accessing static class variables through the self reference is that it only references the static class variable if there is no instance variable with the same name, and to make things worse, trying to redefine a static class variable through the self reference does not work because an instance variable is created which then shadows the previously-accesible static class variable.

的问题通过自我引用访问静态类变量,它只引用静态类变量如果没有同名的实例变量,而更糟的是,试图重新定义一个静态类变量通过自我参考不工作,因为一个实例变量创建阴影previously-accesible静态类变量。

To get around this problem, you should always reference static class variables through the name of the class.

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

Example:

例子:

#!/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()

Output:

输出:

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

I hope this is helpful to someone

我希望这对某人有帮助

#5


0  

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)

In the above code, the User class has 3 global variables, each with value 'none'. u1 is the object created by instantiating this class. The method print_var prints the value of class variables of class User and object variables of object u1. In the output shown below, each of the class variables User.email, User.firstname and User.lastname has value 'none', while the object variables u1.email, u1.firstname and u1.lastname have values 'abc@xyz', 'first' and 'last'.

在上面的代码中,User类有3个全局变量,每个变量的值为“none”。u1是通过实例化这个类而创建的对象。方法print_var打印对象u1的类用户和对象变量的类变量的值。在下面的输出中,每个类变量都是User。电子邮件、用户。firstname和用户。lastname值为“none”,对象变量为u1。电子邮件,u1。firstname和u1。lastname有“abc@xyz”、“first”和“last”的值。

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