Python property returning property object
Question:
I have a class like this:
class Foo(object):
def __init__(self):
self.bar = property(self.get_bar)
def get_bar(self):
return "bar"
print Foo().bar #this prints <property object at 0x0051CB40>
I’ve seen How do Python properties work?, How to set a python property in __init__, but they all use the decorator method, which i don’t because i want a different name. And I need access to self
How do i get the property to behave?
Answers:
You can do it like this
class Foo(object):
def __init__(self):
self.__bar = None
def get_bar(self):
return self.__bar
def set_bar(self, value):
self.__bar = value
bar = property(get_bar, set_bar)
foo = Foo()
print foo.bar # None
foo.bar = 1
print foo.bar # 1
You need to make a minor change:
class Foo(object):
def get_bar(self):
return "bar"
bar = property(get_bar)
print Foo().bar # prints bar
The property needs to be an attribute of the class, not the instance; that’s how the descriptor protocol works.
You can also do it like shown here:
class Foo(object):
def __init__(self):
self._bar = None
@property
def bar(self):
return self._bar
@bar.setter
def bar(self, value):
self._bar = value
@bar.deleter
def bar(self):
self._bar = None # for instance
which is equivalent to:
class Also_Foo(object):
def __init__(self):
self._bar = None
def get_bar(self):
return self._bar
def set_bar(self, value):
self._bar = value
def del_bar(self):
self._bar = None # for instance
bar = property(fget=get_bar, fset=set_bar, fdel=del_bar, doc=None)
BUT without polluting the class namespace with get
and set
methods for each attribute.
You retain external direct access to the variable by using ._bar
instead of .bar
.
The object is not instantiated.
class Foo(object):
def get_bar(self):
return "bar"
bar = Foo()
print(bar.get_bar)
My use case required defining bar
as a property only under certain conditions, so I took jonrsharpe‘s advice and moved the definition into __new__
instead:
class Foo(object):
def __new__(cls):
cls.bar = property(cls.get_bar)
return super(Foo, cls).__new__(cls)
def get_bar(self):
return "bar"
print(Foo().bar) #this prints "bar"
However, nothing was gained by this "cleverness". Once the condition was met, the class contained the property. I might as well have defined it as jonrsharpe did.
Do the following if you want to do within init()
class Foo(object):
def __init__(self):
type(self).bar = property(self.get_bar)
def get_bar(self):
return "bar"
I have a class like this:
class Foo(object):
def __init__(self):
self.bar = property(self.get_bar)
def get_bar(self):
return "bar"
print Foo().bar #this prints <property object at 0x0051CB40>
I’ve seen How do Python properties work?, How to set a python property in __init__, but they all use the decorator method, which i don’t because i want a different name. And I need access to self
How do i get the property to behave?
You can do it like this
class Foo(object):
def __init__(self):
self.__bar = None
def get_bar(self):
return self.__bar
def set_bar(self, value):
self.__bar = value
bar = property(get_bar, set_bar)
foo = Foo()
print foo.bar # None
foo.bar = 1
print foo.bar # 1
You need to make a minor change:
class Foo(object):
def get_bar(self):
return "bar"
bar = property(get_bar)
print Foo().bar # prints bar
The property needs to be an attribute of the class, not the instance; that’s how the descriptor protocol works.
You can also do it like shown here:
class Foo(object):
def __init__(self):
self._bar = None
@property
def bar(self):
return self._bar
@bar.setter
def bar(self, value):
self._bar = value
@bar.deleter
def bar(self):
self._bar = None # for instance
which is equivalent to:
class Also_Foo(object):
def __init__(self):
self._bar = None
def get_bar(self):
return self._bar
def set_bar(self, value):
self._bar = value
def del_bar(self):
self._bar = None # for instance
bar = property(fget=get_bar, fset=set_bar, fdel=del_bar, doc=None)
BUT without polluting the class namespace with get
and set
methods for each attribute.
You retain external direct access to the variable by using ._bar
instead of .bar
.
The object is not instantiated.
class Foo(object):
def get_bar(self):
return "bar"
bar = Foo()
print(bar.get_bar)
My use case required defining bar
as a property only under certain conditions, so I took jonrsharpe‘s advice and moved the definition into __new__
instead:
class Foo(object):
def __new__(cls):
cls.bar = property(cls.get_bar)
return super(Foo, cls).__new__(cls)
def get_bar(self):
return "bar"
print(Foo().bar) #this prints "bar"
However, nothing was gained by this "cleverness". Once the condition was met, the class contained the property. I might as well have defined it as jonrsharpe did.
Do the following if you want to do within init()
class Foo(object):
def __init__(self):
type(self).bar = property(self.get_bar)
def get_bar(self):
return "bar"