Python: добавить атрибут в экземпляр, чтобы он появился в классе - PullRequest
0 голосов
/ 09 февраля 2019

В стремлении создать что-то, эквивалентное структуре Matlab в Python, я хочу создать класс, разработанный таким образом, чтобы при его экземпляре давался новый атрибут, которого у класса в целом еще нет,у класса автоматически объявляется атрибут этого имени (но с динамическим значением).

Например, если я определил класс color таким образом, но не имею атрибутов для начала, то яможет сделать следующее:

>> red = color()
>> blue = color()
>> blue.temperature
   AttributeError: type object 'color' has no attribute 'temperature'
>> red.temperature = 'hot'
>> blue.temperature
   blue.temperature = ''
>> blue.temperature = 'cool'

Есть ли способ взломать процесс добавления другого атрибута и добавить к нему команду, подобную cls.x = '', с x, являющейся переменной для имени атрибутадобавили в экземпляр?

Ответы [ 2 ]

0 голосов
/ 09 февраля 2019

Взять пример из Октавы https://octave.org/doc/v4.4.1/Structure-Arrays.html

Создать структурный массив:

>> x(1).a = "string1";
>> x(2).a = "string2";
>> x(1).b = 1;
>> x(2).b = 2;
>>
>> x
x =

  1x2 struct array containing the fields:

    a
    b

Если я добавлю поле к одной записи, будет добавлено или определено значение по умолчанию дляother:

>> x(1).c = 'red'
x =

  1x2 struct array containing the fields:

    a
    b
    c

>> x(2)
ans =

  scalar structure containing the fields:

    a = string2
    b =  2
    c = [](0x0)

>> save -7 struct1.mat x

In numpy

In [549]: dat = io.loadmat('struct1.mat')
In [550]: dat
Out[550]: 
{'__header__': b'MATLAB 5.0 MAT-file, written by Octave 4.2.2, 2019-02-09 18:42:35 UTC',
 '__version__': '1.0',
 '__globals__': [],
 'x': ...

In [551]: dat['x']
Out[551]: 
array([[(array(['string1'], dtype='<U7'), array([[1.]]), array(['red'], dtype='<U3')),
        (array(['string2'], dtype='<U7'), array([[2.]]), array([], shape=(0, 0), dtype=float64))]],
      dtype=[('a', 'O'), ('b', 'O'), ('c', 'O')])
In [552]: _.shape
Out[552]: (1, 2)

Структура была преобразована в структурированный массив numpy, с тем же shape, что и у Octave size(x).Каждое поле структуры является полем типа dtype в dat.

В отличие от Octave / MATLAB, мы не можем добавить поле к dat['x'] на месте.Я думаю, что в import numpy.lib.recfunctions as rf есть функция, которая может добавить поле с различными формами маскирования или по умолчанию для неопределенных значений, но это создаст новый массив.С некоторой работой я мог бы сделать это с нуля.

In [560]: x1 = rf.append_fields(x, 'd', [10.0])
In [561]: x1
Out[561]: 
masked_array(data=[(array(['string1'], dtype='<U7'), array([[1.]]), array(['red'], dtype='<U3'), 10.0),
                   (array(['string2'], dtype='<U7'), array([[2.]]), array([], shape=(0, 0), dtype=float64), --)],
             mask=[(False, False, False, False),
                   (False, False, False,  True)],
       fill_value=('?', '?', '?', 1.e+20),
            dtype=[('a', 'O'), ('b', 'O'), ('c', 'O'), ('d', '<f8')])
In [562]: x1['d']
Out[562]: 
masked_array(data=[10.0, --],
             mask=[False,  True],
       fill_value=1e+20)

Этот вид действий не подходит для системы классов Python.Класс обычно не отслеживает свои экземпляры.И после определения класс обычно не изменяется.Можно вести список экземпляров и добавлять методы в существующий класс, но это не обычная практика.

0 голосов
/ 09 февраля 2019

метод setattr

x = "temperature"
setattr(red,x,"HOT")

Я думаю, это то, что вы просите

, но, возможно, вы хотите перегрузить методы __setattr__ и __getattr__ вашегоцветовой класс

class color:
     attrs = {}
     def __getattr__(self,item):
         if item in self.attrs:
            return self.attrs[item]
         return ""
     def __setattr__(self,attr,value):
         self.attrs[attr] = value

c = color()
print(repr(c.hello))
c.hello = 5
print(repr(c.hello))
print(repr(c.temperature))
x = 'temperature'
setattr(c,x,"HOT")
print(repr(c.temperature))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...