2017-01-13 4 views
3

В библиотеке питона pytides, я наткнулся на странный метод инициализировать класс (Tide класс и его initialization). я Приводимый ниже упрощенной версии кода:Странная инициализации класса в Python

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) 

Как я понимаю, переменная DTYPE в Foobar является глобальной переменной, но я не понимаю, какой смысл иметь его. Это просто здесь, чтобы обеспечить удобный способ инициализации Foobar? Кроме того, классу Foobar нужен массив Foobar.dtype при построении, это не своего рода циклический вызов (который должен произойти сбой)?

+4

Переменная 'dtype' в' Foobar' - это _not_ глобальная переменная, это атрибут класса, который разделяется всеми экземплярами класса Foobar. –

ответ

1

Foobar.dtype - это атрибут класса.

Это переменная, которая привязана к определению класса не к одному экземпляру класса. Если вы знакомы с другими популярными объектно-ориентированными языками, эта концепция очень похожа на статические переменные в Java и C#.

Python Docs что объясняет более подробно https://docs.python.org/3/tutorial/classes.html#class-objects


Учитывая класс Foobar в примере вы предоставили:

Foobar класс

myFoobar является экземпляром Foobar

давайте притворимся, что есть еще один пример: yourFoobar

затем myFoobar и yourFoobar (и любые другие случаи), возможно, потребуется, чтобы иметь возможность получить доступ к некоторым данным (в данном случае определение numpy типа данных), который является одинаковым для всех экземпляров Foobar. Таким образом, есть аргумент, что он должен быть связан с классом, а не с каждым отдельным экземпляром. (Однако есть также аргументы, что атрибуты класса/статические переменные приносят больше вреда, чем пользы: Why are static variables considered evil?)

т. Е. Избегать способа записи его, где каждый экземпляр Foobar выделяет свой экземпляр того же определения numty 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)]) 
+0

Спасибо @ Рихард. Я думаю, что меня смутило имя переменной (dtype). Документ Python делает его более ясным. – Marcel

1

Существует не так много, что странно об этой инициализации, dtype держит типы Foobar требует для Numpy массива он получает durings его инициализации (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' соответственно.

Смежные вопросы