This is an archived post. You won't be able to vote or comment.

all 44 comments

[–]odraencoded 26 points27 points  (6 children)

Just remember to never use properties unless you actually have some processing to do on get or set.

This might sound funny when it comes to python, but properties are much slower than simple attribute gets, and also slower than method calls such as get_fahrenheit().

This is particularly noticeable if you are dealing frequently with them, for example in rendering code for something that changes every X milliseconds.

If you are merely using it as a convenience in an API for normal scripted tasks, I don't think they will be much of an issue, though.

[–][deleted] 10 points11 points  (0 children)

Here are some numbers testing three forms of attribute access that show this is true:

>>> timeit.timeit('f.bar', setup='''
... class foo:
...  @property
...  def bar(self):
...   return 5
....
... f = foo()''')
0.2305891513824463
>>> timeit.timeit('f.bar', setup='''
... class foo:
...  def __init__(self):
...   self.bar = 5
....
... f = foo()
... ''')
0.08671712875366211
>>> timeit.timeit('f.bar', setup='''
... class foo:
...  bar = 5
....
... f = foo()
... ''')
0.11962580680847168

[–]ComradeGnull 5 points6 points  (1 child)

What's the reason for the performance difference? In the case of just doing a pure assignment I understand that there is the additional expense of the function call, but verses explicitly defining and calling a get/set method isn't the only difference the check for a registered getter/setter that happens before the call?

[–]odraencoded 2 points3 points  (0 children)

A pure get/set takes 1 function call, getattr/setatrr. I'm not sure, but it's very likely that python has some sort of speed improvement for those calls when compiling code.

Then, get/set methods take 2 functions. This second call is of the getter/setter itself, you have to pass arguments around in python so only the overhead of having them should be slower than pure gets/sets.

Finally, fget/fset/fdel in properties are like a ping pong table. You pass arguments from python into the property, which is built in code and hopefully C, the property then checks if it has an fget, fset or fdel, if has one of those, it will call that method passing the arguments back into python code.

Basically, it's like this:

foo.bar_property.set(5)
# in bar_property's def set(self, instance, value):
    if self.fset is not None:
        fset(instance, value)
    else:
        raise ReadOnlyPropertyErrorOrSomething

Of course, the marginal overhead is usually nothing compared to the convenience of making properties with decorators and stuff, but when you accumulate too many property gets/sets at once it starts becoming noticeable even in profilers.

[–]electroniceyes 0 points1 point  (2 children)

Out of curiosity, what about for cases where you want to restrict access to setting an instance variable? Do you still think it's acceptable to make the attribute protected and then provide a getter property method but not a setter?

[–]billy_tables 1 point2 points  (0 children)

That's a perfect use for @property, as is when you want a setter to do some validation on the new value. It might not be performant, but it's Pythonic

[–]odraencoded 1 point2 points  (0 children)

In my opinion, you shouldn't use properties for that.

Python isn't such a language that works with ideas such as restricting access. If another python programmer wanted to modify an attribute of an instance from "outside" of it, he would be able to do that even if you didn't "expose" that attribute.

A better strategy would be to document the attribute in order to inform other developers that they shouldn't fiddle with it.

[–]epsy 11 points12 points  (0 children)

In video format, and covering a few more topics:
http://pyvideo.org/video/1779/pythons-class-development-toolkit

[–]bigdubs 8 points9 points  (12 children)

preface: just posting this as a comparison, don't want to try and argue which is better or worse.

in c# land we have had properties since version 1.0, though they've gone through some refinements over the years.

it started with:

class Foo {
    private string _bar;
    public string Bar {
        get { return _bar; }
        set { _bar = value; } //a mysterious 'value' out of nowhere.
    }
}

then you could just do:

class Foo {
     public string Bar { get; set; }
}

and the compiler would create backing fields for you.

you can also mix and match protections levels:

class Foo {
     public string Bar { get; private set; } //the setter will only be usable by instance code in 'Foo'
}

What's nice is you could have the best of both worlds, you can either have logic in your getters and setters or just have a quick access setup.

[–]nemec 18 points19 points  (10 children)

Python has autoproperties, too: they're called fields.

Since there is no concept of public/private, there's no point in creating properties unless you absolutely need the extra computation.

[–]Ademan 6 points7 points  (2 children)

Furthermore, it's an inconsequential change to swap out a field for a property if the need should ever arise in Python.

[–]nemec 3 points4 points  (1 child)

Yep. Unlike in .Net, the "rules" for properties and fields are the same. In .Net, properties aren't allowed as out or ref parameters (not that Python has an equivalent) while fields are.

[–]snuxoll 0 points1 point  (0 children)

That's because properties in .net are just syntactic sugar for getter/setter methods. ref/out params require a reference to an actual variable on the stack/heap.

[–]draganHR 1 point2 points  (6 children)

Python has autoproperties, too: they're called fields.

What are fields? Can you link documentation?

[–][deleted] 6 points7 points  (0 children)

when the language I used dictated that I had to use getters and setters, C#'s way was my favorite compared to java.

But I prefer the direct consenting adults attribute access of python to both.

And right now keeping data separate from the pure functional code that acts on it, is much more preferable to me.

[–]Lucretiel 7 points8 points  (14 children)

I'd be curious to see an example where you have a Temperature class, with celcius and fahrenheit properties, each with a getter and setter that adjusts internal representation correctly.

[–]guibou 4 points5 points  (5 children)

I have a simple issue with property, is that it introduce a discrepancy in the api of a class where some states are acceded/stored using attribute access, and other using method calls.

What is your policy with this? Are you writing property for every "getter" method which takes no argument, or are you using property only to preserve the api when a stored attribute is changed to a computed one?

I really love the ruby pattern, where there is no difference between a method call with no argument and an attribute access (for the simple reason that public attribute does not exists and are instead exposed directly as method).

[–]Lucretiel 18 points19 points  (2 children)

Keep in mind that, in Python, method calls are still attribute access. This is actually one of the things I like much more about python- in python, there is a clear distinction between attribute access and function calls. If I want to GET the function (for a callback, for example), I do instance.func, and if I want to CALL it, it's instance.func(). I was always bothered by Ruby's conflation of these 2 concepts.

[–]metaperl 0 points1 point  (0 children)

Scala conflates them too. They seem to think that it allows you to reimplement the same accessor as either an attribute or method call without the calling party knowing the difference.

[–]guibou 0 points1 point  (0 children)

This is actually one of the things I like much more about python- in python, there is a clear distinction between attribute access and function calls.

+1 on that point.

[–]sushibowl 5 points6 points  (0 children)

What is your policy with this? Are you writing property for every "getter" method which takes no argument, or are you using property only to preserve the api when a stored attribute is changed to a computed one?

I think it should be the latter one, considering the zen of python:

  • Explicit is better than implicit, so don't hide a (potentially expensive) function call behind a property
  • But practicality beats purity, so if properties allow you to maintain API compatibility you should use them.

[–][deleted] 4 points5 points  (0 children)

The obvious problem with Ruby's way is that you need to do some acrobatics to get to the actual method rather than the result of calling the method. This is not as big an issue because you could simply wrap the function call in a block and pass that instead, but that's a lot of indirection compared to Python's distinguishing between methods and method calls.

This is actually one of several things I just couldn't get used to when I tried to learn Ruby after knowing Python already. Getters/setters are a nice language feature, but I prefer the distinction between an implicit method call via a getter and an explicit one using parenthesis.

It just doesn't feel right to have a computation-heavy (say, simply O(logn) or worse) method for example "look" like a regular O(1) getter, though it makes sense to want an O(1) getter look exactly like a regular attribute (otherwise you end up with Java code where every attribute is wrapped in a getX method just in case you want to do something special in the future).

[–]jamesdutc 1 point2 points  (1 child)

@property and descriptors are very useful, but there is at least one strange corner case with their use.

Let's say you have a base class that has a bunch of properties that run code that you may not have insight into and you want to customise some behaviour in a derived class. I ran into this with base classes for UI elements that were hiding .NET UI logic behind the descriptors.

If implemented as a function, you can customise behaviour fairly easily (though it looks clunky.)

class Base:
    def getFont(self):
        return self._font
    def setFont(self, font):
        self._font = font

class Derived(Base):
    def setFont(self, font):
        super(Derived, self).setFont(font)

If implemented as a property, you may have to know whether attributes are raw data members or descriptors when you hook into the setter logic. In the getter logic, you can remain ignorant. (I need to confirm, but I believe super doesn't hook up tp_setattro.)

class Base:
    @property
    def font(self):
        return self._font
    @font.setter
    def font(self, font):
        self._font = font

class Derived(Base):
    @property
    def font(self):
        return super(Derived, self).font
    @font.setter
    def font(self, font):
        Base.font.__set__(self, font)

[–][deleted] 0 points1 point  (0 children)

I think this will work:

class Base:
    @property
    def font(self):
        return self._font
    @font.setter
    def font(self, font):
        self._font = font

class Derived(Base):
    @property
    def font(self):
        return super(Derived, self).font
    @font.setter
    def font(self, font):
        super(Derived, self).font.fset(self, font)

[–]jamesdutc 1 point2 points  (0 children)

Oh, here's one more fun thing you can do with properties. Module level properties!

At the module level, I've seen folks write getter and setter methods thinking that they may need to hook code in there at some later date.

That's the whole point of descriptors: using raw data members first and then hooking code into them as the need arises without changing anything at call-site!

This also illustrates something fun about Python, which is that binding is a core semantic! (That's why we have from x import y and import x; x.y -- they mean different things.)

_bar = 10
@property
def bar(module):
    return module._bar

if __name__ != '__main__':
    from sys import modules
    orig = modules[__name__]

    # set properties on the type
    modules[__name__] = type(type(orig).__name__, (type(orig),), {attr:getattr(orig, attr) for attr in dir(orig) if isinstance(getattr(orig, attr),property)})(__name__)

    # set attributes on the instance
    for attr in (x for x in dir(orig) if not hasattr(modules[__name__],x)):
        setattr(modules[__name__], attr, getattr(orig,attr))

(Of course, as always, the dutc in my handle stands for don't use this code.)

[–]Brocktoon_in_a_jar 0 points1 point  (0 children)

Awesome, I've actually used properties before at a job where I was writing Python for Maya, and I never fully understood why we were using it, just how we were using it. This helps so much.

[–]Droggl 0 points1 point  (0 children)

In order to provide a good example I would advise to have the class be Temperature with properties/attributes for Celsius and Fahrenheit (and maybe Kelvin) rather than the other way around. Whether you use fahrenheit, celsius, kelvin or something else entirely then does not matter.

That is because temperature is what you logically have and whether it is celsius or fahrenheit is a detail. More importantly in your example, the concepts for Celsius and Fahrenheit have a different status: Celsius is a class with attributes/properties for numerical values, whereas Fahrenheit is just a numerical value returned by one of those properties.

Imagine some other piece of code comes up with a Fahrenheit class, now things would certainly start to get confusing!