__init__ 为啥python类需要初始化
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了__init__ 为啥python类需要初始化相关的知识,希望对你有一定的参考价值。
参考技术A通常构造一个类,用 init 初始化:
为什么python类需要初始化
1.python 类初始化属性 def __init__() 中定义,实例化对象后可直接调用
2.python 类非初始化属性在 def func() 中定义,实例化对象后, 先调用调用函数,再调用属性
结果:
为啥 Python 在创建实例时不调用实例方法 __init__() 而是调用类提供的 __init__() ?
【中文标题】为啥 Python 在创建实例时不调用实例方法 __init__() 而是调用类提供的 __init__() ?【英文标题】:Why doesn't Python call instance method __init__() on instance creation but calls class-provided __init__() instead?为什么 Python 在创建实例时不调用实例方法 __init__() 而是调用类提供的 __init__() ? 【发布时间】:2012-07-23 01:03:22 【问题描述】:我正在覆盖类的 __new__()
方法以返回具有特定 __init__()
集的类实例。 Python 似乎调用了类提供的 __init__()
方法而不是特定于实例的方法,尽管 Python 文档位于
http://docs.python.org/reference/datamodel.html
说:
典型的实现通过调用 使用 super(currentclass, cls).__new__(cls[, ...]) 的超类的 __new__() 方法 使用适当的参数,然后将新创建的实例修改为 退货前需要。
如果 __new__() 返回一个 cls 的实例,那么新实例的 __init__() 方法 将像 __init__(self[, ...]) 一样被调用,其中 self 是新实例,而 其余参数与传递给 __new__() 的参数相同。
这是我的测试代码:
#!/usr/bin/env python
import new
def myinit(self, *args, **kwargs):
print "myinit called, args = %s, kwargs = %s" % (args, kwargs)
class myclass(object):
def __new__(cls, *args, **kwargs):
ret = object.__new__(cls)
ret.__init__ = new.instancemethod(myinit, ret, cls)
return ret
def __init__(self, *args, **kwargs):
print "myclass.__init__ called, self.__init__ is %s" % self.__init__
self.__init__(*args, **kwargs)
a = myclass()
哪个输出
$ python --version
Python 2.6.6
$ ./mytest.py
myclass.__init__ called, self.__init__ is <bound method myclass.myinit of <__main__.myclass object at 0x7fa72155c790>>
myinit called, args = (), kwargs =
似乎让myinit()
运行的唯一方法是在myclass.__init__()
内显式调用它为self.__init__()
。
【问题讨论】:
【参考方案1】:新式类的特殊方法是在实例的类型上查找的,而不是在实例本身上。这是documented behaviour:
对于新型类,特殊方法的隐式调用只有在对象类型上定义时才能保证正常工作,而不是在对象的实例字典中。这种行为是以下代码引发异常的原因(与旧式类的等效示例不同):
>>> class C(object):
... pass
...
>>> c = C()
>>> c.__len__ = lambda: 5
>>> len(c)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: object of type 'C' has no len()
【讨论】:
【参考方案2】:各种特殊方法(包括__init__
,还有__add__
等运算符重载)都是always accessed via the class rather than the instance。不仅如此,它们不能通过类或元类上的__getattr__
或__getattribute__
方法访问,它们必须直接在类上。这是为了提高效率:
以这种方式绕过
__getattribute__()
机制为解释器中的速度优化提供了很大的空间,但代价是处理特殊方法时具有一定的灵活性(特殊方法必须在类对象本身上设置才能被解释器始终调用)。
尚不完全清楚您要完成什么,但您可以在这里做的一件事是在 __new__
方法中子类化 myclass
:
class myclass(object):
def __new__(cls, *args, **kwargs):
class subcls(cls):
def __new__(cls, *args, **kwargs):
return object.__new__(cls)
subcls.__init__ = myinit
return subcls(*args, **kwargs)
【讨论】:
【参考方案3】:为什么 Python 在创建实例时不调用实例方法 init() 而是调用类提供的 init()?
看看这个例子。
class C:
one = 42
def __init__(self,val):
self.two=val
ci=C(50)
print(ci.__dict__)
print(C.__dict__)
结果会是这样的:
'two': 50
'__module__': '__main__', 'one': 42, '__init__': <function C.__init__ at 0x00000213069BF6A8>, '__dict__': <attribute '__dict__' of 'C' objects>, '__weakref__': <attribute '__weakref__' of 'C' objects>, '__doc__': None
请注意,只有值 'two': 50
是实例字典的一部分。
'one': 42
属于一个类 C
字典。 __init__
方法也是如此。
这是每个设计。
【讨论】:
以上是关于__init__ 为啥python类需要初始化的主要内容,如果未能解决你的问题,请参考以下文章
为啥我收到错误:__init__() 缺少 1 个必需的位置参数?
python unittest--TestCase类总结2,__init__初始化实例简介
python 新人 对 初始化函数 的概念没明白 为啥又要初始化函数? 可以解释的详细些吗
29.Python面向对象类:主要讲初始化方法__init__,垃圾回收,继承&多继承,方法重写,super()函数