Python中的类是否需要构造函数__init__?

时间:2016-07-09 09:52:08

标签: python class oop constructor initialization

我读到构造函数就像传递给类的第一个参数一样,这对我来说很有意义,因为参数似乎是通过__init__方法传递给类的。例如,

class NewsStory(object):
    def __init__(self, guid, title, subject, summary, link):
        self.guid = guid
        self.title = title
        self.subject = subject
        self.summary = summary
        self.link = link

    def get_guid(self):
        return self.guid

    def get_title(self):
        return self.title

    def get_subject(self):
        return self.subject

    def get_summary(self):
        return self.summary

    def get_link(self):
        return self.link
firstStory = NewsStory('Globally Unique Identifier', \
    'first_title','first_subject','This is an example \
    sumary','example_link@something.com')

print firstStory.get_guid() # prints Globally Unique Identifier

所以,当我打电话给'该类,我从__init__方法传递参数?我是新上课的,我读到的一切都让我难以理解和困惑。谢谢!

编辑1

我发现这个问题有助于解释一些事情,例如 init 之间的区别,抱歉,我不知道如何添加链接,必须剪切和粘贴:What can `__init__` do that `__new__` cannot?

6 个答案:

答案 0 :(得分:4)

不,构造函数只是被调用来构造对象的方法。它没有通过任何地方。而是将self对象自动传递给类的所有方法。

如果您没有构建任何内容,则不需要构造函数,但通常您在开始时可以执行某些操作。

答案 1 :(得分:3)

我在构造函数之间看到了一个误解 - 构造对象和初始化对象:

Python's use of __new__ and __init__?

  

当您需要控制新实例的创建时,请使用__new__。需要控制新实例的初始化时,请使用__init__

所以我们一定要小心。

  

我读到构造函数就像传递给类的第一个参数一样,这对我来说很有意义,因为参数似乎是通过__init__方法传递给类的。

构造函数未传递给类,确切地说,构造函数(__new__)的结果将是类或其子类中每个实例方法的第一个参数(注意:{{1 }仅适用于新式类):

__new__

看看你打电话给班级时会发生什么(创建对象):

class A:
    def __new__(self):
            return 'xyz'

调用该类不再返回类型>>> A() 'xyz' >>> type(A()) <class 'str'> 的实例,因为我们更改了构造函数A的机制。实际上这样做会改变你班级的全部意义,不仅如此,这也很难破译。在特定对象的创建时间内,您不太可能切换对象类型。我希望这句话有意义,如果没有,你的代码将如何理解!

__new__

看看当我们尝试调用class A: def __new__(self): return 'xyz' def type_check(self): print(type(self)) 方法时会发生什么:

type_check

>>> a = A() >>> a 'xyz' >>> a.type_check() AttributeError: 'str' object has no attribute 'type_check' 不是类a的对象,因此基本上您无法再访问类A

A用于初始化对象的状态。 __init__通过在创建时初始化对象的成员来解决此问题,而不是调用将初始化对象成员的方法,因此如果您有一个名为__init__的成员在一个类中,你想在创建类时初始化name而不是调用额外的方法name,你肯定会使用init_name('name')来实现这个目的。

  

所以当我'打电话'这个班级时,我会从__init__方法中传递参数?

当您调用该类时,您传递参数(至)__init__方法?

无论你传递什么参数,所有的参数都将传递给__init__,并为你自动添加一个额外的参数,这个参数通常称为__init__(实例本身)。通过Python自动传递为最左边的参数

self
class A:
    def __init__(self, a, b):
        self.a = a
        self.b = b 

注意: A( 34, 35) self.a = 34 | | | | | | self.b = 35 init(self, a, b) | | | The instance that you created by calling the class A() 适用于classic classes and new style classes。然而,__init__仅适用于新式类。

答案 2 :(得分:1)

Python类与其他语言的类有点不同。 例如,python中没有私有属性。只是命名约定以暗示方法或成员变量不是供公众使用的(领先的_)。

虽然每个类都必须具有属性__new____init__,它们共同构建了其他语言可能称为构造函数的属性,但基本python类实现了thos方法。如果您不需要,则不必覆盖它们。

这很好:

class A:
   def hello(self):
        print('Hello, World')

a = A()
a.hello()

在python中__new__(cls, ...)首先用于创建所请求的cls的类实例。然后,新创建的实例将__init__(self, ...)传递给self

__new____init__方法都接收传递给构造表达式的参数。这就是python调用m = MyClas(1, 2, 3)的方式。

class A:
    def __new__(cls, *args, **kwargs):
        print('In __new__')
        print(args)
        print(kwargs)
        return object.__new__(cls) # create a new object of type cls

    def __init__(self, *args, **kwargs):
        print('In __init__')
        print(args)
        print(kwargs)


a = A(1, 2, c=3)

结果:

In __new__
(1, 2)
{'c': 3}
In __init__
(1, 2)
{'c': 3}

答案 3 :(得分:0)

没有必要,因为对象构造函数在调用类时定义了默认值,但开发人员通常建议使用 init 函数作为约定。 init 返回&#34;无&#34;正常函数必须返回一个值。

答案 4 :(得分:0)

理解Python类构造函数并不太难,但确实有点棘手,特别是如果我们已经从支持OOP的其他语言(如C ++或Java)中听到一些面向对象的编程术语。

类构造函数的主要目的是创建具有针对特定初始状态定制的实例的对象。在Python中理解这一点非常重要,因为不需要声明数据属性(成员变量),并且它们在首次分配时就会存在。因此,对实例的所有数据属性进行分组的好地方是构造函数。

在类的所有实例之外共享在类的所有函数之外分配的任何数据属性。在这里,Python变得更加棘手,因为它具有可变数据类型和不可变数据类型。

例如,请参阅以下代码段:


    class MyClass:
        i = 3
        arr = []

    x = MyClass()
    x.i = 4
    x.arr.append('x')

    y = MyClass()
    y.i = 5
    y.arr.append('y')

    MyClass.arr.append('m')

    print "{}, {}, {}".format(x.i, y.i, MyClass.i)
    print "{}, {}, {}".format(x.arr, y.arr, MyClass.arr)

,输出结果为:


    4, 5, 3
    ['x', 'y', 'm'], ['x', 'y', 'm'], ['x', 'y', 'm']

由于整数在Python中是不可变的数据类型,因此每个赋值都会创建整数对象的新副本,这可能会误导某些程序员,因为看起来每个实例都有自己的成员变量的私有副本。列表数据类型是可变的,因此上面的代码片段修改了所有实例的列表的相同副本。

因此,如果所有成员都由该类的所有实例共享,则不需要为Python类编写构造函数,否则编写构造函数并将其中的所有私有数据成员分组是一个好习惯。

在上面的代码片段中,如果程序员真的想要一个私有数据成员,i对于类实例,那么应该编写构造函数并初始化变量,而不是依赖于不可变属性。

修改代码以使用构造函数:


    class MyClass:
        arr = []
        def __init__(self, i):
            self.i = i


    x = MyClass(4)
    y = MyClass(5)
    print "{}, {}".format(x.i, y.i)

输出将是:


    4, 5

希望在此线程上的其他人已经共享的有用知识上有所帮助。祝你好运。

答案 5 :(得分:-2)

你走在正确的轨道上。 __init__()的参数是实例化类的参数。这与其他语言中的构造函数类似,但是__new__()(您几乎不需要实际使用)是实际创建对象的内容。

如果我创建这个类:

class TestClass(object):
    def __init__(self, paramA, paramB):
        self.paramA = paramA
        self.paramB = paramB

我会像这样实例化这个类:

tc = TestClass(1, 2)

如果我打印:

print tc.paramA
print tc.paramB

我明白了:

1
2

但是,构造函数除了传递参数之外还有其他用途。它们运行在创建对象时需要运行的任何代码,例如:

class AnotherTestClass(object):
    def __init__(self):
        self.name = "testing"

atc = AnotherTestClass()
print atc.name

会显示:

testing

如果您不需要将任何参数传递给课程来创建它的对象,并且您不需要进行任何初始化或初始设置,则不需要{{ 1}}方法:

__init__()

输出:

class SimpleTestClass(object):
    def output(self, text):
        print text

stc = SimpleTestClass()
stc.output("hi!")

请注意,上面是Python 2.7语法,因为最初的问题是使用Python 2.x。