1

As I transition from JavaScript to Python, I noticed I haven't figured out a way to add properties to the data type classes. For example, in JavaScript, if I wanted to be able to type arr.last and have it return the last element in the array arr, or type arr.last = 'foo' and to set the last element to 'foo', I would use:

Object.defineProperty(Array.prototype,'last',{
    get:function(){
        return this[this.length-1];
    },
    set:function(val){
        this[this.length-1] = val;
    }
});

var list = ['a','b','c'];
console.log(list.last); // "c"
list.last = 'd';
console.log(list); // ["a","b","d"]

However, in Python, I'm not sure how to do the equivalent of Object.defineProperty(X.prototype,'propname',{get:function(){},set:function(){}});

Note: I am not asking for how to do the specific example function, I am trying to be able to define a property with a get and set onto the primitive data types (str, int, float, list, dict, set, etc.)

Cyoce
  • 253
  • 3
  • 14
  • Perhaps you want to read about the [standard types](https://docs.python.org/3/library/stdtypes.html)? You can do this stuff directly in Python, with no messy bits getting in the way. In other words, in trying to define properties and getters/setters, you probably have an [XY Problem](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). – TigerhawkT3 Sep 04 '15 at 00:51

3 Answers3

4

In Python 21, adding new attributes (aka member objects, including methods) to a new-style class (one that derives from object) is as easy as simply defining them:

class Foo(object):
    def __init__(self):
        self._value = "Bar"

def get_value(self):
    return self._value

def set_value(self, val):
    self._value = val

def del_value(self):
    del self._value

Foo.value = property(get_value, set_value, del_value)
f = Foo()

print f.value
f.value = "Foo"
print f.value

I use the property builtin that Dan D. mentioned in his answer, but this actually assigns the attribute after the class is created, like the question asks.

Online demo

1: in Python 3, it's even simpler, since all classes are new-style classes

Community
  • 1
  • 1
3

See the documentation of the property function. It has examples. The following is the result of print property.__doc__ under Python 2.7.3:

property(fget=None, fset=None, fdel=None, doc=None) -> property attribute

fget is a function to be used for getting an attribute value, and likewise
fset is a function for setting, and fdel a function for del'ing, an
attribute.  Typical use is to define a managed attribute x:
class C(object):
    def getx(self): return self._x
    def setx(self, value): self._x = value
    def delx(self): del self._x
    x = property(getx, setx, delx, "I'm the 'x' property.")

Decorators make defining new properties or modifying existing ones easy:
class C(object):
    @property
    def x(self): return self._x
    @x.setter
    def x(self, value): self._x = value
    @x.deleter
    def x(self): del self._x
Dan D.
  • 73,243
  • 15
  • 104
  • 123
  • This does not add existing functionality at runtime, like OP asked. –  Dec 18 '15 at 01:49
0

If I understood you correctly, you want to edit existing classes (add method) Check out this thread Python: changing methods and attributes at runtime

Community
  • 1
  • 1
Anthony N.
  • 295
  • 3
  • 16
  • I'm not sure if I understand that post correctly, but it appears that that is making a new class that can have its attributes modified, as opposed to what I want (being able to modify the attributes of a class that was defined with Python (e.g. int) – Cyoce Sep 04 '15 at 00:56
  • @Cyoce Not all classes are equal in Python, largely due to performance/implementation considerations. – user2864740 Sep 04 '15 at 00:56