gcq
gcq

Reputation: 977

Python property returning property object

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

Answers (6)

Bora Inceler
Bora Inceler

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

jcomeau_ictx
jcomeau_ictx

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

warchitect
warchitect

Reputation: 447

The object is not instantiated.

class Foo(object):
  def get_bar(self):
    return "bar"

bar = Foo()
print(bar.get_bar)

Upvotes: 9

jonrsharpe
jonrsharpe

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

berna1111
berna1111

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

thefourtheye
thefourtheye

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

Related Questions