简体   繁体   English

如何从python的zip继承而使用class attrs?

[英]How to inherit from python's zip but use class attrs?

I ran into an interesting issue... I was trying to SubClass python's zip type... I wanted to create a class that acted as a zip yet has class attrs. 我遇到了一个有趣的问题...我试图对python的zip类型进行SubClass ...我想创建一个充当zip的类,但具有class attrs。

At First I tried 起初我尝试过

class SomeClass(zip):
    def __init__(self):
        print('I ran')
        self.x = np.array([1,2,3,4])
        self.y = np.array([1,4,9,16])
        super().__init__(self.x,self.y)

But it seems like zip 's __init__ takes nothing but self ? 但是似乎zip__init__除了self什么都不做?

So I tried 所以我尝试了

class SomeClass(zip):
    def __init__(self):
        self.x = np.array([1, 2, 3, 4])
        self.y = np.array([1, 4, 9, 16])

    def new(self):
        return zip.__new__(SomeClass, self.x, self.y)

Which works but requires I do x=SomeClass().new() 哪个有效,但需要我执行x=SomeClass().new()

Finally I got to this... 终于我明白了...

class SomeClass(zip):
    def __init__(self):
        print('I ran')
        self.x = np.array([1,2,3,4])
        self.y = np.array([1,4,9,16])
    def __new__(self):
        self.__init__(self)
        return zip.__new__(self, self.x, self.y)
for i in SomeClass():
...     print(i)
...
I ran
I ran
(1, 1)
(2, 4)
(3, 9)
(4, 16)

This runs __init__ twice... I am just curious if there is a way to circumvent this or will class attrs never exist at the time __new__ runs? 这两次运行__init__我只是好奇是否有办法绕过这个问题,或者在__new__运行时是否永远不会存在类attrs?

UPDATE: This ALMOST works 更新:此ALMOST有效

class SomeClass(zip):
    def __new__(self):
        self.x = np.array([1,2,3,4])
        self.y = np.array([1,4,9,16])
        return super().__new__(self, self.x, self.y)

How ever x and y are not instance variables :(. Example xy不是实例变量:(。

class SomeClass(zip):
    def __new__(self, x, y):
        self.x = x
        self.y = y
        return super().__new__(self, self.x, self.y)
>>> k=SomeClass([1,2],[3,4])
>>> k.x
[1, 2]
>>> j=SomeClass([2,2],[4,4])
>>> j.x
[2, 2]
>>> k.x
[2, 2]

Why is this? 为什么是这样?

Your problem is that you're trying to use the object attributes self.x and self.y in __new__ , where self doesn't actually exist yet. 你的问题是,你要使用的对象属性self.xself.y__new__ ,其中self实际上并不存在呢。 (The thing you've so inappropriately labeled self is actually the class.) You're going about this backwards. (你这么不恰当地标示事情self实际上是类。)你倒退这个问题。 First, __new__ must create an object ( self ), and only then can you call __init__ . 首先, __new__必须创建一个对象( self ), 然后才能调用__init__ (You shouldn't, though, because python will do it for you automatically.) (不过,您不应该这样做,因为python会自动为您完成此操作。)

Now, as you've already found out, you have to have access to x and y before __init__ is executed (because you have to pass them to zip.__new__ ). 现在,您已经发现,必须执行__init__ 之前访问xy (因为必须将它们传递给zip.__new__ )。 Because of this, it's easiest to initialize x and y directly in __new__ . 因此,最简单的方法是直接在__new__初始化xy (The __init__ then no longer serves a purpose, so it can be removed.) (然后, __init__不再__init__ ,因此可以将其删除。)

class SomeClass(zip):
    def __new__(cls):
        x = [1, 2, 3, 4]
        y = [1, 4, 9, 16]

        obj = super().__new__(cls, x, y)

        obj.x = x
        obj.y = y
        return obj

    def __init__(self):
        print('I ran')

Demo: 演示:

>>> k = SomeClass()
I ran
>>> k.x
[1, 2, 3, 4]
>>> k.y
[1, 4, 9, 16]
>>> list(k)
[(1, 1), (2, 4), (3, 9), (4, 16)]

zip doesn't define __init__ . zip没有定义__init__ super().__init__ actually calls object.__init__ (since in this example, the MRO consists of just SomeClass , zip , and object ), which expects no arguments. super().__init__实际上会调用object.__init__ (因为在此示例中,MRO仅由SomeClasszipobject ),它不需要任何参数。 After calling that, you can set your own attributes. 调用之后,您可以设置自己的属性。

class SomeClass(zip):
    def __init__(self, *args, **kwargs):
        super().__init__(**kwargs)
        self.x = np.array([1,2,3,4])
        self.y = np.array([1,4,9,16])

If you don't care about cooperative inheritance, you can simplify it to 如果您不关心协作继承,则可以将其简化为

class SomeClass(zip):
    def __init__(self, *args):
        self.x = np.array([1,2,3,4])
        self.y = np.array([1,4,9,16])

While I'm not sure to understand the purpose of this, you can do it by using delegation instead of inheritance: 虽然我不确定要了解的目的,但是可以通过使用委托而不是继承来做到这一点:

class SomeClass:
    def __init__(self):
        self.x = [1,2,3,4]
        self.y = [1,4,9,16]
        self.zipp = zip(self.x, self.y)

    def __iter__(self):
        return self.zipp

for x, y in SomeClass():
    print(x, y)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM