__new__ 不合理地创建生成器
__new__ irrationally creates generator
我有一个 class 处理数组并根据类型用不同的 class 包装它或制作一个生成器
Coat class 决定如何处理参数
涂层是核心class
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)
它returns 我是发电机:
<generator object Coat.__new__ at 0x7fc2b4410bf8>
<generator object Coat.__new__ at 0x7fc291b5ef10>
new.
中没有打印任何内容
但是,如果我删除生成器创建,一切正常
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]]
yield里面的__new__怎么可能表现的这么霸道,也就是说,弄得一团糟甚至如果它处于未触发的条件内?
How is it possible that yield
inside __new__
behaves so dominantly, that is to say, makes a mess even if it is inside a condition that is not triggered?
这是 Python 语言的内置功能。 yield
在函数中的存在(函数中的任何位置)自动使该函数成为生成器函数。
来自文档:
7.7. The yield statement
[...]
Yield expressions and statements are only used when defining a generator function, and are only used in the body of the generator function. Using yield in a function definition is sufficient to cause that definition to create a generator function instead of a normal function.
[...]
请注意,return
在生成器函数中的行为也与在普通函数中的行为略有不同。
另外我认为可能有更好的方法来处理这种情况,例如使用一个简单的函数而不是“class with __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__
总是returns作为发电机。
我有一个 class 处理数组并根据类型用不同的 class 包装它或制作一个生成器
Coat class 决定如何处理参数
涂层是核心class
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)
它returns 我是发电机:
<generator object Coat.__new__ at 0x7fc2b4410bf8>
<generator object Coat.__new__ at 0x7fc291b5ef10>
new.
中没有打印任何内容但是,如果我删除生成器创建,一切正常
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]]
yield里面的__new__怎么可能表现的这么霸道,也就是说,弄得一团糟甚至如果它处于未触发的条件内?
How is it possible that
yield
inside__new__
behaves so dominantly, that is to say, makes a mess even if it is inside a condition that is not triggered?
这是 Python 语言的内置功能。 yield
在函数中的存在(函数中的任何位置)自动使该函数成为生成器函数。
来自文档:
7.7. The yield statement
[...]
Yield expressions and statements are only used when defining a generator function, and are only used in the body of the generator function. Using yield in a function definition is sufficient to cause that definition to create a generator function instead of a normal function.
[...]
请注意,return
在生成器函数中的行为也与在普通函数中的行为略有不同。
另外我认为可能有更好的方法来处理这种情况,例如使用一个简单的函数而不是“class with __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__
总是returns作为发电机。