The built-in object can be instantiated but can't have any attributes set on it. (I wish it could, for this exact purpose.) This is because it doesn't have a __dict__ to hold the attributes.
I generally just do this:
class Object(object):
pass
obj = Object()
obj.somefield = "somevalue"
But consider giving the Object class a more meaningful name, depending on what data it holds.
Another possibility is to use a sub-class of dict that allows attribute access to get at the keys:
class AttrDict(dict):
def __getattr__(self, key):
return self[key]
def __setattr__(self, key, value):
self[key] = value
obj = AttrDict()
obj.somefield = "somevalue"
To instantiate the object attributes using a dictionary:
d = {"a": 1, "b": 2, "c": 3}
for k, v in d.items():
setattr(obj, k, v)
Answer from FogleBird on Stack OverflowThe built-in object can be instantiated but can't have any attributes set on it. (I wish it could, for this exact purpose.) This is because it doesn't have a __dict__ to hold the attributes.
I generally just do this:
class Object(object):
pass
obj = Object()
obj.somefield = "somevalue"
But consider giving the Object class a more meaningful name, depending on what data it holds.
Another possibility is to use a sub-class of dict that allows attribute access to get at the keys:
class AttrDict(dict):
def __getattr__(self, key):
return self[key]
def __setattr__(self, key, value):
self[key] = value
obj = AttrDict()
obj.somefield = "somevalue"
To instantiate the object attributes using a dictionary:
d = {"a": 1, "b": 2, "c": 3}
for k, v in d.items():
setattr(obj, k, v)
You could use my ancient Bunch recipe, but if you don't want to make a "bunch class", a very simple one already exists in Python -- all functions can have arbitrary attributes (including lambda functions). So, the following works:
obj = lambda: None
obj.somefield = 'somevalue'
Whether the loss of clarity compared to the venerable Bunch recipe is OK, is a style decision I will of course leave up to you.
Adding new (undefined) attributes on class instances
dynamically add properties to a class (property, __getattribute__, something else?)
Properties must be defined on the class, not the instance. You're assigning the property on self when it needs to be assigned on A.
But dynamically creating attributes like this is weird and messy. The first thing you should do is reconsider whether you really do need to dynamically create attributes. It's an overly complex solution to most problems. Describing your problem to us might be helpful here. If you still decide you need this then you should use __getattr__ (and probably not __getattribute__). Properties are not the right solution.
Python: How to assign attributes to existing objects?
Setting an attibute of an object as a String
Videos
I'm trying to dynamically add attributes with setters and getters to objects on instantiation. However, I can't figure out how to dynamically add a property to a class. IE:
class A(object):
def __init__(self):
self.x = property(lambda self: 'no work :(')
a = A()
print a.x #prints a property object
class B(object):
x = property(lambda self: 'works!') #can't be defined on instantiation
b = B()
print b.x #prints "works!"What I actually want to do is more like this:
class C(object):
def __init__(self,attr_objects):
# generate setters and getters for attributes
setter = self._setter_factory
getter = self._getter_factory
for attr in attr_objects:
setattr(self,attr.name,property(getter(attr),setter(attr)))
My next guess would be to over-ride C.__getattribute__ and C.__setattribute__ so they check if the accessed attribute is one of my dynamically generated ones. If so, call the appropriate function, otherwise handle as usual. Is there a more elegant/pythonic way?
edit: more details on what I'm actually doing:
This is a Data Oriented Programming ORM. I have a DataDomain that has numpy arrays. When you add an "object" to it through the add method, it registers space in those arrays and you get a DataAccessor back that you use to interact with that "instance's" properties. The C class above is my DataAccessor. Like I could have a PolygonDataDomain with arrays of positions and angles of rotation of polygons. When you add a polygon to it, you get an accessor that has a position and angle. When you get or set those values, the getter and setter do it through the PolygonDataDomain arrays. So:
class PolygonDataDomain(DataDomain):
def __init__(self):
self.positions = DataArray()
self.angles = DataArray()
self._data_oriented_properties = [self.positions, self.angles]
def add(self, position, angle):
#register space for this in the DataArrays
#generate an id through which to keep track of this registered space
return DataAccessor(self,id)
class DataAccessor(object):
def __init__(self, domain, id):
self.__domain = domain
self.__id = id
for attr in domain._data_oriented_properties:
#create an attribute for this attr with appropriate setters and getters
poly_domain = PolygonDataDomain()
poly1 = poly_domain.add( (0,0), 5.)
print dir(poly1) # shows that this "instance" has a position and angle
poly1.position = (2,3) #updates DataArray entry for this "instance"After creating the PolygonDataDomain subclass, I don't want to have to repeat myself in defining it's properties by having to make a specific PolygonDataAccessor and hard coding it's properties and setters and getters.
Properties must be defined on the class, not the instance. You're assigning the property on self when it needs to be assigned on A.
But dynamically creating attributes like this is weird and messy. The first thing you should do is reconsider whether you really do need to dynamically create attributes. It's an overly complex solution to most problems. Describing your problem to us might be helpful here. If you still decide you need this then you should use __getattr__ (and probably not __getattribute__). Properties are not the right solution.
If you want to be ugly you could do this:
class A(object):
def __init__(self):
A.x = property(lambda self: 'works :)')
(you did say you wanted to add to the class, not the instance)