Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Built-in non-data version of property?

Tags:

python

class Books():
    def __init__(self):
        self.__dict__['referTable'] = 1

    @property
    def referTable(self):
        return 2

book = Books()
print(book.referTable)
print(book.__dict__['referTable'])

Running:

vic@ubuntu:~/Desktop$ python3 test.py 
2
1

Books.referTable being a data descriptor is not shadowed by book.__dict__['referTable']:

The property() function is implemented as a data descriptor. Accordingly, instances cannot override the behavior of a property.

To shadow it, instead of property built-in descriptor i must use my own descriptor. Is there a built in descriptor like property but which is non-data?

like image 525
warvariuc Avatar asked Apr 29 '12 17:04

warvariuc


People also ask

What are the available built-in document property names?

The following list shows the available built-in document property names: 1 Title 2 Subject 3 Author 4 Keywords 5 Comments 6 Template 7 Last Author 8 Revision Number 9 Application Name 10 Last Print Date More items...

What does builtindocumentproperties return in Excel?

Workbook.BuiltinDocumentProperties property (Excel) Returns a DocumentProperties collection that represents all the built-in document properties for the specified workbook.

How do I return a collection of built-in document properties?

This property returns the entire collection of built-in document properties. Use the Item method to return a single member of the collection (a DocumentProperty object) by specifying either the name of the property or the collection index (as a number). You can refer to document properties either by index value or by name.

How is property () implemented in Python in terms of descriptor protocol?

To see how property () is implemented in terms of the descriptor protocol, here is a pure Python equivalent: The property () builtin helps whenever a user interface has granted attribute access and then subsequent changes require the intervention of a method.


2 Answers

To expand on my comment, why not simply something like this:

>>> class Books():
...     def __init__(self):
...         self.__dict__['referTable'] = 1
...     @property
...     def referTable(self):
...         try:
...             return self.__dict__['referTable']
...         except KeyError:
...             return 2
... 
>>> a = Books()
>>> a.referTable
1
>>> del a.__dict__['referTable']
>>> a.referTable
2

Now, I'd like to note that I don't think this is good design, and you'd be much better off using a private variable rather than accessing __dict__ directly. E.g:

class Books():
    def __init__(self):
        self._referTable = 1

    @property
    def referTable(self):
        return self._referTable if self._referTable else 2

In short, the answer is no, there is no alternative to property() that works in the way you want in the Python standard library.

like image 149
Gareth Latty Avatar answered Sep 23 '22 12:09

Gareth Latty


There is something very similar to a built-in non-data descriptor -- the class attribute:

class Books():

    referTable = 'default'

    def __init__(self, referTable=None):
        if referTable is not None:
            self.referTable = referTable


book = Books()
print(book.referTable)
# default
book.referTable = 'something specific'
print(book.referTable)
# something specific

If you need something more like a property (for example, you want a function to do some heavy-lifting the first time, but then use that first value for all future references), then you will need to build it yourself:

class OneTime(object):

    def __init__(self, method):
        self.name = method.__name__
        self.method = method

    def __get__(self, inst, cls):
        if inst is None:
            return self
        result = self.method(inst)
        inst.__dict__[self.name] = result
        return result

class Books(object):

    @OneTime
    def referTable(self):
        print 'calculating'
        return 1 * 2 * 3 * 4 * 5

b = Books()
print b.__dict__
print b.referTable
print b.__dict__
print b.referTable

With the following results:

{}
calculating
120
{'referTable': 120}
120
like image 35
Ethan Furman Avatar answered Sep 22 '22 12:09

Ethan Furman