0

So I've looked around and read many postings covering the TypeError: message, where it "takes exactly X arguments but only 1 is given".

I know about self. I don't think I have an issue understanding self. Regardless, I was trying to to create a class with some properties and as long as I have @property in front of my function hwaddr, I get the following error:

Traceback (most recent call last):
  File line 24, in <module>
    db.hwaddr("aaa", "bbbb")
TypeError: hwaddr() takes exactly 3 arguments (1 given)

Here is the code. Why is @property messing me up? I take it out, and the code works as expected:

#!/usr/bin/env python2.7

class Database:
    """An instance of our Mongo systems database"""

    @classmethod
    def __init__(self):
        pass

    @property
    def hwaddr(self, host, interface):

        results = [ host, interface ]
        return results

db = Database()
print db.hwaddr("aaa", "bbbb"

Process finished with exit code 1

With it gone, the output is:

File
['aaa', 'bbbb']

Process finished with exit code 0
Mike S
  • 1,065
  • 11
  • 16

2 Answers2

2

Properties are used as syntactical sugar getters. So they expect that you only pass self. It would basically shorten:

print db.hwaddr()

to:

print db.hwaddr

There is no need to use a property here as you pass two arguments in.

Dair
  • 14,712
  • 7
  • 54
  • 91
  • Yes, I see now. Thanks. I will accept this answer. My confusion was in the purpose of a getter. Here, I wasn't getting an object variable... nor was I in the real code that I'm writing. – Mike S Oct 14 '15 at 21:41
1

Basically, what Dair said: properties don't take parameters, that's what methods are for.

Typically, you will want to use properties in the following scenarios:

  • To provide read-only access to an internal attribute
  • To implement a calculated field
  • To provide read/write access to an attribute, but control what happens when it is set

So the question would be, what does hwaddr do, and does it match any of those use cases? And what exactly are host and interface? What I think you want to do is this:

#!/usr/bin/env python2.7

class Database:
    """An instance of our Mongo systems database"""

    def __init__(self, host, interface):
        self._host = host
        self._interface = interface

    @property
    def host(self):
        return self._host

    @property
    def interface(self):
        return self._interface

    @property
    def hwaddr(self):
        return self._host, self._interface

db = Database("my_host", "my_interface")
print db.host
print db.interface
print db.hwaddr

Here, your Database class will have host and interface read-only properties, that can only be set when instantiating the class. A third property, hwaddr, will produce a tuple with the database full address, which may be convenient in some cases.

Also, note that I removed the classmethod decorator in init; constructors should be instance methods.

Marti Congost
  • 206
  • 1
  • 9
  • Thanks for the reply; very helpful. *host* is a string, and *interface* is a dict with a number of dict's in it; each key is a string and each value is a dict (example: "management" for the eth0 interface). Each of THOSE dicts has key/value pairs of string/string; keys include "hwaddr", "ip", and "defaultgw". So hwaddr can be modified dynamically if we change network cards for a particular interface name on a host. It does not meet the criteria of a property. – Mike S Oct 15 '15 at 13:49
  • Regarding the `classmethod` decorator: it makes sense not to have it for _init__. The reason I put it there was because there will always be only 1 instance of the Database class in my script. Not seen in my example are *host, port, user,* and *password* variables for the database (forgetting the security implications for the moment). In `__init__`, I set up the connection based on those values. How would you construct a class then with 1 and only 1 instance? (Maybe I don't care, because there is no technical limitation that restricts me to only 1 connection to the database...?) – Mike S Oct 15 '15 at 13:58
  • The singleton pattern is frowned uppon by many. But if you want to implement it, you can find lots of discussion and examples on the best ways to do it in Python: http://stackoverflow.com/questions/6760685/creating-a-singleton-in-python – Marti Congost Oct 15 '15 at 14:48
  • The link is very helpful too, @Marti Congost. I am comfortable with not implementing the class as a singleton. This is a restriction that, although in practice I will have only 1 instance, does not require me to enforce. So I'll eliminate the added complexity. – Mike S Oct 15 '15 at 15:46