Search code examples
pythonclassoop

How to make a function accessible from both the object and the class itself?


I have a simple class called Storage that has many methods and properties.

For this question, I'm only interested in making uniques a classmethod and a property in the same time. I don't know if this is possible. I wonder if there is a dynamic processing : based on if uniques is being called from the class or an object, then we should always have the same result for the same input used (here it's data).

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

    @classmethod
    def uniques(cls, data=None):
        if data is None:
            data = cls.data
        return [list(set(item)) for item in data]

Unfortunately, when I try doing both calls one is working but the second one gives error :

data = [["apple", "banana", "apple"], ["cat", "dog", "dog"], ["red", "blue", "red"]]

print(Storage.uniques(data))
# [["banana", "apple"], ["cat", "dog"], ["blue", "red"]]

########################################

print(Storage(data).uniques())

      5 @classmethod
      6 def uniques(cls, data=None):
      7     if data is None:
----> 8         data = cls.data
      9     return [list(set(item)) for item in data]

AttributeError: type object 'Storage' has no attribute 'data'

Can you guys show me how to deal with that ? Is this even possible ?


Solution

  • I just wanted to try it. I think this is what you are looking for.

    class Storage:
        def __init__(self, data):
             self.data = data
    
        def uniques(instance_or_data):
            if isinstance(instance_or_data, Storage):
                data = instance_or_data.data
            else:
                data = instance_or_data
            print(data)
    
    
    Storage.uniques('X')
    X
    
    Storage('X').uniques()
    X
    
    Storage('Y').uniques()
    Y
    
    Storage.uniques('Y')
    Y