Correct practice for Python properties that depend on other attributes When a property is essentially a boolean value for whether or not an attribute exists or is set a certain way, is it more appropriate to create an object that does not list the option attribute in its __init__() call, or is it better to simply create the object with the 'falsiest' version of that attribute?

Consider the following class:

class RectLikeObj(object):
    def __init__(self, x, y, w, h, pinned=None):
        self.x = x
        self.y = y
        self.w = w
        self.h = h
        self.pinned = pinned or ()

    ###series of property getter/setters for attributes that are
    ###derived from the above
    @property
    def topleft(self):
        return (self.x, self.y)

    @topleft.setter
    def topleft(self, value):
        self.x, self.y = value

    ###and so on for all corners and center, etc

    @property
    def is_pinned(self):
        if not self.pinned:
            return False
        return True

    def pin_corner(self, corner, xy):
        self.pinned = (corner, xy)


Alternatively the object may not ever have the self.pinned attribute and the property is instead looking for the attribute.

class RectLikeObj(object):
    def __init__(self, x, y, h, w):
        self.x = x
        self.y = y
        self.w = w
        self.h = h

    ###same getters/setters as above

    @property
    def is_pinned(self):
        if getattr(self, 'pinned', False):
            return True
        return False

    def pin_corner(self, corner, xy):
        self.pinned = (corner, xy)


Now it could be done to use a try/except, only there's nothing exceptional about this behavior; it's quite binary, either the Rect object is pinned to a particular corner and xy coordinates or it isn't. So I don't know that using eafp is the most correct choice here.

Is it better to use a 'falsy' attribute such as self.pinned = () in the __init__() method, or is it better to leave it to be set later by the self.pin_corner() method and then use the property to check for its existence?
I vote the first method (with the change of having () as the default argument instead of None, because it's simpler).

If you don't absolutely need code introspection, don't use it. In my mind it's more cluttered and risks confusing editors such as PyCharm, as well as human beings, about the composition of a class. To take this idea a little further, there's no need for "pinned" to accept a tuple in the constructor. Give it the same contract as pin_corner; that is, accept both arguments and default them both to None. There's less validation required - when accepting a tuple you would need to check its length as well as the validity of its members.