Python的__init__和self是做什么的?


790

我正在学习Python编程语言,遇到了一些我不太了解的东西。

用类似的方法:

def method(self, blah):
    def __init__(?):
        ....
    ....

怎么self办?这是什么意思?它是强制性的吗?

__init__方法做什么?为什么有必要?(等等。)

我认为它们可能是OOP构造,但我不太了解。

Answers:


583

在此代码中:

class A(object):
    def __init__(self):
        self.x = 'Hello'

    def method_a(self, foo):
        print self.x + ' ' + foo

... self变量表示对象本身的实例。大多数面向对象的语言将此作为隐藏参数传递给在对象上定义的方法。Python没有。您必须明确声明它。创建A类的实例并调用其方法时,它将自动传递,如...

a = A()               # We do not pass any argument to the __init__ method
a.method_a('Sailor!') # We only pass a single argument

__init__方法大致代表了Python中的构造函数。调用时,A()Python为您创建一个对象,并将其作为第一个参数传递给__init__方法。任何其他参数(例如A(24, 'Hello'))也将作为参数传递-在这种情况下,会引发异常,因为构造函数不期望它们。


8
如果您将init放在课堂x = 'Hello'之外但在课堂上怎么办?是像Java一样,还是变成只初始化一次的静态变量?
Jayen'4

15
这就像一个静态变量。它仅初始化一次,可以通过A.x或来使用a.x。请注意,在特定类上覆盖它不会影响基础,因此A.x = 'foo'; a.x = 'bar'; print a.x; print A.xbar随后打印foo
Chris B.

155
值得指出的是,不一定必须调用第一个参数self,而只是按照惯例。
亨利·戈默索尔

13
什么是点object在类声明?我注意到有些班级有这个课程,有些则没有
克里斯(Chris)

9
@Chris用于Python 2兼容性。在Python 3中,无需显式继承,object因为它默认发生。
加百利

241

是的,您是对的,这些是oop结构。

__init__是一个类的构造函数。该self参数是指对象的实例(如this在C ++中)。

class Point:
    def __init__(self, x, y):
        self._x = x
        self._y = y

__init__分配对象的内存时将调用该方法:

x = Point(1,2)

self如果要将值与对象保持在一起,则在对象的方法内使用参数很重要。例如,如果您实现如下__init__方法:

class Point:
    def __init__(self, x, y):
        _x = x
        _y = y

您的xy参数将存储在堆栈中的变量中,并且当init方法超出范围时将被丢弃。将这些变量设置为self._x并将self._y这些变量设置为Point对象的成员(在对象的生存期内可访问)。


1
那么,有什么理由为什么您不想self成为构造函数?为什么还要指定它,如果它是隐式的,岂不是更好吗?
亚伦·弗兰克

据我所知,__ init __不是构造函数,它是在创建任何对象时将执行的第一个方法,__ init __用于设置对象。__ new __是python中的构造函数。
Deepanshu

206

简短的说明性示例

希望对您有所帮助,这是我用来理解在类内部声明的变量与在__init__函数内部声明的变量之间的区别的一个简单示例:

class MyClass(object):
    i = 123
    def __init__(self):
        self.i = 345

a = MyClass()
print(a.i)
print(MyClass.i)

输出:

345
123

7
有趣的观察,但我认为您走错了路。通过打印MyClass.i,看起来更像是您在调用“静态”变量。与使用ai一样,您在调用成员变量。在我看来,init只是一个创建类对象时首先执行的构造函数。
captainspi 2013年

34
这就是我在本例中试图“向自己解释”的原因-设置的变量__init__是传递给类实例的内容,而不是具有相同名称的类本身的“静态”变量...
Dave Everitt

44

简而言之:

  1. self正如它暗示的那样,它指向自身 -调用该方法的对象。也就是说,如果您有N个对象调用该方法,则将self.a为N个对象中的每一个引用变量的单独实例。想象a每个对象的N个变量副本
  2. __init__在其他OOP语言(例如C ++ / Java)中称为构造函数。基本思想是它是一种特殊的方法,当创建该Class的对象时会自动调用该方法

29

__init__确实像构造函数。如果希望它们充当非静态方法,则需要将“ self”作为第一个参数传递给任何类函数。“ self”是您的类的实例变量。


1
'self'定义一个方法是否是静态的!哇,这对于这个Java家伙来说是大开眼界。
liwevire

25

试用此代码。希望它能帮助像我这样的许多C程序员学习Py。

#! /usr/bin/python2

class Person:

    '''Doc - Inside Class '''

    def __init__(self, name):
        '''Doc - __init__ Constructor'''
        self.n_name = name        

    def show(self, n1, n2):
        '''Doc - Inside Show'''
        print self.n_name
        print 'Sum = ', (n1 + n2)

    def __del__(self):
        print 'Destructor Deleting object - ', self.n_name

p=Person('Jay')
p.show(2, 3)
print p.__doc__
print p.__init__.__doc__
print p.show.__doc__

输出:

Jay

Sum = 5

Doc - Inside Class

Doc - __init__ Constructor

Doc - Inside Show

Destructor Deleting object - Jay


我不知道是否只有我一个人,但是阅读这段代码有点令人困惑。也许是因为我还是iDk的Python新手。
琳妮

我不太清楚doc的内容。它会拉文档吗?如果我这样做:'''test-my doc''',我可以使用:print.p .__ test__吗?还是doc是特定关键字?
托马斯

@Thomas doc是记录的详细信息的关键字。三引号用于记录文档,文档是可选的实体。
Jayzcode

24

类对象支持两种操作:属性引用和实例化

属性引用使用Python中所有属性引用使用的标准语法:obj.name。有效属性名称是创建类对象时在类名称空间中的所有名称。因此,如果类定义如下所示:

class MyClass:
    """A simple example class"""
    i = 12345

    def f(self):
        return 'hello world'

then MyClass.iMyClass.f是有效的属性引用,分别返回整数和函数对象。类属性也可以分配给它,因此您可以MyClass.i通过赋值来更改其值。__doc__也是有效的属性,返回属于该类的文档字符串:“简单示例类”。

类实例化使用函数表示法。只是假装类对象是一个无参数函数,它将返回该类的新实例。例如:

x = MyClass()

所述实例化操作(“呼叫”一类对象)来创建一个空对象。许多类喜欢创建具有定制为特定初始状态的实例的对象。因此,一个类可以定义一个名为的特殊方法__init__(),如下所示:

def __init__(self):
    self.data = []

当类定义__init__()方法时,类实例化将自动__init__()为新创建的类实例调用。因此,在此示例中,可以通过以下方式获取新的初始化实例:

x = MyClass()

当然,该__init__()方法可能具有更大的灵活性。在这种情况下,提供给类实例化运算符的参数将传递给__init__()。例如,

class Complex:
    def __init__(self, realpart, imagpart):
        self.r = realpart
        self.i = imagpart

x = Complex(3.0, -4.5)
x.r, x.i

摘自最终对我最大的帮助的官方文档


这是我的例子

class Bill():
    def __init__(self,apples,figs,dates):
        self.apples = apples
        self.figs = figs
        self.dates = dates
        self.bill = apples + figs + dates
        print ("Buy",self.apples,"apples", self.figs,"figs 
                and",self.dates,"dates. 
                Total fruitty bill is",self.bill," pieces of fruit :)")

创建Bill类的实例时:

purchase = Bill(5,6,7)

你得到:

> Buy 5 apples 6 figs and 7 dates. Total fruitty bill is 18  pieces of
> fruit :)

22

自己弄不清楚这个问题。即使在这里阅读答案。

要正确理解__init__方法,您需要了解自己。

自我参数

__init__方法接受的参数为:

def __init__(self, arg1, arg2):

但是我们实际上只传递了两个参数:

instance = OurClass('arg1', 'arg2')

多余的争论从何而来?

当我们访问对象的属性时,我们按名称(或按引用)进行操作。这里的实例是对我们新对象的引用。我们使用instance.printargs访问实例对象的printargs方法。

为了从__init__方法内部访问对象属性,我们需要对对象的引用。

每当调用方法时,对主对象的引用都会作为第一个参数传递。按照惯例,您总是将第一个参数称为方法自身。

这意味着__init__我们可以执行以下方法:

self.arg1 = arg1
self.arg2 = arg2

在这里,我们在对象上设置属性。您可以通过执行以下操作来验证这一点:

instance = OurClass('arg1', 'arg2')
print instance.arg1
arg1

这样的值称为对象属性。在这里,该__init__方法设置实例的arg1和arg2属性。

来源:http : //www.voidspace.org.uk/python/articles/OOP.shtml#the-init-method


17

请注意,self实际上它可以是任何有效的python标识符。例如,我们可以从Chris B的示例中轻松编写:

class A(object):
    def __init__(foo):
        foo.x = 'Hello'

    def method_a(bar, foo):
        print bar.x + ' ' + foo

它的工作原理完全一样。但是,建议使用self,因为其他pythoner会更容易识别它。


我同意建议使用self代替foo,以帮助其他程序员查看代码
Linny

15

基本上,在同一类的多个函数中使用变量时,需要使用'self'关键字。至于init,它用于设置默认值,以防该类中没有其他函数被调用。


6
Python中没有'self'关键字。调用第一个参数“ self”只是一个约定。
大卫·安德森

self基本上用作占位符。不需要使用self,可以使用“ eeee”或“ foo”之类的东西,建议其他程序员在阅读代码时使用
Linny

15
  1. __init__本质上是一个函数,一旦创建并与相应的类匹配,该函数将“初始化” / “激活”特定对象的类的属性。
  2. self 表示将继承这些属性的对象。

1
不必使用“自我”关键字,它只是一个占位符。您可以使用任何单词,但是建议您使用self来提高程序的可读性
Linny

13

“自我”是对类实例的引用

class foo:
    def bar(self):
            print "hi"

现在我们可以创建foo的实例并对其调用方法,在这种情况下,Python将添加self参数:

f = foo()
f.bar()

但是,如果方法调用不在类实例的上下文中,则也可以传递它,下面的代码执行相同的操作

f = foo()
foo.bar(f)

有趣的是,变量名“ self”只是一个约定。下面的定义将完全相同。.尽管说过,这是非常严格的约定,应该始终遵循,但是它确实说明了语言的灵活性。

class foo:
    def bar(s):
            print "hi"

为什么这么说关于语言的灵活性?它只是说您可以给变量提供您选择的任何合法名称。这与任何其他编程语言有何不同?
丹尼尔(Daniel)

如我在答案中所写,“ bar”只是一个函数,其中将类实例作为第一个参数。因此,尽管将“ bar”定义为绑定到“ foo”的方法,但也可以使用其他类的实例来调用它。例如,这不是方法和“ this”在Java中的工作方式,尽管我想您会看到它们是相同的概念,函数和某些实例上下文(实例上下文是Python中的第一个参数,而Java中是“ this”) 。也许您现在可以看到我所指的语言的灵活性?
塔恩,2014年

是的,确实显示了语言的灵活性。用措辞表达答案的方式,似乎是在说可以将“ self”变量称为其他名称(例如s),这一事实表明了python的灵活性。
丹尼尔(Daniel)

12

只是演示的问题。

class MyClass:

    def __init__(self):
        print('__init__ is the constructor for a class')

    def __del__(self):
        print('__del__ is the destructor for a class')

    def __enter__(self):
        print('__enter__ is for context manager')
        return self

    def __exit__(self, exc_type, exc_value, traceback):
        print('__exit__ is for context manager')

    def greeting(self):
        print('hello python')


if __name__ == '__main__':
    with MyClass() as mycls:
        mycls.greeting()

$ python3 class.objects_instantiation.py
__init__ is the constructor for a class
__enter__ is for context manager
hello python
__exit__ is for context manager
__del__ is the destructor for a class

11

在此代码中:

class Cat:
    def __init__(self, name):
        self.name = name
    def info(self):
        print 'I am a cat and I am called', self.name

在此__init__充当类的构造函数,并在实例化对象时调用此函数。self表示实例化对象。

c = Cat('Kitty')
c.info()

以上语句的结果如下:

I am a cat and I am called Kitty

11

什么是自我呢?这是什么意思?是强制性的吗?

每个类方法(包括init)的第一个参数始终是对该类当前实例的引用。按照惯例,该参数始终命名为self。在init方法中,self指的是新创建的对象;在其他类方法中,它引用其方法被调用的实例。

Python 不会强迫您使用self ”。您可以为其指定任何名称。但是请记住,方法定义中的第一个参数是对对象的引用。Python self为您将参数添加到列表中。调用方法时不需要包含它。如果您没有提供self in init方法,则会收到错误消息

TypeError: __init___() takes no arguments (1 given)

什么是初始化方法吗?为什么有必要?(等等。)

init是初始化的缩写。它是一个构造函数,当您创建类的实例时会调用该构造函数,而不必这样做。但是通常我们的做法是编写用于设置对象默认状态的init方法。如果您最初不愿设置对象的任何状态,则无需编写此方法。


8
# Source: Class and Instance Variables
# https://docs.python.org/2/tutorial/classes.html#class-and-instance-variables

class MyClass(object):
    # class variable
    my_CLS_var = 10

    # sets "init'ial" state to objects/instances, use self argument
    def __init__(self):
        # self usage => instance variable (per object)
        self.my_OBJ_var = 15

        # also possible, class name is used => init class variable
        MyClass.my_CLS_var = 20


def run_example_func():
    # PRINTS    10    (class variable)
    print MyClass.my_CLS_var

    # executes __init__ for obj1 instance
    # NOTE: __init__ changes class variable above
    obj1 = MyClass()

    # PRINTS    15    (instance variable)
    print obj1.my_OBJ_var

    # PRINTS    20    (class variable, changed value)
    print MyClass.my_CLS_var


run_example_func()

5

Python __init__及其作用self是什么?

怎么self办?这是什么意思?它是强制性的吗?

__init__方法做什么?为什么有必要?(等等。)

给出的示例不正确,因此让我基于它创建一个正确的示例:

class SomeObject(object):

    def __init__(self, blah):
        self.blah = blah

    def method(self):
        return self.blah 

当我们创建对象的实例时,将__init__在对象创建后调用,以自定义对象。也就是说,当我们SomeObject'blah'下面的方法(可能是任何东西)进行调用时,它将__init__作为参数传递给函数blah

an_object = SomeObject('blah')

self参数是实例SomeObject,将被分配到an_object

稍后,我们可能要在此对象上调用方法:

an_object.method()

进行点分查找,即将an_object.method实例绑定到该函数的实例,并且该方法(如上所述)现在是“绑定”方法-这意味着我们无需将实例显式传递给方法调用。

方法调用获取实例是因为它绑定在点分查找上,并在调用时执行其编程要执行的任何代码。

隐式传递的self参数self由约定调用。我们可以使用其他任何合法的Python名称,但是如果将其更改为其他名称,您可能会被其他Python程序员感到羞耻和ed愧。

__init__是一种特殊的方法,在Python数据模型文档中进行了介绍。在创建实例后立即调用它(通常通过__new__-,尽管__new__不是必需的,除非您将不可变的数据类型作为子类)。


3

在这里,这家伙写得非常好而且很简单:https : //www.jeffknupp.com/blog/2014/06/18/improve-your-python-python-classes-and-object-oriented-programming/

阅读以上链接作为对此的参考:

self?那么,所有客户方法的自我参数又如何呢?它是什么?当然,这就是实例!换句话说,诸如提款之类的方法定义了从某个抽象客户帐户中提款的指令。调用jeff.withdraw(100.0)会将这些指令用于jeff实例。

因此,当我们说def withdraw(self,amount):时,我们的意思是,“这是您如何从Customer对象(我们称为self)和一个美元图形(我们称为amount)提取钱的方法。是被调用提现的Customer的实例,也不是我做类比。jeff.withdraw(100.0)只是Customer.withdraw(jeff,100.0)的简写,这是完全有效的(如果不经常出现)码。

init自我可能对其他方法有意义,但是init呢?当我们调用init时,我们正在创建一个对象,那么如何已经存在一个self?Python允许我们将self模式扩展到构造对象的时间,即使它并不完全适合。试想一下jeff = Customer('Jeff Knupp',1000.0)与调用jeff = Customer(jeff,'Jeff Knupp',1000.0)相同;传入的jeff也成为结果。

这就是为什么当我们调用init时,我们通过说出self.name = name之类的东西来初始化对象。请记住,由于self是实例,所以这等效于说jeff.name = name,与jeff.name ='Jeff Knupp相同。同样,self.balance = balance与jeff.balance = 1000.0相同。在这两行之后,我们认为“客户”对象已“初始化”并可以使用。

小心你 __init__

经过初始化完成后,主叫方可以正确地假定对象就可以使用了。也就是说,在jeff = Customer('Jeff Knupp',1000.0)之后,我们可以开始对jeff进行入金和出金;jeff是一个完全初始化的对象。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.