【发布时间】:2010-10-12 02:58:51
【问题描述】:
我正在学习 Python 编程语言,但遇到了一些我不完全理解的东西。
在这样的方法中:
def method(self, blah):
def __init__(?):
....
....
self 是做什么的?它是什么意思?是强制性的吗?
__init__ 方法有什么作用?为什么有必要? (等等)
我认为它们可能是 OOP 构造,但我不太了解。
【问题讨论】:
我正在学习 Python 编程语言,但遇到了一些我不完全理解的东西。
在这样的方法中:
def method(self, blah):
def __init__(?):
....
....
self 是做什么的?它是什么意思?是强制性的吗?
__init__ 方法有什么作用?为什么有必要? (等等)
我认为它们可能是 OOP 构造,但我不太了解。
【问题讨论】:
是的,你是对的,这些是 oop 结构。
__init__ 是类的构造函数。 self 参数指的是对象的实例(如 C++ 中的 this)。
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
您的x 和y 参数将存储在堆栈上的变量中,并在init 方法超出范围时被丢弃。将这些变量设置为 self._x 和 self._y 会将这些变量设置为 Point 对象的成员(在对象的生命周期内可访问)。
注意在此答案中对“构造函数”一词的使用进行了一些澄清。从技术上讲,“构造函数”的职责在 Python 中分为两种方法。这些方法是__new__(负责分配内存)和__init__(这里讨论过,负责初始化新创建的实例)。
【讨论】:
self 出现在构造函数中?为什么还要指定,如果是隐式的不是更好吗?
__init__ 不分配内存空间。预计会初始化实例属性。在内存中分配的是__new__。
希望对您有所帮助,这里有一个简单的例子,我用来理解在类中声明的变量和在__init__ 函数中声明的变量之间的区别:
class MyClass(object):
i = 123
def __init__(self):
self.i = 345
a = MyClass()
print(a.i)
print(MyClass.i)
输出:
345
123
【讨论】:
__init__ 设置的变量是传递给类的 instances 的内容,而不是具有相同名称的类本身的“静态”变量...
自我是做什么的?它意味着是什么?是否强制?
每个类方法(包括 init)的第一个参数始终是对当前类实例的引用。按照惯例,这个参数总是命名为self。在init方法中,self指的是新创建的对象;在其他类方法中,它指的是被调用方法的实例。
Python 不会强迫您使用“self”。你可以给它任何你想要的名字。但请记住方法定义中的第一个参数是对对象的引用。 Python 为您将self 参数添加到列表中;调用方法时不需要包含它。
如果你没有在 init 方法中提供 self 那么你会得到一个错误
TypeError: __init___() takes no arguments (1 given)
init 方法有什么作用?为什么有必要? (等等)
init 是初始化的缩写。它是一个构造函数,当你创建一个类的实例并且没有必要时会调用它。但通常我们的习惯是编写初始化方法来设置对象的默认状态。如果您最初不愿意设置对象的任何状态,则不需要编写此方法。
【讨论】:
属性引用使用用于 Python 中所有属性引用的标准语法:obj.name。有效的属性名称是创建类对象时类名称空间中的所有名称。因此,如果类定义如下所示:
class MyClass:
"""A simple example class"""
i = 12345
def f(self):
return 'hello world'
那么MyClass.i 和MyClass.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
取自官方documentation,最后对我帮助最大。
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 :)
【讨论】:
只是一个问题的演示。
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
【讨论】:
在这段代码中:
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
【讨论】:
Python
__init__和self它们是做什么的?
self是做什么的?它是什么意思?是强制性的吗?
__init__方法有什么作用?为什么有必要? (等等)
给出的例子不正确,所以让我根据它创建一个正确的例子:
class SomeObject(object):
def __init__(self, blah):
self.blah = blah
def method(self):
return self.blah
当我们创建对象的实例时,会调用__init__ 来在对象创建后对其进行自定义。也就是说,当我们用下面的'blah'(可以是任何东西)调用SomeObject 时,它会作为参数传递给__init__ 函数,blah:
an_object = SomeObject('blah')
self 参数是将分配给an_object 的SomeObject 的实例。
稍后,我们可能想在这个对象上调用一个方法:
an_object.method()
进行点分查找,即an_object.method,将实例绑定到函数的实例,并且该方法(如上所述)现在是“绑定”方法 - 这意味着我们不需要显式传递方法调用的实例。
方法调用获取实例,因为它被绑定在虚线查找上,并且在被调用时,然后执行它被编程执行的任何代码。
按照约定,隐式传递的self 参数称为self。我们可以使用任何其他合法的 Python 名称,但如果您将其更改为其他名称,您可能会被其他 Python 程序员涂上焦油和羽化。
__init__ 是一个特殊的方法,documented in the Python datamodel documentation。它在实例创建后立即调用(通常通过__new__ - 尽管__new__ 不是必需的,除非您将子类化为不可变数据类型)。
【讨论】:
简而言之:
self 正如它所暗示的那样,指的是自身——调用该方法的对象。也就是说,如果您有 N 个对象调用该方法,那么 self.a 将为 N 个对象中的每一个引用一个单独的变量实例。想象一下每个对象有 N 个变量 a 的副本__init__ 在其他 OOP 语言(如 C++/Java)中称为构造函数。基本思想是它是一个特殊方法,当该类的对象被创建时会自动调用【讨论】:
# 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()
【讨论】:
试试这个代码。希望对很多像我一样的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
【讨论】:
这里,这家伙写得很好很简单:https://www.jeffknupp.com/blog/2014/06/18/improve-your-python-python-classes-and-object-oriented-programming/
阅读以上链接作为参考:
self?那么对于所有客户来说,这个 self 参数是什么? 方法?它是什么?为什么,当然是实例!再放一个 方式,像withdraw这样的方法定义了撤回的指令 来自某个抽象客户帐户的钱。打电话 jeff.withdraw(100.0) 将这些指令放在 jeff 上使用 实例。所以当我们说 defwithdraw(self, amount): 时,我们是在说,“这就是如何 您从 Customer 对象(我们称之为 self)中提取资金,并且 一个美元数字(我们称之为金额)。自我是的实例 正在调用退出的客户。那不是我做的 类比,要么。 jeff.withdraw(100.0) 只是简写 Customer.withdraw(jeff, 100.0),这是完全有效的(如果不是经常 见)代码。
init self 可能对其他方法有意义,但是 init 呢?当我们调用init时,我们正在创建一个对象,那么怎么可能已经有了一个self呢? Python允许我们扩展 构造对象时的自我模式,即使 它不完全适合。想象一下 jeff = Customer('Jeff Knupp', 1000.0) 等同于调用 jeff = Customer(jeff, 'Jeff 克努普', 1000.0);传入的 jeff 也是结果。
这就是为什么当我们调用 init 时,我们通过说来初始化对象 self.name = name 之类的东西。请记住,因为 self 是实例, 这相当于说 jeff.name = name,与 jeff.name = '杰夫克努普。同样,self.balance = balance 是一样的 作为 jeff.balance = 1000.0。在这两行之后,我们考虑 客户对象已“初始化”并可供使用。
小心你
__init__init 完成后,调用者可以正确地假设 对象已准备好使用。也就是说,在 jeff = Customer('Jeff Knupp', 1000.0),我们可以开始对 jeff 进行存款和取款; jeff 是一个完全初始化的对象。
【讨论】:
__init__ 基本上是一个函数,一旦创建并匹配到对应的类..self 表示将继承这些属性的对象。【讨论】:
基本上,在同一类的多个函数中使用变量时,您需要使用“self”关键字。至于 init,它用于设置默认值,以防该类中没有其他函数被调用。
【讨论】:
我自己无法理解这一点。即使在阅读了这里的答案之后。
要正确理解 __init__ 方法,您需要了解 self.
self参数
__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
【讨论】:
__init__ 确实像构造函数。如果您希望它们表现为非静态方法,则需要将“self”作为第一个参数传递给任何类函数。 “self”是您的类的实例变量。
【讨论】:
请注意,self 实际上可以是任何有效的 Python 标识符。例如,我们可以从 Chris B 的示例中轻松编写:
class A(object):
def __init__(foo):
foo.x = 'Hello'
def method_a(bar, foo):
print bar.x + ' ' + foo
它的工作原理完全相同。但是建议使用 self ,因为其他 python 用户会更容易识别它。
【讨论】:
'self' 是对类实例的引用
class foo:
def bar(self):
print "hi"
现在我们可以创建一个 foo 的实例并调用它的方法,在这种情况下,self 参数是由 Python 添加的:
f = foo()
f.bar()
但如果方法调用不在类实例的上下文中,也可以传入,下面的代码做同样的事情
f = foo()
foo.bar(f)
有趣的是,变量名“self”只是一个约定。下面的定义将完全一样。虽然说它是非常严格的约定,应该始终遵循,但它确实说明了语言的灵活性
class foo:
def bar(s):
print "hi"
【讨论】:
s)这一事实显示了python的灵活性。
在这段代码中:
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'))也将作为参数传递——在这种情况下会引发异常,因为构造函数不期望它们。
【讨论】:
x = 'Hello' 放在 init 之外但放在类中会怎样?是像java一样,还是变成了一个只初始化一次的静态变量?
A.x 或a.x 获得。请注意,在特定类上覆盖它不会影响基类,因此 A.x = 'foo'; a.x = 'bar'; print a.x; print A.x 将打印 bar 然后 foo
self,它只是按照惯例。
object的意义何在?我注意到有些课程有这个,有些没有
object 继承,因为它是默认发生的。