Class object instance. Link instance attribute to class. Can it be done easier. - Printable Version +- Python Forum (https://python-forum.io) +-- Forum: Python Coding (https://python-forum.io/forum-7.html) +--- Forum: General Coding Help (https://python-forum.io/forum-8.html) +--- Thread: Class object instance. Link instance attribute to class. Can it be done easier. (/thread-14484.html) |
Class object instance. Link instance attribute to class. Can it be done easier. - Windspar - Dec-03-2018 Just want class object instance to update all children. Every time object value changes. Linking class object instance attributes to class. Can it be done any easier than this. class Point: def __init__(self, x, y): self.x = x self.y = y def set(self, x, y): self.x = x self.y = y def __repr__(self): return str(vars(self)) class Dimension: def __init__(self, w, h): self.w = w self.h = h def set(self, w, y): self.w = w self.h = h def __repr__(self): return str(vars(self)) def dir_trim(item): return [d for d in dir(item) if not d.startswith('__')] class LinkProperty: def __init__(self, attr): self.attr = attr def __set__(self, instance, value): setattr(instance.read_value, self.attr, value) instance.callback() def __get__(self, instance, owner): return getattr(instance.read_value, self.attr) def link_variable(value, callback): class LinkVariable: def __init__(self, value, callback): self.read_value = value self.callback = callback def __call__(self, value=None): if value is None: return self.read_value self.read_value = value self.callback() def clear(self): self.read_value = None self.callback() items = dir_trim(value) for item in items: setattr(LinkVariable, item, LinkProperty(item)) return LinkVariable(value, callback) def callback(): print('Callback') a = link_variable(Point(2,3), callback) b = link_variable(Dimension(1,4), callback) print(dir_trim(a)) print(dir_trim(b)) print(a.read_value, b.read_value) a.x = 7 print(a.read_value, b.read_value) print(a.x, a.y, b.w, b.h) RE: Class object instance. Link instance attribute to class. Can it be done easier. - ichabod801 - Dec-03-2018 It's totally unclear to me what you are trying to do. Can you explain the desired behavior, in English, with examples? RE: Class object instance. Link instance attribute to class. Can it be done easier. - Windspar - Dec-03-2018 I have objects like a pygame.Rect. It has methods and properties. Every time it values changes. I want a callback to update a list. Example The problem is I have to remember to type update_point_total. class Point: def __init__(self, x, y): self.x = x self.y = y def copy(self): return Point(self.x, self.y) def set(self, x, y): self.x = x self.y = y def __add__(self, point): return Point(self.x + point.x, self.y + point.y) def __repr__(self): return str(vars(self)) class MyObject: def __init__(self, point): self.parent = None self.point = point self.point_total = point.copy() self.items = [] def add(self, my_object): my_object.parent = self my_object.update_point_total() self.items.append(my_object) def get_points(self): if self.parent: return self.point + self.parent.get_points() return self.point.copy() def update_point_total(self): self.point_total = self.point.copy() if self.parent: self.point_total = self.get_points() self.update_all_items() def update_all_items(self): for item in self.items: item.update_point_total() def __repr__(self): return str(vars(self)) def main(): a = MyObject(Point(1,1)) b = MyObject(Point(2,2)) c = MyObject(Point(5,5)) d = MyObject(Point(10,10)) a.add(b) c.add(d) a.add(c) print(a.point_total) print(b.point_total) print(c.point_total) print(d.point_total) # This is all over my code b.point.x = 5 # If this is forgotten. Hard bug to find. b.update_point_total() c.point.y += 3 c.update_point_total() print() print(a.point_total) print(b.point_total) print(c.point_total) print(d.point_total) main()My solution was to use a class. That holds the rect and callback. I link this rect attributes, methods, and properties to the class. For I don't have to remember to type update after value changes. def dir_trim(item): return [d for d in dir(item) if not d.startswith('__')] class LinkProperty: def __init__(self, attr): self.attr = attr def __set__(self, instance, value): setattr(instance.read_value, self.attr, value) instance.callback() def __get__(self, instance, owner): return getattr(instance.read_value, self.attr) def link_variable(value, callback): class LinkVariable: def __init__(self, value, callback): self.read_value = value self.callback = callback def __call__(self, value=None): if value is None: return self.read_value self.read_value = value self.callback() def clear(self): self.read_value = None self.callback() items = dir_trim(value) for item in items: setattr(LinkVariable, item, LinkProperty(item)) return LinkVariable(value, callback) class Point: def __init__(self, x, y): self.x = x self.y = y def copy(self): return Point(self.x, self.y) def set(self, x, y): self.x = x self.y = y def __add__(self, point): return Point(self.x + point.x, self.y + point.y) def __repr__(self): return str(vars(self)) class MyObject: def __init__(self, point): self.parent = None self.point = link_variable(point, self.update_point_total) self.point_total = point.copy() self.items = [] def add(self, my_object): my_object.parent = self my_object.update_point_total() self.items.append(my_object) def get_points(self): if self.parent: return self.point.read_value + self.parent.get_points() return self.point.copy() def update_point_total(self): self.point_total = self.point.copy() if self.parent: self.point_total = self.get_points() self.update_all_items() def update_all_items(self): for item in self.items: item.update_point_total() def __repr__(self): return str(vars(self)) def main(): a = MyObject(Point(1,1)) b = MyObject(Point(2,2)) c = MyObject(Point(5,5)) d = MyObject(Point(10,10)) a.add(b) c.add(d) a.add(c) print(a.point_total) print(b.point_total) print(c.point_total) print(d.point_total) b.point.x = 5 c.point.y += 3 print() print(a.point_total) print(b.point_total) print(c.point_total) print(d.point_total) main()Is there an easier or better way to tackle this ? RE: Class object instance. Link instance attribute to class. Can it be done easier. - ichabod801 - Dec-03-2018 What about subclassing the Rect, and redoing all of it's attributes as standardized properties? RE: Class object instance. Link instance attribute to class. Can it be done easier. - Gribouillis - Dec-03-2018 Windspar Wrote:Is there an easier or better way to tackle this ?Why not use the point member as a private member and define x and y properties in MyObject ?class MyObject: @property def x(self): return self._point.x @x.setter def x(self, value): self._point.x = value self.update_point_total() ... b.x = 5 c.y += 3 RE: Class object instance. Link instance attribute to class. Can it be done easier. - Windspar - Dec-03-2018 @Gribouillis. I would but Point is just an example. I would have to do that for every method that could change it value. class Point: def __init__(self, x, y): self.x = x self.y = y def set(self, x, y): self.x = x self.y = y def move(self, x, y): self.x += x self.y += y # some other propertiesFigure out how to do it with __setattr__ and __getattr__. class LinkObject: def __init__(self, value, callback): self.read_value = value self.callback = callback def __call__(self, value=None): if value is None: return self.read_value self.read_value = value self.callback() def __setattr__(self, instance, value): if instance in ['read_value', 'callback']: super().__setattr__(instance, value) else: setattr(self.read_value, instance, value) self.callback() def __getattr__(self, instance): return getattr(self.read_value, instance) def clear(self): self.read_value = None self.callback = callbackEdit. Fix __call__ RE: Class object instance. Link instance attribute to class. Can it be done easier. - Gribouillis - Dec-03-2018 The solution seems to me way too complicated, but perhaps I don't understand exactly what you want to do. Do you need to call update_point_total() in other situations than when x or y changes?
RE: Class object instance. Link instance attribute to class. Can it be done easier. - Windspar - Dec-03-2018 The read_only/private way. Will not let methods and properties to be use. In these method and properties update would need to be called. I have pygame.Rect like object. That has 7 methods, 4 attributes, and 18 properties that can change data. I like to have access to these method and properties. |