1

可能重复:
类 __init__() 函数内部和外部的变量

我知道当一个类被调用时,它会先运行代码__init__。我仍然看不出这与直接在类下编写代码之间的区别。

例如:

class main():
  x = 1

  def disp(self):
    print self.x
class main():
  def __init__(self):
    self.x = 1

  def disp(self):
    print self.x

对我来说,两者都有相同的功能。(也许我错过了一些东西。)我想知道哪个更(咳咳)pythonic以及为什么。

4

5 回答 5

2

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

在 init 中定义成员与在 Python 中的类主体中定义成员之间的区别?

于 2012-12-26T08:28:40.787 回答
2

这里有几个关键的区别,无论__init__是在课堂上还是在课堂上写,以及你写的东西。

x = 1

首先,你是对的——这两条代码有效地为你的目的做同样的事情(特别是因为我们在int这里使用对象,这对于可变对象会有所不同):

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

class main(object):
    x = 1

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

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

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

然而,正如另一张海报指出的那样,两者之间的区别在于,当x=1它在函数之外时__init__,即使没有初始化,它也是类本身的一部分——有关更多详细信息,请参见Zagorulkin Dmitry的回答。但是,在大多数情况下,这种区别与您无关。

其他注意事项

__init__除了设置变量之外,还有更多用途。最重要的一项是在初始化期间接受参数的能力。 据我所知,没有__init__函数就没有办法做到这一点。我会在这个例子中告诉你我的意思。

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

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

正在使用:

>>>joe = Person(23)
>>>joe.age
23
>>>joe.birth_year
1990

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

于 2012-12-26T08:29:49.347 回答
2

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

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

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
于 2012-12-26T09:25:32.267 回答
0

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

>>> 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__']
>>>
于 2012-12-26T08:22:16.860 回答
0

让我们考虑以下类定义:

class Main:
        x = 1

        def __init__(self):
            self.y = 5

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

>>>Main.x
1

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

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

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

>>> obj = Main()
>>> obj.y
5

这类似于staticC++ 和 Java 中的变量。

于 2012-12-26T08:32:40.030 回答