【问题标题】:__new__ irrationally creates generator__new__ 不合理地创建生成器
【发布时间】:2019-11-16 14:38:49
【问题描述】:

我有一个处理数组的类,并根据类型用不同的类包装它或制作一个生成器

外套类决定如何处理参数

涂层是核心类

class Coat:
    def __new__(cls, array, dtype=np.float32):

        if isinstance(array, np.ndarray):
            print('Condition 1')
            template = dtype(Coating(array.shape) * 0 + array)
            return template

        if isinstance(array, (list,tuple, GeneratorType)):
            print('Condition 2')
            for item in array:
                yield dtype(Coating(item.shape) * 0 + item)

class Coating(np.ndarray):

    def __init__(self, *args, **kwargs):
        if len(self.shape) < 2:
            raise Exception("Not accustomed for 1D")
    def ...
    ...

所以当我尝试触发两个条件(条件 1 或条件 2)时

iterable = Coat([np.zeros(shape = [20,35]),np.zeros(shape = [20,35]),np.zeros(shape = [20,35])])
print(iterable)
array = Coat(np.zeros(shape=[10,10]),dtype=np.uint8)
print(array)

它返回给我生成器:

<generator object Coat.__new__ at 0x7fc2b4410bf8>
<generator object Coat.__new__ at 0x7fc291b5ef10>

中没有打印任何内容。

但是,如果我删除生成器创建,一切正常

class Coat:
    def __new__(cls, array, dtype=np.float32):

        if isinstance(array, np.ndarray):
            print('Condition 1')
            template = dtype(Coating(array.shape) * 0 + array)
            return template
        if isinstance(array, (list,tuple, GeneratorType)):
            print('Condition 2')

然后

Condition 2
None
Condition 1
[[0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0]]

__new__ 中的 yield 怎么可能表现得如此占主导地位,也就是说,即使它在未触发的条件中也会造成混乱?

【问题讨论】:

  • 我不认为 new 是适合这项工作的工具
  • 目前还不清楚您为什么会有其他预期。在任何分支上产生的任何函数都会返回一个生成器。
  • @D.BenKnoble 那么什么是好的做法呢?
  • 看起来您只是在两个不同的结果之间做出选择——一个函数? new 通常用于元编程。函数也可以返回类和对象
  • __new__ 不一定用于元编程,但是当Coat__new__ 方法从不返回Coat 的实例时,它几乎没有理由成为一个类;它也可能是一个普通的功能。 (请特别注意,您永远不会在正文中使用 cls 的值,这肯定表明您正在做一些不必要的复杂事情。)

标签: python class oop metaprogramming yield


【解决方案1】:

__new__ 内部的 yield 怎么可能表现得如此占主导地位,也就是说,即使它处于未触发的条件之内,也会造成混乱?

这是 Python 语言中内置的。 yield 在函数中(函数中的任何位置)的存在会自动使该函数成为生成器函数。

来自文档:

7.7. The yield statement

[...]

Yield 表达式和语句仅在定义 generator 函数时使用,并且仅在生成器函数的主体中使用。 在函数定义中使用 yield 足以使该定义创建生成器函数而不是普通函数。

[...]

请注意,生成器函数中的return 的行为也会与普通函数中的有所不同。


另外我认为可能有更好的方法来处理这种情况,例如使用简单的函数而不是“带有__new__ 的类”。但我对您的代码了解得不够多,无法提出更好或更合适的解决方案。

但是,如果您只是想“让它工作”,您也可以在第一个分支中yield

class Coat:
    def __new__(cls, array, dtype=np.float32):
        if isinstance(array, np.ndarray):
            yield dtype(Coating(array.shape) * 0 + array)

        if isinstance(array, (list,tuple, GeneratorType)):
            for item in array:
                yield dtype(Coating(item.shape) * 0 + item)

然后Coat.__new__ 总是作为生成器返回。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-11-19
    • 1970-01-01
    • 2018-12-18
    • 2013-04-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多