【问题标题】:Strange class initialization in PythonPython中奇怪的类初始化
【发布时间】:2017-01-13 08:03:29
【问题描述】:

在 python 库 pytides 中,我遇到了一种奇怪的方法来初始化一个类(Tide 类及其 initialization )。 我在下面转载了代码的简化版本:

import numpy as np

class Foo(object):
    def __init__(self,x,y):
        self.x = x
        self.y = y

class Foobar(object):
    dtype = np.dtype([('fooObj', object),
                      ('A', float),
                      ('B', float)])

    def __init__(self,model):
        '''model: an ndarray of type Foobar.dtype '''
        self.model = model


# initialize a Foobar object
myFoos = [Foo(4,3),Foo(4,9),Foo(0,2)]
A = [2,3,4]
B = [8,9,0]
model = np.zeros(len(myFoos), dtype = Foobar.dtype)
model['fooObj'] = myFoos     #what is that?!?
model['A'] = A
model['B'] = B
myFoobar = Foobar(model=model)

据我了解,Foobar 中的 dtype 变量是一个全局变量,但我不明白拥有它有什么意义。只是在这里提供一种方便的方式来初始化 Foobar 吗?而且 Foobar 类在构造时需要一个 Foobar.dtype 数组,是不是一种循环调用(应该崩溃)?

【问题讨论】:

  • Foobar 中的dtype 变量不是全局变量,它是一个类属性,由Foobar 类的所有实例共享。跨度>

标签: python python-3.x oop numpy


【解决方案1】:

Foobar.dtype 是一个类属性。

这是一个附加到类定义的变量,而不是类的单个实例。如果您熟悉其他流行的面向对象语言,这个概念与 Java 和 C# 中的静态变量非常相似。

Python 文档更详细地解释了https://docs.python.org/3/tutorial/classes.html#class-objects


考虑您提供的示例中的类 Foobar:

Foobar 是一个类

myFoobarFoobar 的一个实例

让我们假设还有另一个实例:yourFoobar

那么myFoobaryourFoobar(以及任何其他实例)可能需要能够访问某些数据(在这种情况下是numpy 数据类型的定义),这对于@ 的所有实例都是相同的987654331@。因此,有一个论点是它应该与类相关联,而不是与每个单独的实例相关联。 (不过也有观点认为类属性/静态变量弊大于利:Why are static variables considered evil?

即避免一种编写方式,您将 Foobar 的每个实例分配给它自己的相同 numpy dtype 定义的实例,例如...

class Foobar(object):
    def __init__(self,model):
        '''model: an ndarray of type self.dtype '''
        self.model = model
        self.dtype = np.dtype([('fooObj', object),
                      ('A', float),
                      ('B', float)])

【讨论】:

  • 谢谢@Richard。我想我对变量(dtype)的名称感到困惑。 Python 文档使其更清晰。
【解决方案2】:

这个初始化并没有什么奇怪的,dtype 拥有 Foobar 在初始化期间接收到的 numpy 数组所需的类型 (model)。它是一个类属性,而不是全局属性,因此它由Foobar 类的所有实例共享。

model 的初始化方式可能看起来很奇怪,但它只是根据指定字段的名称来初始化 model,这可能最好通过在步骤之间打印出 model 来证明:

model['fooObj'] = myFoos
print(model)
array([(<__main__.Foo object at 0x7f125ed93828>, 0.0, 0.0),
       (<__main__.Foo object at 0x7f125ed93940>, 0.0, 0.0),
       (<__main__.Foo object at 0x7f125ed93240>, 0.0, 0.0)], 
      dtype=[('fooObj', 'O'), ('A', '<f8'), ('B', '<f8')])

添加'fooObj' 对象类型的值。而:

model['A'] = A
model['B'] = B

分别添加float 类型'A''B' 的值。

【讨论】:

    猜你喜欢
    • 2017-11-15
    • 2011-02-22
    • 1970-01-01
    • 2017-05-18
    • 2021-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多