简体   繁体   English

Python:将属性添加到实例,使其出现在类中

[英]Python: add attribute to instance, have it appear in class

In pursuit of creating something equivalent to the struct of Matlab in Python, I want to create a class that is designed so that when an instance of it is given a new attribute that the class as a whole doesn't yet have, the class is automatically declared to have an attribute of that name (but dynamic value). 为了追求在Python中创建等效于Matlab的结构,我想创建一个设计成这样的类,以便在给它的实例赋予新的属性时,该类作为一个整体还不具有,因此该类是自动声明为具有该名称的属性(但为动态值)。

For example, if I have defined the class color in this manner, but having no attributes to start with, then I could do the following: 例如,如果我以这种方式定义了类的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'

Is there a way to hack the process of adding another attribute and add to it a command like cls.x = '' , with x being a variable for the name of the attribute added to the instance? 有没有办法破解添加另一个属性并向其添加诸如cls.x = ''类的命令cls.x = '' ,其中x是添加到实例的属性名称的变量?

the setattr method setattr方法

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

I think is what you are asking for 我想是你要的

but maybe what you want is to overload the __setattr__ and __getattr__ methods of your color class 但也许您想要的是重载颜色类的__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))

To take an example from Octave https://octave.org/doc/v4.4.1/Structure-Arrays.html 以Octave为例, https://octave.org/doc/v4.4.1/Structure-Arrays.html

Make a structure array: 制作一个结构数组:

>> 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

If I add a field to one entry, a default value is added or defined for the 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 在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)

The struct has been translated into a structured numpy array, with the same shape as the Octave size(x) . 该结构已转换为结构化的numpy数组,其shape与Octave size(x) Each struct field is an object dtype field in dat . 每个struct字段都是dat一个对象dtype字段。

In contrast to Octave/MATLAB we can't add a field to dat['x'] in-place. 与Octave / MATLAB相比,我们不能就地向dat['x']添加字段。 I think there's a function in import numpy.lib.recfunctions as rf that can add a field, with various forms of masking or default for undefined values, but that will make a new array. 我认为import numpy.lib.recfunctions as rf有一个函数可以import numpy.lib.recfunctions as rf添加一个字段,具有各种形式的掩码或未定义值的默认值,但这将创建一个新数组。 With some work I could do that from scratch. 通过一些工作,我可以从头开始。

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)

This kind of action does not fit the Python class system well. 这种动作不太适合Python类系统。 A class doesn't normally keep track of its instances. 类通常不会跟踪其实例。 And once defined a class is not normally amended. 并且一旦定义了一个类,通常就不会对其进行修改。 It is possible to maintain a list of instances, and it is possible to add methods to an existing class, but that's not common practice. 可以维护实例列表,还可以将方法添加到现有的类中,但这不是常见的做法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM