Towzeur
Towzeur

Reputation: 108

How may I edit a class attribut

I was wondering how I can make all instances inherited from dataObj (Two and One) modify the .data attribute of self.buffer:

When I modify the .data of the instance of one or two, I want this to change the .data of the buffer instance.

In order word, how can I make .data become global for all instance of dataObj so when I change .data in one of the instance it apply changes for all of them.

class dataObj():

def __init__(self, data):
    self.data = data

def read(self, width):
    self.data = self.data[width:]


class One(dataObj):
    def __init__(self, data):
        self.data = data

    def deserialize(self):
        self.read(1)


class Two(dataObj):
    def __init__(self, data):
        self.data = data

    def deserialize(self):
        self.read(2)


class msg():
    def __init__(self):
        self.buffer = dataObj('0123456789')

    def run(self):
        print("buffer.data = ", self.buffer.data)

        one = One(self.buffer.data)
        one.deserialize()
        print("one.data = ",one.data)

        two = Two(self.buffer.data)
        two.deserialize()
        print("two.data = ", two.data)

        print("buffer.data = ", self.buffer.data)


main = msg()
main.run()

The output:

buffer.data =  0123456789
one.data =  123456789
two.data =  23456789
buffer.data =  0123456789

The output I want:

buffer.data =  0123456789
one.data =  123456789
two.data =  3456789
buffer.data =  3456789

I have to think of using a class attribute something like this:

class dataObj():

    data = '0123456789'
    def __init__(self, data):
        pass

But I dont know how i may modify this class attribute.

Upvotes: 2

Views: 58

Answers (3)

JohanL
JohanL

Reputation: 6891

Using a separate class, as suggested here is probably a better idea but if you are dead set on trying to do it with class methods it can be achieved as:

class dataObj():

    data = None

    @classmethod
    def read(cls, width):
        dataObj.data = dataObj.data[width:]


class One(dataObj):

    @classmethod
    def deserialize(cls):
        dataObj.read(1)


class Two(dataObj):

    @classmethod
    def deserialize(cls):
        dataObj.read(2)


class msg():
    def __init__(self):
        dataObj.data = '0123456789'
        self.buffer = dataObj()

    def run(self):
        print("buffer.data = ", self.buffer.data)

        one = One()
        one.deserialize()
        print("one.data = ",one.data)

        two = Two()
        two.deserialize()
        print("two.data = ", two.data)

        print("buffer.data = ", self.buffer.data)


main = msg()
main.run()

Here all subclasses are updating the same class variable defined in dataObj().

Upvotes: 1

6502
6502

Reputation: 114481

In Python str objects are immutable; so after

a = 'hello world'
b = a

there's nothing you can do to b to change the value of a; the only way to change the value of a is to reassign a.

If for buffer instead you use a mutable object (e.g. a list) then you need two simple changes:

def read(self, width):
    self.data[:] = self.data[width:]  # note the [:] part

...

self.buffer = dataObj(list('0123456789')) # list

One key point is that the statement

self.data[:] = self.data[width:]

is different from a simple assignment because it will mutate the list content and the other instance will see the changes.

Writing instead

self.data = self.data[width:]

creates a new list object with the remaining part, without touching the original list object pointed to by the other instance.

With those two changes the output becomes:

buffer.data =  ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
one.data =  ['1', '2', '3', '4', '5', '6', '7', '8', '9']
two.data =  ['3', '4', '5', '6', '7', '8', '9']
buffer.data =  ['3', '4', '5', '6', '7', '8', '9']

Upvotes: 2

Ketan Mukadam
Ketan Mukadam

Reputation: 859

You can try this

class data:
    val = ''
    def __init__(self, value):
        data.val = value
    def printval(self):
        print(self.val)

Now the variable val is shared between all the instances.

d1 = data('addingfromd1')
d1.printval()
d2 = data('addingfromd2')
d1.printval()  --> This will print latest value "addingfromd2"

Upvotes: 1

Related Questions