0

Let's say I have classes where I define attributes as getter/setter. Classes are like this one:

class TestClass:
    def __init__(self):
        self.name = "default name"

    @property
    def myname(self):
        self._myname = self.name
        return self._myname

    @myname.setter
    def myname(self, n):
        self._myname = n
        self.name = self._myname

I instance these classes. In this example I instance several times this same class:

a = TestClass()
a.myname = "A"
b = TestClass()
b.myname = "B"

Setting and getting these names requires a certain amount of time.

How can I get in parallel a.myname and b.myname? How can I set in parallel a.myname = "new A" and b.myname = new B?

The examples that I saw here, here, here and here with multiprocessing, multithreading only involve functions or standard class methods. Moreover, a solution based on ray apparently does not allow to access class attributes.

leonard vertighel
  • 1,058
  • 1
  • 18
  • 37
  • Why are `_myname` and `name` separate attributes? Why even bother with properties when the name is both readable and writable and there's no clear need for programmatic behavior? – ShadowRanger Dec 23 '21 at 09:51
  • Because I wanted to keep the example as simple as possible. True setter and getter involves a `request.get()` and a `request.put()` – leonard vertighel Dec 23 '21 at 10:13

1 Answers1

1

Answering how you'd use properties as functions

You can directly access the underlying getter and setter function if needed, and manually pass the instance to them, e.g. replacing:

a.myname = "A"

with:

type(a).myname.fset(a, "A")

For simpler usage, you could expose the functions as both functions and propertys, e.g:

class TestClass:
    def __init__(self):
        self.name = "default name"

    def get_myname(self):
        self._myname = self.name
        return self._myname

    def set_myname(self, n):
        self._myname = n
        self.name = self._myname

    myname = property(get_myname, set_myname)

so you could directly replace:

a.myname = "A"

with:

a.set_myname("A")

without needing to manually bypass the descriptor protocol, while still allowing a.myname = "A" to continue working when it's not needed for parallel processing.

Addressing the XY problem here

All that said, this is a bad use case for properties. Properties, as a rule, should be low overhead, because from the perspective of someone reading code using them, they look like attribute access and should behave roughly like attribute access, e.g. they not require multiple orders of magnitude greater time to access than regular attribute access. If your "property" requires non-local network operations, it's not suitable to act as a property; use dedicated getter and setter functions and don't provide a property at all, so consumers of your API aren't deceived into thinking the access can be done cheaply. By not using properties, your problem disappears; you're back to methods, which can be parallelized.

ShadowRanger
  • 143,180
  • 12
  • 188
  • 271