Reputation: 13
So I want to call method on returned value from another method of same class.
class A():
def __init__(self,data):
self.data = data
def values(self,key):
return list(list(x.values())[0] for x in self.data['data'] if key in x.keys())
def length(self):
return len(self)
data ={"data":[{"country":"india"},{"state":"punjab"},{"country":"usa"}]}
obj = A(data)
res = obj.values('country') # returns ['india', 'usa']
res1 = obj.values('country').length() # returns AttributeError: 'list' object has no attribute 'length'
print(res)
print(res1)
i want both res and res1 to work.
I have also tried using @property decorator
class B():
def __init__(self,data):
self.data = data
def __call__(self, key):
self.key = key
return self
@property
def values(self):
self.valu = list(list(x.values())[0] for x in self.data['data'] if self.key in x.keys())
return self
def length(self):
return len(self.valu)
data ={"data":[{"country":"india"},{"state":"punjab"},{"country":"usa"}]}
obj = B(data)
res = obj('country').values.length() # returns 2
res1 = obj('country').values # returns <__main__.A object at 0x103a9fbe0>
print(res)
print(res1)
This way res works but res1 does not.
Thanks
Upvotes: 0
Views: 109
Reputation: 3727
I think the confusion here is on what object is the .length
method invoked. In the first case, it is invoked on a list
which does not have a .length
method. In the second case, it is invoked on the B
object which indeed has a .length
method. The most straightforward and preferred solution is what @Subhrajyoti Das suggested.
If you still want your code (as described in the question) to work (or just want to know if this could actually be done), you could define a custom list object which would look like as follows:
class CustomList(list):
def length(self):
return len(self)
Now instead of making a list
, you would make a CustomList
.
Edit: Adding the complete example, as requested in the comment.
class CustomList(list):
def length(self):
return len(self)
class A():
def __init__(self,data):
self.data = data
def values(self,key):
return CustomList(CustomList(x.values())[0] for x in self.data['data'] if key in x.keys())
def length(self):
return len(self)
data ={"data":[{"country":"india"},{"state":"punjab"},{"country":"usa"}]}
obj = A(data)
res = obj.values('country') # returns ['india', 'usa']
res1 = obj.values('country').length() # 2
object has no attribute 'length'
print(res)
print(res1)
Upvotes: 0
Reputation: 2710
.length()
is not a python list function. Use len(listobject)
instead.
Eg:
len(obj('country').values)
If you want to print the values. In your second example:
#Use
res1 = obj('country').data
#instead of
res1 = obj('country').values
Use below code to get list of countries
res1 = [_dict.get('country') for _dict in obj('country').data.get('data') if 'country' in _dict.keys()]
print(res1)
#['india', 'usa']
Final Updated working code:
class B():
def __init__(self,data):
self.data = data
def __call__(self, key):
self.key = key
return self
@property
def values(self):
self.valu = list(list(x.values())[0] for x in self.data['data'] if self.key in x.keys())
return self
def length(self):
return len(self.valu)
data ={"data":[{"country":"india"},{"state":"punjab"},{"country":"usa"}]}
obj = B(data)
res = obj('country').values.length() # returns 2
res1 = [_dict.get('country') for _dict in obj('country').data.get('data') if 'country' in _dict.keys()] # returns ['usa', 'india']
print(res)
print(res1)
Upvotes: 2