Python 通过函数对象
Python Object via Function
我试图理解(并最终使用)使用来自 numpy 的记录数组的对象数组的实现,来自这里:Numpy object array 在审查代码时,我显然正在学习关于 python 和我似乎无法完全理解以下内容:
在 obarray.py 文件中,一个函数用于创建新对象,我对
感到困惑
- 为什么要用一个函数,
- 参数如何作用于函数,
- 使用此函数与直接使用参数创建 class 和(大概使用参数作为属性)和
有何不同
- 这是什么 main.Obarray 我只是调用函数时得到的?
对于 1 和 2,我有预感参数会以某种方式变成对象 "local scope" 并且可能类似于对象属性?
这是来自 link 的新对象的代码:
import numpy as np
def make_obarray(klass, dtype):
class Obarray(np.ndarray):
def __new__(cls, obj):
print "CLS:", cls
print "OBJ:", obj
A = np.array(obj,dtype=np.object)
N = np.empty(shape=A.shape, dtype=dtype)
for idx in np.ndindex(A.shape):
for name, type in dtype:
N[name][idx] = type(getattr(A[idx],name))
return N.view(cls)
def __getitem__(self, idx):
V = np.ndarray.__getitem__(self,idx)
if np.isscalar(V):
kwargs = {}
for i, (name, type) in enumerate(dtype):
kwargs[name] = V[i]
return klass(**kwargs)
else:
return V
def __setitem__(self, idx, value):
if isinstance(value, klass):
value = tuple(getattr(value, name) for name, type in dtype)
# FIXME: treat lists of lists and whatnot as arrays
return np.ndarray.__setitem__(self, idx, value)
return Obarray
以下是我的测试方式:
class Foo:
def __init__(self, a, b):
self.a = a
self.b = b
def __str__(self):
return "<Foo a=%s b=%s>" % (self.a, self.b)
dtype = [("a",np.int),
("b",np.float)]
FooArray = make_obarray(Foo, dtype)
A = FooArray([Foo(0,0.1),Foo(1,1.2),Foo(2,2.1),Foo(3,3.3)])
- 当我调用 FooArray 时,我得到
__main__.Obarray
- 这是什么?
- 我作为参数输入的 "klass" 和 "dtype" 发生了什么?
- 这与以下内容有何不同:
Blockquote
class Obarray(np.ndarray):
def __new__(cls,input_array, klass, dtype):
obj = np.assarray(input_array).view(cls)
obj.klass = klass
obj.dtype = dtype
A = np.array(obj,dtype=np.object)
N = np.empty(shape=A.shape, dtype=dt ype)
for idx in np.ndindex(A.shape):
for name, type in dtype:
N[name][idx] = type(getattr(A[idx],name))
obj.N = N.view(np.ndarray)
return obj
make_obarray
函数是一个生产classes的工厂。 class 的 it returns 的方法将是可以访问函数的局部变量(例如 klass
和 dtype
参数)的闭包,即使它已完成 运行.
这里有一个更简单的闭包,可以帮助您理解它们的工作原理:
def make_adder(x):
def adder(y):
return x + y
return adder
make_adder
是一个工厂函数。它 returns 一个 adder
函数,它是一个闭包。即使在 make_adder
返回后,adder
仍然可以看到定义它的 make_adder
调用的 x
参数。
这与您显示的 numpy
代码相似。 make_obarray
函数returns一个class,而不是一个函数,但除此之外几乎是一样的。 class 的限定名称将是 Python 2 中的 some_module.Obarray
(或 Python 3 中的 some_module.make_obarray.<locals>.Obarray
),其中 some_module
是它在其中定义的模块(或 __main__
如果您已将其模块作为脚本执行)。返回的 class 的方法将能够看到传递给 make_obarray
的 klass
和 dtype
参数,就像 adder
函数可以看到 [=在我更简单的例子中,make_adder
的 18=] 参数。
至于为什么你找到的代码是这样写的,我也不好说。也许代码的作者认为能够使用 isinstance
来区分具有不同 klass
或 dtype
值的 Obarray
实例会很有用:
FooArray = make_obarray(Foo, dtype)
BarArray = make_obarray(Bar, some_other_dtype)
f = FooArray([Foo(1,2)])
print(isinstance(f, FooArray)) # True
print(isinstance(f, BarArray)) # False
如果 klass
和 dtype
只是单个 class 的参数,您无法通过这种方式区分数组实例(尽管您可能会进行比较实例属性的等效检查)。
我试图理解(并最终使用)使用来自 numpy 的记录数组的对象数组的实现,来自这里:Numpy object array 在审查代码时,我显然正在学习关于 python 和我似乎无法完全理解以下内容:
在 obarray.py 文件中,一个函数用于创建新对象,我对
感到困惑- 为什么要用一个函数,
- 参数如何作用于函数,
- 使用此函数与直接使用参数创建 class 和(大概使用参数作为属性)和 有何不同
- 这是什么 main.Obarray 我只是调用函数时得到的?
对于 1 和 2,我有预感参数会以某种方式变成对象 "local scope" 并且可能类似于对象属性?
这是来自 link 的新对象的代码:
import numpy as np
def make_obarray(klass, dtype):
class Obarray(np.ndarray):
def __new__(cls, obj):
print "CLS:", cls
print "OBJ:", obj
A = np.array(obj,dtype=np.object)
N = np.empty(shape=A.shape, dtype=dtype)
for idx in np.ndindex(A.shape):
for name, type in dtype:
N[name][idx] = type(getattr(A[idx],name))
return N.view(cls)
def __getitem__(self, idx):
V = np.ndarray.__getitem__(self,idx)
if np.isscalar(V):
kwargs = {}
for i, (name, type) in enumerate(dtype):
kwargs[name] = V[i]
return klass(**kwargs)
else:
return V
def __setitem__(self, idx, value):
if isinstance(value, klass):
value = tuple(getattr(value, name) for name, type in dtype)
# FIXME: treat lists of lists and whatnot as arrays
return np.ndarray.__setitem__(self, idx, value)
return Obarray
以下是我的测试方式:
class Foo:
def __init__(self, a, b):
self.a = a
self.b = b
def __str__(self):
return "<Foo a=%s b=%s>" % (self.a, self.b)
dtype = [("a",np.int),
("b",np.float)]
FooArray = make_obarray(Foo, dtype)
A = FooArray([Foo(0,0.1),Foo(1,1.2),Foo(2,2.1),Foo(3,3.3)])
- 当我调用 FooArray 时,我得到
__main__.Obarray
- 这是什么? - 我作为参数输入的 "klass" 和 "dtype" 发生了什么?
- 这与以下内容有何不同:
Blockquote
class Obarray(np.ndarray):
def __new__(cls,input_array, klass, dtype):
obj = np.assarray(input_array).view(cls)
obj.klass = klass
obj.dtype = dtype
A = np.array(obj,dtype=np.object)
N = np.empty(shape=A.shape, dtype=dt ype)
for idx in np.ndindex(A.shape):
for name, type in dtype:
N[name][idx] = type(getattr(A[idx],name))
obj.N = N.view(np.ndarray)
return obj
make_obarray
函数是一个生产classes的工厂。 class 的 it returns 的方法将是可以访问函数的局部变量(例如 klass
和 dtype
参数)的闭包,即使它已完成 运行.
这里有一个更简单的闭包,可以帮助您理解它们的工作原理:
def make_adder(x):
def adder(y):
return x + y
return adder
make_adder
是一个工厂函数。它 returns 一个 adder
函数,它是一个闭包。即使在 make_adder
返回后,adder
仍然可以看到定义它的 make_adder
调用的 x
参数。
这与您显示的 numpy
代码相似。 make_obarray
函数returns一个class,而不是一个函数,但除此之外几乎是一样的。 class 的限定名称将是 Python 2 中的 some_module.Obarray
(或 Python 3 中的 some_module.make_obarray.<locals>.Obarray
),其中 some_module
是它在其中定义的模块(或 __main__
如果您已将其模块作为脚本执行)。返回的 class 的方法将能够看到传递给 make_obarray
的 klass
和 dtype
参数,就像 adder
函数可以看到 [=在我更简单的例子中,make_adder
的 18=] 参数。
至于为什么你找到的代码是这样写的,我也不好说。也许代码的作者认为能够使用 isinstance
来区分具有不同 klass
或 dtype
值的 Obarray
实例会很有用:
FooArray = make_obarray(Foo, dtype)
BarArray = make_obarray(Bar, some_other_dtype)
f = FooArray([Foo(1,2)])
print(isinstance(f, FooArray)) # True
print(isinstance(f, BarArray)) # False
如果 klass
和 dtype
只是单个 class 的参数,您无法通过这种方式区分数组实例(尽管您可能会进行比较实例属性的等效检查)。