Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AttributeError: 'property' object has no attribute

Python (2.6) seems to be derping for no reason, can anyone see a problem with this code?

class DB ():
    def doSomething (self, str):
        print str

class A ():
    __db = DB()

    @staticmethod
    def getDB ():
        return A.__db

    db = property(getDB)


A.db.doSomething("blah")

Fails with the exception:

AttributeError: 'property' object has no attribute 'doSomething'

It was my understanding that a property would automatically run its getter when accessed, so why is it complaining about a property object, and why isn't it finding my clearly available method?

like image 694
Ben Avatar asked Dec 13 '12 19:12

Ben


People also ask

What is a property object Python?

The property() method in Python provides an interface to instance attributes. It encapsulates instance attributes and provides a property, same as Java and C#. The property() method takes the get, set and delete methods as arguments and returns an object of the property class.

How do you print a property object in Python?

Use Python's dir to Print an Object's Attributes One of the easiest ways to access a Python object's attributes is the dir() function. This function is built-in directly into Python, so there's no need to import any libraries.

How do you create a class property in Python?

The following example shows how to create a Circle class with a handy property to manage its radius: # circle.py class Circle: def __init__(self, radius): self. _radius = radius def _get_radius(self): print("Get radius") return self. _radius def _set_radius(self, value): print("Set radius") self.


2 Answers

In addition to needing to inherit from object, properties only work on instances.

a = A()
a.db.doSomething("blah")

To make a property work on the class, you can define a metaclass. (A class is an instance of a metaclass, so properties defined on the metaclass work on the class, just as properties defined on a class work on an instance of that class.)

like image 65
kindall Avatar answered Oct 07 '22 06:10

kindall


You aren't using classes correctly. A class is (normally) two things:

  1. A factory for creating a family of related objects
  2. A definition of the common behaviour of those objects

These related objects are the instances of the class. Normal methods are invoked on instances of the class, not on the class itself. If you want methods that can be invoked from the class, without an instance, you need to label the methods with @classmethod (or @staticmethod).

However I don't actually know whether properties work when retrieved from a class object. I can't check right now, but I don't think so. The error you are getting is that A.db is retrieving the property object which defines the property itself, it isn't "evaluating" the property to get A.__db. Property objects have no doSomething attribute. Properties are designed to be created in classes as descriptions of how the instances of those classes work.

If you did intend to be working with an instance of A, then you'll need to create one:

my_a = A()
my_a.db.doSomething("blah")

However, this will also fail. You have not correctly written getDB as any kind of method. Normal methods need an argument to represent the instance it was invoked on (traditionally called self):

def getDB(self):
    ...

Static methods don't, but need a decorator to label them as static:

@staticmethod
def getDB():
    ...

Class methods need both an argument to receive the class they were invoked on, and a decorator:

@classmethod
def getDB(cls):
    ...
like image 35
Ben Avatar answered Oct 07 '22 04:10

Ben