3

How can you emulate assignment operator overloading in Python? For example...

class Example(object):

    name = String()
    age = Integer()

    def __init__(self,myname,myage):
        self.name.value = myname
        self.age.value = myage

Rather than doing self.name.value = name, how can you emulate overloading of the assignment operator so that myname is assigned to self.name.value when you do self.name = myname?

4
  • I ended up creating a metaclass to register the typed attributes (which are all subclasses of the Property class). Then I overloaded the __setattr__ method in the Example (Model) class to type check those attributes registered by the metaclass. See github.com/espeed/bulbs/blob/master/bulbs/model.py Commented Feb 2, 2013 at 6:51
  • Are you using traits? Commented Oct 18, 2013 at 18:30
  • No, I rolled my own Property class github.com/espeed/bulbs/blob/master/bulbs/property.py , which the Model's metaclass uses. See the Bulbs Model API docs bulbflow.com/docs/api/bulbs/model Commented Nov 18, 2013 at 18:13
  • Check out Enthought's traits library. (It has stuff like this, with more support for other stuff). Also, what you need are descriptors. There is an example there about the same. Commented Nov 19, 2013 at 9:45

4 Answers 4

13

In this very special case, in attribute assignment, you can use a descriptor. In fact, I suspect that in the example you are using, Integer and String are actually descriptors.

Aside from using premade descriptors, the easiest way to use descriptors is with property(). here's a brief example:

>>> class Foo(object):
        @property
        def bar(self):
            print 'bar'
            return 'bar'
        @bar.setter
        def bar(self, value):
            print 'bar =', value


>>> afoo = Foo()
>>> afoo.bar
bar
'bar'
>>> afoo.bar = 'baz'
bar = baz
>>> 
Sign up to request clarification or add additional context in comments.

2 Comments

Yes, that might work. I created a class String() with __get__(), __set__(), and a method to_db(); however, when I do name = String(), I can't do self.name.to_db() because it's calling to_db() on the value returned by __get__(), not the object "name". One way to deal with this is to not call self.name.to_db() directly and instead set a flag in instance and create a conditional in __get__() to check for it and call to_db() if it's True, but this seems kludgy. Is there a better way?
If you want to be able to do self.attr1.attr2, you probably don't want a descriptor for attr1. For one thing, you generally don't have one descriptor per instance, you have one per class, so you'll have to go to a lot of trouble getting per instance information. Descriptors mostly serve to hide implementation details like database persistence. Instead, you should implement the full functionality in terms of the descriptor special method names, and possibly a metaclass on the parent.
2

You cannot overload the assignment operator in python however with some clever overloading of magic methods you can get to A <<= B+C by overloading the rshift magic method, for a comprehensive guide on pythons magic methods see this.

Comments

0

You can't overload assignment. It's not an operator. You would be better off here just constructing the value in the object constructor.

class Example(object):

    def __init__(self,myname, myage):
        self.name = String(myname)
        self.age = Integer(myage)

However in this case I don't see why you can't just use the built-in str and int.

Comments

0

I ended up creating a Model metaclass called ModelMeta that registers the typed attributes.

See http://github.com/espeed/bulbs/blob/master/bulbs/model.py

In this case, the typed attributes are graph-database "properties", which are all subclasses of the Property class.

See https://github.com/espeed/bulbs/blob/master/bulbs/property.py

Here's an example Model declaration:

# people.py

from bulbs.model import Node, Relationship
from bulbs.property import String, Integer, DateTime
from bulbs.utils import current_datetime

class Person(Node):

    element_type = "person"

    name = String(nullable=False)
    age = Integer()


class Knows(Relationship):

    label = "knows"

    created = DateTime(default=current_datetime, nullable=False)

Example usage:

>>> from people import Person
>>> from bulbs.neo4jserver import Graph
>>> g = Graph()

# Add a "people" proxy to the Graph object for the Person model:
>>> g.add_proxy("people", Person)

# Use it to create a Person node, which also saves it in the database:
>>> james = g.people.create(name="James")
>>> james.eid
3
>>> james.name
'James'

# Get the node (again) from the database by its element ID:
>>> james = g.people.get(james.eid)

# Update the node and save it in the database:
>>> james.age = 34
>>> james.save()

# Lookup people using the Person model's primary index:
>>> nodes = g.people.index.lookup(name="James")

See...

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.