Skip to content

Instantly share code, notes, and snippets.

@orbingol
Last active February 22, 2025 17:21
Show Gist options
  • Select an option

  • Save orbingol/ab490b8de1dd80c1b2822a692b87ac3f to your computer and use it in GitHub Desktop.

Select an option

Save orbingol/ab490b8de1dd80c1b2822a692b87ac3f to your computer and use it in GitHub Desktop.

Revisions

  1. orbingol revised this gist Jan 9, 2020. 1 changed file with 61 additions and 34 deletions.
    95 changes: 61 additions & 34 deletions dynamic_attributes.py
    Original file line number Diff line number Diff line change
    @@ -1,54 +1,81 @@
    # Illustrates creating dynamic attributes in Python
    # 'GPSPosition' class contains 'coordinates' and their dynamic 'attributes'
    #
    # For implementation details, please see the following methods:
    # For implementation details of the dynamic attributes, please see the following methods:
    # - GPSPosition.__getattr__
    # - GPSPosition.__setattr__
    #

    class GPSPosition(object):
    __slots__ = ('_coords', '_attribs')
    __slots__ = ('_coords', '_attribs', '_iter_index')

    def __init__(self, coords, **kwargs):
    self._coords = coords
    self._attribs = kwargs.get('attribs', tuple())

    def __str__(self):
    return str(self._coords)

    def __getattr__(self, attr):
    def __repr__(self):
    return self.__str__()

    def __iter__(self):
    self._iter_index = 0
    return self

    def next(self):
    return self.__next__()

    def __next__(self):
    try:
    # Try to get the attribute name from the attribute list
    # 'index' function will return the index of the attribute in the '_attribs' list
    idx = object.__getattribute__(self, '_attribs').index(attr)
    # Since we know the index value, it should be the same in the '_coords' list
    return object.__getattribute__(self, '_coords')[idx]
    except ValueError:
    # 'index' function will throw a 'ValueError' exception if 'attr' is not in the list
    raise AttributeError("'" + self.__class__.__name__ + "' object has no attribute '" + attr + "'")
    except AttributeError:
    return object.__getattribute__(self, attr)
    res = self._coords[self._iter_index]
    except IndexError:
    raise StopIteration
    self._iter_index += 1
    return res

    def __setattr__(self, attr, val):
    def __len__(self):
    return len(self._coords)

    def __reversed__(self):
    return reversed(self._coords)

    def __getitem__(self, key):
    return self._coords[key]

    def __setitem__(self, key, value):
    self._coords[key] = value

    def __getattr__(self, name):
    try:
    # Try to get the attribute name from the attribute list
    # 'index' function will return the index of the attribute in the '_attribs' list
    idx = object.__getattribute__(self, '_attribs').index(attr)
    # Get the '_coords' list
    temp_coords = object.__getattribute__(self, '_coords')
    # Update the '_coords' list
    temp_coords[idx] = val
    # Update the class member in this instance
    object.__setattr__(self, '_coords', temp_coords)
    idx = object.__getattribute__(self, '_attribs').index(name)
    # Since we know the index value, it should be the same in the '_coords' list
    return object.__getattribute__(self, '_coords')[idx]
    except ValueError:
    # 'index' function will throw a 'ValueError' exception if 'attr' is not in the list
    raise AttributeError("'" + self.__class__.__name__ + "' object has no attribute '" + attr + "'")
    raise AttributeError("'" + self.__class__.__name__ + "' object has no attribute '" + name + "'")
    except AttributeError:
    # Check if the 'attr' is in the '__slots__'
    if attr in object.__getattribute__(self, '__slots__'):
    object.__setattr__(self, attr, val)
    else:
    raise AttributeError("'" + self.__class__.__name__ + "' object has no attribute '" + attr + "'")
    return object.__getattribute__(self, name)

    def __setattr__(self, name, value):
    # Check if the 'name' is in the '__slots__'
    if name in object.__getattribute__(self, '__slots__'):
    object.__setattr__(self, name, value)
    else:
    try:
    # Try to get the attribute name from the attribute list
    # 'index' function will return the index of the attribute in the '_attribs' list
    idx = object.__getattribute__(self, '_attribs').index(name)
    # Get the '_coords' list
    temp = object.__getattribute__(self, '_coords')
    # Update the '_coords' list
    temp[idx] = value
    # Update the class member in this instance
    object.__setattr__(self, '_coords', temp)
    except ValueError:
    # 'index' function will throw a 'ValueError' exception if 'name' is not in the list
    raise AttributeError("'" + self.__class__.__name__ + "' object has no attribute '" + name + "'")

    @property
    def coordinates(self):
    @@ -58,7 +85,7 @@ def coordinates(self):
    def coordinates(self, val):
    if not isinstance(val, (list, tuple)):
    raise TypeError("Input for 'coordinates' should be a list or tuple")
    self._coords = list(val)
    self._coords = list(val)

    @property
    def attributes(self):
    @@ -75,7 +102,7 @@ def attributes(self, val):
    if __name__ == '__main__':
    # Create a 3-D GPSPosition instance and set the coordinates & attributes
    pos1 = GPSPosition([10, 21, 32], attribs=['x', 'y', 'z'])

    # Print 'position'
    print('pos1:', pos1)

    @@ -90,7 +117,7 @@ def attributes(self, val):

    # Create a 4-D GPSPosition instance and set the coordinates & attributes
    pos2 = GPSPosition([11, 13, 17, 19], attribs=['x', 'y', 'z', 'w'])

    # Print 'position'
    print('pos2:', pos2)

    @@ -106,7 +133,7 @@ def attributes(self, val):

    # Create a 2-D GPSPosition instance and set the coordinates & attributes
    pos3 = GPSPosition([100, 200], attribs=['u', 'v'])

    # Print 'position'
    print('pos3:', pos3)

    @@ -122,6 +149,6 @@ def attributes(self, val):

    # Create a 2-D GPSPosition instance without the attributes
    pos4 = GPSPosition([36, 42])

    # Print 'position'
    print('pos4:', pos4)
  2. orbingol revised this gist Jan 9, 2020. 1 changed file with 7 additions and 1 deletion.
    8 changes: 7 additions & 1 deletion dynamic_attributes.py
    Original file line number Diff line number Diff line change
    @@ -104,7 +104,7 @@ def attributes(self, val):
    pos2.w = 23
    print('updated w:', pos2.w) # will print 23

    # Create 2-D GPSPosition instance and set the coordinates & attributes
    # Create a 2-D GPSPosition instance and set the coordinates & attributes
    pos3 = GPSPosition([100, 200], attribs=['u', 'v'])

    # Print 'position'
    @@ -119,3 +119,9 @@ def attributes(self, val):
    pos3.v = 250
    print('updated u:', pos3.u) # will print 150
    print('updated v:', pos3.v) # will print 250

    # Create a 2-D GPSPosition instance without the attributes
    pos4 = GPSPosition([36, 42])

    # Print 'position'
    print('pos4:', pos4)
  3. orbingol revised this gist Jan 9, 2020. 1 changed file with 56 additions and 36 deletions.
    92 changes: 56 additions & 36 deletions dynamic_attributes.py
    Original file line number Diff line number Diff line change
    @@ -1,39 +1,26 @@
    # Illustrates how to dynamically create attributes on Python
    #
    # GPSPosition holds coordinates and dynamic attributes assigned to those coordinates
    # GPSData holds the GPSPosition object (not necessary for the dynamic attributes)
    # Illustrates creating dynamic attributes in Python
    # 'GPSPosition' class contains 'coordinates' and their dynamic 'attributes'
    #
    # For implementation details, please see the following methods:
    # - GPSPosition.__getattr__
    # - GPSPosition.__setattr__
    #

    class GPSData(object):
    __slots__ = ('_position',)

    def __init__(self, pos):
    self._position = pos

    @property
    def position(self):
    return self._position


    class GPSPosition(object):
    __slots__ = ('_coords', '_coord_attribs')
    __slots__ = ('_coords', '_attribs')

    def __init__(self, coords, **kwargs):
    self._coords = coords
    self._coord_attribs = kwargs.get('attribs', list())
    self._attribs = kwargs.get('attribs', tuple())

    def __str__(self):
    return str(self._coords)

    def __getattr__(self, attr):
    try:
    # Try to get the attribute name from the attribute list
    # 'index' function will return the index of the attribute in the '_coord_attribs' list
    idx = object.__getattribute__(self, '_coord_attribs').index(attr)
    # 'index' function will return the index of the attribute in the '_attribs' list
    idx = object.__getattribute__(self, '_attribs').index(attr)
    # Since we know the index value, it should be the same in the '_coords' list
    return object.__getattribute__(self, '_coords')[idx]
    except ValueError:
    @@ -45,8 +32,8 @@ def __getattr__(self, attr):
    def __setattr__(self, attr, val):
    try:
    # Try to get the attribute name from the attribute list
    # 'index' function will return the index of the attribute in the '_coord_attribs' list
    idx = object.__getattribute__(self, '_coord_attribs').index(attr)
    # 'index' function will return the index of the attribute in the '_attribs' list
    idx = object.__getattribute__(self, '_attribs').index(attr)
    # Get the '_coords' list
    temp_coords = object.__getattribute__(self, '_coords')
    # Update the '_coords' list
    @@ -64,38 +51,71 @@ def __setattr__(self, attr, val):
    raise AttributeError("'" + self.__class__.__name__ + "' object has no attribute '" + attr + "'")

    @property
    def coords(self):
    def coordinates(self):
    return self._coords

    @coords.setter
    def coords(self, val):
    self._coords = val
    @coordinates.setter
    def coordinates(self, val):
    if not isinstance(val, (list, tuple)):
    raise TypeError("Input for 'coordinates' should be a list or tuple")
    self._coords = list(val)

    @property
    def attributes(self):
    return self._coord_attribs
    return self._attribs

    @attributes.setter
    def attributes(self, val):
    self._coord_attribs = val
    if not isinstance(val, (list, tuple)):
    raise TypeError("Input for 'attributes' should be a list or tuple")
    self._attribs = tuple(val)


    # Example run
    if __name__ == '__main__':
    # Create a GPSPosition instance and set the coordinates & attributes
    # Create a 3-D GPSPosition instance and set the coordinates & attributes
    pos1 = GPSPosition([10, 21, 32], attribs=['x', 'y', 'z'])

    # Print 'position'
    print('pos1:', pos1)

    # Get dynamic properties
    print('x:', pos1.x) # will print 10
    print('y:', pos1.y) # will print 21
    print('z:', pos1.z) # will print 32

    # Set dynamic properties
    pos1.x = 12
    print('updated x:', pos1.x) # will print 12

    # Create a 4-D GPSPosition instance and set the coordinates & attributes
    pos2 = GPSPosition([11, 13, 17, 19], attribs=['x', 'y', 'z', 'w'])

    # Print 'position'
    print('pos2:', pos2)

    # Get dynamic properties
    print('x:', pos2.x) # will print 11
    print('y:', pos2.y) # will print 13
    print('z:', pos2.z) # will print 17
    print('w:', pos2.w) # will print 19

    # Set dynamic properties
    pos2.w = 23
    print('updated w:', pos2.w) # will print 23

    # Create a GPSData instance
    data1 = GPSData(pos1)
    # Create 2-D GPSPosition instance and set the coordinates & attributes
    pos3 = GPSPosition([100, 200], attribs=['u', 'v'])

    # Print 'position'
    print(data1.position)
    print('pos3:', pos3)

    # Get dynamic properties
    print(data1.position.x) # will print 10
    print(data1.position.y) # will print 21
    print(data1.position.z) # will print 32
    print('u:', pos3.u) # will print 100
    print('v:', pos3.v) # will print 200

    # Set dynamic properties
    data1.position.x = 12
    print(data1.position.x) # will print 12
    pos3.u = 150
    pos3.v = 250
    print('updated u:', pos3.u) # will print 150
    print('updated v:', pos3.v) # will print 250
  4. orbingol revised this gist Jan 9, 2020. No changes.
  5. orbingol revised this gist Jan 9, 2020. 1 changed file with 51 additions and 17 deletions.
    68 changes: 51 additions & 17 deletions dynamic_attributes.py
    Original file line number Diff line number Diff line change
    @@ -1,7 +1,11 @@
    # Illustrates how to dynamically create attributes on Python
    #
    # GPSPosition holds coordinates and dynamic attributes assigned to those coordinates
    # GPSData holds the GPSPosition object
    # GPSData holds the GPSPosition object (not necessary for the dynamic attributes)
    #
    # For implementation details, please see the following methods:
    # - GPSPosition.__getattr__
    # - GPSPosition.__setattr__
    #

    class GPSData(object):
    @@ -18,21 +22,46 @@ def position(self):
    class GPSPosition(object):
    __slots__ = ('_coords', '_coord_attribs')

    def __init__(self):
    self._coords = []
    self._coord_attribs = []
    def __init__(self, coords, **kwargs):
    self._coords = coords
    self._coord_attribs = kwargs.get('attribs', list())

    def __str__(self):
    return str(self._coords)

    # This is where we generate the dynamic attributes
    def __getattr__(self, attr):
    if attr in self._coord_attribs:
    try:
    return self._coords[self._coord_attribs.index(attr)]
    except IndexError:
    raise AttributeError(attr)
    if attr not in self.__slots__:
    raise AttributeError(attr)
    return self.__slots__[attr]
    try:
    # Try to get the attribute name from the attribute list
    # 'index' function will return the index of the attribute in the '_coord_attribs' list
    idx = object.__getattribute__(self, '_coord_attribs').index(attr)
    # Since we know the index value, it should be the same in the '_coords' list
    return object.__getattribute__(self, '_coords')[idx]
    except ValueError:
    # 'index' function will throw a 'ValueError' exception if 'attr' is not in the list
    raise AttributeError("'" + self.__class__.__name__ + "' object has no attribute '" + attr + "'")
    except AttributeError:
    return object.__getattribute__(self, attr)

    def __setattr__(self, attr, val):
    try:
    # Try to get the attribute name from the attribute list
    # 'index' function will return the index of the attribute in the '_coord_attribs' list
    idx = object.__getattribute__(self, '_coord_attribs').index(attr)
    # Get the '_coords' list
    temp_coords = object.__getattribute__(self, '_coords')
    # Update the '_coords' list
    temp_coords[idx] = val
    # Update the class member in this instance
    object.__setattr__(self, '_coords', temp_coords)
    except ValueError:
    # 'index' function will throw a 'ValueError' exception if 'attr' is not in the list
    raise AttributeError("'" + self.__class__.__name__ + "' object has no attribute '" + attr + "'")
    except AttributeError:
    # Check if the 'attr' is in the '__slots__'
    if attr in object.__getattribute__(self, '__slots__'):
    object.__setattr__(self, attr, val)
    else:
    raise AttributeError("'" + self.__class__.__name__ + "' object has no attribute '" + attr + "'")

    @property
    def coords(self):
    @@ -54,14 +83,19 @@ def attributes(self, val):
    # Example run
    if __name__ == '__main__':
    # Create a GPSPosition instance and set the coordinates & attributes
    pos1 = GPSPosition()
    pos1.coords = [10, 21, 32]
    pos1.attributes = ['x', 'y', 'z']
    pos1 = GPSPosition([10, 21, 32], attribs=['x', 'y', 'z'])

    # Create a GPSData instance
    data1 = GPSData(pos1)

    # Check dynamic properties
    # Print 'position'
    print(data1.position)

    # Get dynamic properties
    print(data1.position.x) # will print 10
    print(data1.position.y) # will print 21
    print(data1.position.z) # will print 32

    # Set dynamic properties
    data1.position.x = 12
    print(data1.position.x) # will print 12
  6. orbingol created this gist Jan 8, 2020.
    67 changes: 67 additions & 0 deletions dynamic_attributes.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,67 @@
    # Illustrates how to dynamically create attributes on Python
    #
    # GPSPosition holds coordinates and dynamic attributes assigned to those coordinates
    # GPSData holds the GPSPosition object
    #

    class GPSData(object):
    __slots__ = ('_position',)

    def __init__(self, pos):
    self._position = pos

    @property
    def position(self):
    return self._position


    class GPSPosition(object):
    __slots__ = ('_coords', '_coord_attribs')

    def __init__(self):
    self._coords = []
    self._coord_attribs = []

    # This is where we generate the dynamic attributes
    def __getattr__(self, attr):
    if attr in self._coord_attribs:
    try:
    return self._coords[self._coord_attribs.index(attr)]
    except IndexError:
    raise AttributeError(attr)
    if attr not in self.__slots__:
    raise AttributeError(attr)
    return self.__slots__[attr]


    @property
    def coords(self):
    return self._coords

    @coords.setter
    def coords(self, val):
    self._coords = val

    @property
    def attributes(self):
    return self._coord_attribs

    @attributes.setter
    def attributes(self, val):
    self._coord_attribs = val


    # Example run
    if __name__ == '__main__':
    # Create a GPSPosition instance and set the coordinates & attributes
    pos1 = GPSPosition()
    pos1.coords = [10, 21, 32]
    pos1.attributes = ['x', 'y', 'z']

    # Create a GPSData instance
    data1 = GPSData(pos1)

    # Check dynamic properties
    print(data1.position.x) # will print 10
    print(data1.position.y) # will print 21
    print(data1.position.z) # will print 32