在类中编写代码和在python中定义 __init__(self) 有什么区别?

What is the difference writing code in a class and in def __init__(self) in Python?

本问题已经有最佳答案,请猛点这里访问。

Possible Duplicate:
Variables inside and outside of a class __init__() function

我理解,当调用一个类时,它会先运行__init__中的代码。我仍然看不出这两者之间的区别,而是直接在类下编写代码。

例如:

1
2
3
4
5
class main():
  x = 1

  def disp(self):
    print self.x
1
2
3
4
5
6
class main():
  def __init__(self):
    self.x = 1

  def disp(self):
    print self.x

对我来说,两者都具有相同的功能。(也许我漏掉了什么)我想知道哪一个更像(啊哈)Python,为什么。


如前所述,类属性(在类级别分配)和实例属性(例如在__init__中分配为自属性)是不同的。

另一方面,在第一个类中,您定义了两个不同的属性(类x和实例x,它们共存,但可能相互干扰。下面的代码试图显示如果用这种方式定义类,可能会遇到的问题。

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
30
31
32
33
34
35
36
37
38
39
40
In [32]: class main():
   ....:     x = 1
   ....:     def disp(self):
   ....:         print(self.x)
   ....:

# I create 2 instances
In [33]: jim = main()
In [34]: jane = main()

# as expected...:
In [35]: main.x
Out[35]: 1

In [36]: jim.x
Out[36]: 1

In [37]: jane.x
Out[37]: 1

# now, I assign to jim attribute x
In [38]: jim.x = 5

# main class preserves its attribute value as well as jane instance  
In [39]: main.x
Out[39]: 1

In [40]: jane.x
Out[40]: 1

# But what happens if I change the class attribute ?
In [41]: main.x = 10

# nothing to jim (I overwrote before jim.x)
In [42]: jim.x
Out[42]: 5

# but jane did see the change
In [43]: jane.x
Out[43]: 10

这里有两个关键的区别,一个是__init__,另一个是在课堂下写,还有你写的东西。

x = 1合作

首先,您是对的——这两项代码实际上为您的目的做了相同的事情(特别是因为我们在这里处理int对象,对于可变对象,这是不同的):

请注意,他们实际上并没有做同样的事情——请参阅对这个答案的评论以获得澄清。

1
2
class main(object):
    x = 1
1
2
3
class main(object):
    def __init__(self):
        self.x = 1

这就是为什么许多非标准的python库(如mongoenginedjango模型)都有一个标准,即在不使用__init__语句的情况下创建类,以避免覆盖内置的类,但仍允许创建类属性,例如django示例:

1
2
3
class mymodel(models.model):
    name = models.CharField(max_length=20)
    url = models.UrlField()

然而,正如另一张海报所指出的那样,两者之间有一个区别,即当x=1__init__函数之外时,即使没有初始化,它也是类本身的一部分——有关详细信息,请参阅zagorulkin dmitry的答案。不过,在大多数情况下,这种区别对你来说并不重要。

其他注意事项

除了设置变量外,__init__还有更多的用途。最重要的一点是可以在初始化期间接受参数。据我所知,如果没有__init__功能,就没有办法做到这一点。在这个例子中,我将向您展示我所指的含义。

假设我们正在创建一个Person类,当我们创建一个Person类时,我们提供他们的年龄,然后他们的出生年份会自动从中计算出来。

1
2
3
4
5
import datetime
class Person(object):
    def __init__(self, age):
        self.age = age
        self.birth_year = (datetime.date.today() - datetime.timedelta(days=age*365)).year

使用中:

1
2
3
4
5
>>>joe = Person(23)
>>>joe.age
23
>>>joe.birth_year
1990

如果没有__init__,这是不可能的,因为我们无法通过初始化age参数,否则。


是的,如其他各种问题所述,在类体中定义的变量是类的属性,而在def __init__(self)块中定义的变量是类实例的属性。

在in it中定义成员与在python中的类体中定义成员之间的区别?


让我们考虑以下类定义:

1
2
3
4
5
class Main:
        x = 1

        def __init__(self):
            self.y = 5

在这种情况下,我们可以直接引用x,如:Main.x,即它是一个类属性,它属于这个类的每个对象。

1
2
>>>Main.x
1

但是,属性y是特定于每个对象的。我们不能这样直接引用它:

1
2
3
4
>>> Main.y
Traceback (most recent call last):
  File"<stdin>", line 1, in <module>
AttributeError: class Main has no attribute 'y'

您需要实例化一个类main的对象来引用y:

1
2
3
>>> obj = Main()
>>> obj.y
5

这类似于C++和Java中的EDCOX1和18变量。


这是不同的。在第一个示例中,您有没有初始化的x

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
>>> class main():
...     def __init__(self):
...             self.x =1
...
>>> test2 = main()
>>> dir(test2)
['__doc__', '__init__', '__module__', 'x']
>>> class main1():
...     x =1
...     def disp(self):
...             print self.x
...
>>> dir(main1)
['__doc__', '__module__', 'disp', 'x']
>>> dir(main)
['__doc__', '__init__', '__module__']
>>>