相关疑难解决方法(0)

Python(和Python C API):__ new__与__init__

我要问的问题似乎是Python使用__new__和__init__的重复但是无论如何,我还不清楚到底是什么__new____init__它之间的实际区别.

在你急于告诉我__new__是用于创建对象并且__init__用于初始化对象之前,让我说清楚:我明白了. 事实上,这种区别对我来说是很自然的,因为我在C++中有经验,我们有新的贴图,它同样将对象分配与初始化分开.

Python的C API教程解释它是这样的:

新成员负责创建(而不是初始化)该类型的对象.它在Python中作为__new__()方法公开.... 实现新方法的一个原因是确保实例变量的初始值.

所以,是的 - 我得到了什么__new__,但尽管如此,我仍然不明白为什么它在Python中有用.给出的示例说,__new__如果要"确保实例变量的初始值" ,这可能很有用.那么,这究竟是什么意思__init__呢?

在C API教程中,显示​​了一个示例,其中创建了一个新类型(称为"Noddy"),并__new__定义了Type的函数.Noddy类型包含一个名为的字符串成员first,并且此字符串成员初始化为空字符串,如下所示:

static PyObject * Noddy_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
    .....

    self->first = PyString_FromString("");
    if (self->first == NULL)
    {
       Py_DECREF(self);
       return NULL;
    }

    .....
}
Run Code Online (Sandbox Code Playgroud)

请注意,如果没有__new__此处定义的方法,我们必须使用PyType_GenericNew,它只是将所有实例变量成员初始化为NULL.因此,该__new__方法的唯一好处是实例变量将以空字符串开头,而不是NULL. 但是为什么这个有用,因为如果我们关心确保我们的实例变量被初始化为某个默认值,我们可以在 …

c python python-c-api

118
推荐指数
5
解决办法
3万
查看次数

Python中的__new__和__init__

我正在学习Python和到目前为止,我可以告诉低于约的事情__new____init__:

  1. __new__ 用于创建对象
  2. __init__ 用于对象初始化
  3. __new__被调用之前__init____new__返回一个新的实例,并__init__随后调用初始化内部状态.
  4. __new__对于不可变对象是有益的,因为它们一旦被分配就无法更改.所以我们可以返回具有新状态的新实例.
  5. 我们可以使用__new____init__为两个可变对象,因为它的内部状态可以改变.

但我现在还有另外一个问题.

  1. 当我创建一个新实例时a = MyClass("hello","world"),如何传递这些参数?我的意思是我应该如何构造类__init__,__new__因为它们是不同的,并且除了默认的第一个参数之外都接受任意参数.
  2. self关键字在名称方面可以改为别的吗?但我想知道cls在名称方面可能会改变其他东西,因为它只是一个参数名称?

我做了一些实验,如下:

>>> class MyClass(tuple):
    def __new__(tuple):
        return [1,2,3]
Run Code Online (Sandbox Code Playgroud)

我在下面做了:

>>> a = MyClass()
>>> a
[1, 2, 3]
Run Code Online (Sandbox Code Playgroud)

虽然我说我想回来tuple,但这段代码运行正常并且还给了我[1,2,3].我知道在__new__调用函数后,我们将第一个参数作为我们想要接收的类型传递.我们说的是New功能对吗?我不知道除绑定类型以外的其他语言返回类型?

我也做了其他事情:

>>> issubclass(MyClass,list)
False
>>> issubclass(MyClass,tuple)
True
>>> isinstance(a,MyClass)
False
>>> isinstance(a,tuple)
False
>>> isinstance(a,list) …
Run Code Online (Sandbox Code Playgroud)

python class

51
推荐指数
1
解决办法
2万
查看次数

什么可以`__init__`做那个`__new__`不能?

在Python中,__new__用于初始化不可变类型,__init__通常初始化可变类型.如果__init__从语言中删除,那么就不能再轻松完成了什么?

例如,

class A:

    def __init__(self, *, x, **kwargs):
        super().__init__(**kwargs)
        self.x = x


class B(A):

    def __init__(self, y=2, **kwargs):
        super().__init__(**kwargs)
        self.y = y
Run Code Online (Sandbox Code Playgroud)

可以__new__像这样重写:

class A_N:

    def __new__(cls, *, x, **kwargs):
        obj = super().__new__(cls, **kwargs)
        obj.x = x
        return obj


class B_N(A_N):

    def __new__(cls, y=2, **kwargs):
        obj = super().__new__(cls, **kwargs)
        obj.y = y
        return obj
Run Code Online (Sandbox Code Playgroud)

澄清问题范围:这不是关于如何使用__init____new__使用它们或它们之间有什么区别的问题.这是一个关于如果__init__从语言中删除会发生什么的问题.什么事情会破裂?有什么事情会变得更难或不可能吗?

python initialization

29
推荐指数
2
解决办法
2294
查看次数

Python:总是使用__new__而不是__init__?

我了解都__init____new__工作.我想知道是否有什么__init__可以做到的__new__不可以?

即可以使用__init__以下模式替换:

class MySubclass(object):
    def __new__(cls, *args, **kwargs):
        self = super(MySubclass, cls).__new__(cls, *args, **kwargs)
        // Do __init__ stuff here
        return self
Run Code Online (Sandbox Code Playgroud)

我问,因为我想让Python OO的这个方面更适合我.

python new-style-class

27
推荐指数
2
解决办法
4540
查看次数

错误异常必须从BaseException派生,即使它确实如此(Python 2.7)

以下代码有什么问题(在Python 2.7.1下):

class TestFailed(BaseException):
    def __new__(self, m):
        self.message = m
    def __str__(self):
        return self.message

try:
    raise TestFailed('Oops')
except TestFailed as x:
    print x
Run Code Online (Sandbox Code Playgroud)

当我运行它时,我得到:

Traceback (most recent call last):
  File "x.py", line 9, in <module>
    raise TestFailed('Oops')
TypeError: exceptions must be old-style classes or derived from BaseException, not NoneType
Run Code Online (Sandbox Code Playgroud)

但它看起来TestFailed确实来自于BaseException.

python

20
推荐指数
3
解决办法
3万
查看次数

继承类中的python __init__方法

我想给一个子类一些额外的属性,而不必显式调用一个新方法.那么有没有一种方法可以为继承的类提供一个__init__不会覆盖__init__父类方法的类型方法?

我编写下面的代码纯粹是为了说明我的问题(因此属性的命名很差等).

class initialclass():
    def __init__(self):
        self.attr1 = 'one'
        self.attr2 = 'two'    

class inheritedclass(initialclass):
    def __new__(self):
        self.attr3 = 'three'

    def somemethod(self):
        print 'the method'


a = inheritedclass()

for each in a.__dict__:
    print each

#I would like the output to be:
attr1
attr2
attr3
Run Code Online (Sandbox Code Playgroud)

谢谢

python oop inheritance

19
推荐指数
3
解决办法
3万
查看次数

__init__方法在python中返回什么

class Num:
   def __init__(self,num):
      self.n = num
Run Code Online (Sandbox Code Playgroud)

我读到该__init__方法返回None.当我执行时a=Num(5),Num(5)将调用类的__init__方法.但是如果__init__ 返回Nonea应该引用nothing.But 而是a引用NumClass 的对象.它是如何发生的?那么__init__返回None还是类的对象?

python

17
推荐指数
1
解决办法
7094
查看次数

`__new__`中的`super()`是什么?

注意:使用Python的flyweight实现的一部分

import weakref

class CarModel:
    _models = weakref.WeakValueDictionary()

    def __new__(cls, model_name, *args, **kwargs):
        model = cls._models.get(model_name)
        if not model:
            model = super().__new__(cls)
            cls._models[model_name] = model    
        return model

    def __init__(self, model_name, air=False):
        if not hasattr(self, "initted"):
          self.model_name = model_name
          self.air = air
          self.initted=True
Run Code Online (Sandbox Code Playgroud)

问题1>什么super()意思?这是否意味着父类CarModel

问题2>我也很难理解该功能的__new__工作原理?具体来说,以下行.

model = super().__new__(cls)
Run Code Online (Sandbox Code Playgroud)

说明__new__:

构造函数被调用__new__而不是__init__,并且只接受一个参数,即正在构造的类(在构造对象之前调用它,因此没有自参数).它还必须返回新创建的对象.

python python-3.x

12
推荐指数
2
解决办法
8050
查看次数

如何从具有__new__方法的超类中正确继承?

假设我们有一个类'Parent',由于某种原因已__new__定义,并且继承了它的类'Child'.(在我的情况下,我试图继承我无法修改的第三方课程)

class Parent:
    def __new__(cls, arg):
        # ... something important is done here with arg
Run Code Online (Sandbox Code Playgroud)

我的尝试是:

class Child(Parent):
    def __init__(self, myArg, argForSuperclass):
         Parent.__new__(argForSuperclass)
         self.field = myArg
Run Code Online (Sandbox Code Playgroud)

但同时

p = Parent("argForSuperclass")
Run Code Online (Sandbox Code Playgroud)

按预期工作

c = Child("myArg", "argForSuperclass")
Run Code Online (Sandbox Code Playgroud)

失败,因为'Child'试图调用__new__它从'Parent'而不是它自己的__init__方法继承的方法.

为了获得预期的行为,我必须在"儿童"中进行哪些更改?

python inheritance

9
推荐指数
2
解决办法
5015
查看次数

不正确地使用__new__来生成类?

我正在创建一些类来处理各种类型的文件共享(nfs,afp,s3,本地磁盘)等文件名.我得到一个用户输入一个标识数据源(即"nfs://192.168.1.3""s3://mybucket/data")等的字符串.

我从具有公共代码的基类继承特定文件系统.我困惑的地方是对象创建.我所拥有的是以下内容:

import os

class FileSystem(object):
    class NoAccess(Exception):
        pass

    def __new__(cls,path):
        if cls is FileSystem:
            if path.upper().startswith('NFS://'): 
                return super(FileSystem,cls).__new__(Nfs)
            else: 
                return super(FileSystem,cls).__new__(LocalDrive)
        else:
            return super(FileSystem,cls).__new__(cls,path)

    def count_files(self):
        raise NotImplementedError

class Nfs(FileSystem):
    def __init__ (self,path):
        pass

    def count_files(self):
        pass

class LocalDrive(FileSystem):
    def __init__(self,path):
        if not os.access(path, os.R_OK):
            raise FileSystem.NoAccess('Cannot read directory')
        self.path = path

    def count_files(self):
        return len([x for x in os.listdir(self.path) if os.path.isfile(os.path.join(self.path, x))])

data1 = FileSystem('nfs://192.168.1.18')
data2 = FileSystem('/var/log')

print type(data1)
print type(data2)

print data2.count_files() …
Run Code Online (Sandbox Code Playgroud)

python factory factory-pattern

9
推荐指数
2
解决办法
3228
查看次数