Reputation: 977
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?
Upvotes: 29
Views: 42948
Reputation: 1
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"
The property method is basically similar to property decoration, it tells python to define a property.
And then we assign this to "bar" property of the type. This needs to be at the type level because you are defining the property for the class, so it is static, not a specific instance.
get_bar is your usual getter where you use the decorator.
Upvotes: 0
Reputation: 38432
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.
Upvotes: 0
Reputation: 447
The object is not instantiated.
class Foo(object):
def get_bar(self):
return "bar"
bar = Foo()
print(bar.get_bar)
Upvotes: 9
Reputation: 122024
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.
Upvotes: 23
Reputation: 1861
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
.
Upvotes: 7
Reputation: 239473
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
Upvotes: 8