922

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

在这样的方法中:

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

做什么self?它是什么意思?它是强制性的吗?

__init__方法有什么作用?为什么有必要?(ETC。)

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

4

18 回答 18

670

在这段代码中:

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'))也将作为参数传递——在这种情况下会引发异常,因为构造函数并不期望它们。

于 2009-03-09T05:18:46.950 回答
287

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

__init__是类的构造函数。self参数指的是对象的实例(如在thisC++ 中)。

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对象的生命周期内可访问)。

注意在此答案中对“构造函数”一词的使用进行了一些澄清。从技术上讲,“构造函数”的职责在 Python 中分为两种方法。这些方法是__new__(负责分配内存)和__init__(如这里所讨论的,负责初始化新创建的实例)。

于 2009-03-09T05:18:21.693 回答
264

一个简短的说明性示例

希望它可能会有所帮助,这里有一个简单的例子,我用来理解在类中声明的变量和在__init__函数中声明的变量之间的区别:

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

输出:

345
123
于 2013-06-23T12:15:34.777 回答
50

简而言之:

  1. self正如它所暗示的,指的是它自己——调用该方法的对象。也就是说,如果您有 N 个对象调用该方法,那么self.a将为 N 个对象中的每一个引用一个单独的变量实例。a想象一下每个对象的变量的 N 个副本
  2. __init__在其他 OOP 语言(如 C++/Java)中称为构造函数。基本思想是它是一个特殊的方法,在创建该类的对象时自动调用
于 2009-03-09T05:41:21.327 回答
37

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

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

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

    def f(self):
        return 'hello world'

thenMyClass.iMyClass.f是有效的属性引用,分别返回一个整数和一个函数对象。类属性也可以赋值,所以可以MyClass.i通过赋值来改变值。__doc__也是一个有效属性,返回属于该类的文档字符串:“A simple example class”。

类实例化使用函数表示法。假设类对象是一个返回类的新实例的无参数函数。例如:

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 :)
于 2018-05-01T08:17:20.117 回答
35

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

于 2009-03-09T05:18:20.947 回答
28

试试这个代码。希望它能帮助很多像我这样的 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

于 2013-05-10T03:03:13.847 回答
25

我自己很难理解这一点。即使在阅读了这里的答案之后。

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

自我参数

__init__方法接受的参数是:

def __init__(self, arg1, arg2):

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

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

额外的论点从何而来?

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

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

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

这意味着在__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

于 2014-01-09T22:39:09.330 回答
20

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

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

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

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

于 2009-03-09T12:50:30.907 回答
19

自我做什么?它是什么意思?是强制性的吗?

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

Python不会强迫你使用self ”。你可以给它任何你想要的名字。但请记住,方法定义中的第一个参数是对对象的引用。Python为您将self参数添加到列表中;调用方法时不需要包含它。如果你没有在 init 方法中提供 self 那么你会得到一个错误

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

init方法有什么作用?为什么有必要?(ETC。)

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

于 2017-10-21T10:01:19.347 回答
17
  1. __init__基本上是一个函数,一旦创建并匹配到相应的类,它将“初始化” / “激活”特定对象的类属性。
  2. self表示将继承这些属性的对象。
于 2015-09-03T22:19:24.633 回答
16

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

于 2012-09-23T12:02:55.517 回答
15

只是这个问题的演示。

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
于 2018-04-19T02:50:44.783 回答
14

'self' 是对类实例的引用

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"
于 2009-03-09T06:09:20.840 回答
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
于 2015-08-25T22:02:29.363 回答
10
# 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()
于 2016-07-02T04:15:17.837 回答
6

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

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

self? 那么所有 Customer 方法的 self 参数是什么?它是什么?为什么,当然是实例!换句话说,像withdraw 这样的方法定义了从某个抽象客户的帐户中提取资金的指令。调用 jeff.withdraw(100.0) 会将这些指令用于 jeff 实例。

所以当我们说 defwithdraw(self, amount): 时,我们是在说,“这就是你如何从一个 Customer 对象(我们称之为 self)和一个美元数字(我们称之为 amount)中提取资金。self是正在调用退出的客户的实例。这也不是我在做类比。jeff.withdraw(100.0) 只是 Customer.withdraw(jeff, 100.0) 的简写,这是完全有效的(如果不经常看到的话)代码。

init self 可能对其他方法有意义,但是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 相同。在这两行之后,我们认为 Customer 对象“已初始化”并可以使用。

小心你的__init__

init完成后,调用者可以正确地假设该对象已准备好使用。即在 jeff = Customer('Jeff Knupp', 1000.0) 之后,我们可以开始对 jeff 进行存款和取款调用;jeff 是一个完全初始化的对象。

于 2015-08-13T12:22:15.480 回答
5

Python__init__self它们是做什么的?

做什么self?它是什么意思?它是强制性的吗?

__init__方法有什么作用?为什么有必要?(ETC。)

给出的示例不正确,所以让我根据它创建一个正确的示例:

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 程序员涂上焦油和羽化。

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

于 2017-10-25T20:21:54.373 回答