How to modify the value of index while trying to fecth it? - python

For example there is a list called Demo_list.
Demo_list = [4,5,6,7]
If i give
Demo_list[0]
we will get value as 4.
But if i gave only Demo_list[0] i want to get square of that value and the list should not be modified.
Is it possible?

Yes, it is possible.
variable = Demo_list[0]**2
The code above won't modify the list.

demo_list = [4, 6, 7, 8]
for i in range (len(demo_list)):
j = demo_list[i] * demo_list[i]
print j
May be you are looking something like that..

#For complete list
SqrtList = [x**2 for x in Demo_list]
#For single element
Sqrtvariable = Demo_list**2

You can use the < math > function
import math
print ( math.pow(demo[0],2)
where, 2 is the power that you want to raise the value in demo[0].
Edit (Inheriting from the collections, and overriding the abstract list methods , in your case (getitem),that you wish to modify).
import collections
class MyList(collections.MutableSequence):
def __init__(self, *args):
self.list=list()
self.extend(list(args))
def __len__(self):
return len(self.list)
def __getitem__(self,i):
return (self.list[i]**2)
def __delitem__(self,i):
del self.list[i]
def __setitem__(self,i,v):
self.list[i]=v
def insert(self,i,v):
self.list.insert(i,v)
def __str__(self):
return str(self.list)
Note: When you override these abstract methods, you need to define your list, with the type, you declared in this class. i.e.,
demo_list=MyList(1,2,3,4)
demo_list[1]
Output : 4

Related

(Python) How to override list's method python?

well, i want to add method in list.
So, i made new child class like this.
class list(list):
def findAll(self,position):
data = []
for i in range(len(self)):
if(self[i] == position):
data.append(i)
return data
k = list()
k.append(1)
k.append(2)
k.append(3)
k.append(4)
print(k.findAll(10))
but i want to make code like this.
class list(list):
def findAll(self,position):
data = []
for i in range(len(self)):
if(self[i] == position):
data.append(i)
return data
k = [10,1,2,3,4,5,10,10,10,10,10] #when i make list, i want use '[' and ']'
print(k.findAll(10))#it occur AttributeError: 'list' object has no attribute 'findAll'
how can i make this?
when i make list, i want use '[' and ']'
i tried this code
class list(list):
def findAll(self,position):
data = []
for i in range(len(self)):
if(self[i] == position):
data.append(i)
return data
k = [10,1,2,3,4,5,10,10,10,10,10]
k = list(k)
print(k.findAll(10))
Usually a child class shouldn't have the same name as the parent, especially when it's a standard class, it can lead to lots of confusion down the road.
you could use the same name, but it should be in a particular package, so when it's used, to be sure it's not confused with the other one.
Another thing here, when you want to use your list class, you need to instantiate it.
With this k = [10,1,2,3,4,5,10,10,10,10,10]you instantiate the standard list, also with `k = list(k)' because you use the same name, instead of package.class to distinguish, also because in your class you have no overwritten method that takes a list as argument, no conversion method etc.
The answer already given by the other user should be ok, but so you understand what is what and why I wrote this
You can't override built in type's method.
You can create a new class, that "extends" class "list" (inheritance).
class ExtendedList(list):
def find_all(self, num):
return [i for i in range(len(self)) if self[i] == num]
k = ExtendedList([1, 2, 3, 3, 3, 4, 3])
print(k.find_all(3))
# [2, 3, 4, 6]

Using the map() function within a class

I've been trying to get the map() function to work within a class but have had trouble because I'm not sure if I should be passing self into it. If so, I'm unsure how to make self into a list to go with my other iterables. Here is my code so far:
from itertools import repeat
class test:
def __init__(self):
self.nums = [1, 4, 8]
self.empty_list = []
map(self.fxn, repeat(self, len(self.nums)), self.nums)
print(self.empty_list)
def fxn(self, num):
self.empty_list.append(num ** num)
instance = test()
Even after trying to append to the empty list, the list still seems to be blank, what am I doing wrong in that example?
map doesn't mutate its argument. It returns a new iterable.
self.nums = list(map(...))
test.fxn is a function of two arguments: self and num. self.fxn is a bound method of one argument: num. Since you're just repeatedly applying it on self, you can bind it and save yourself the extra argument.
self.nums = list(map(self.fxn, self.nums))
You can change map(self.fxn, repeat(self, len(self.nums)), self.nums) to self.empty_list=list(map(self.fxn,self.nums)) which is equivalent to self.empty_list=list(map(lambda x: self.fxn(x),self.nums)) and self.empty_list=[self.fxn(i) for i in self.nums] and remember to change fxn() from self.empty_list.append(num ** num) to return num ** num (and since it is list(map(...))-list it will be a list), so try the below:
class test:
def __init__(self):
self.nums = [1, 4, 8]
self.empty_list=list(map(self.fxn,self.nums))
print(self.empty_list)
def fxn(self, num):
return num ** num
instance = test()
Output:
[1, 256, 16777216]

How would I be able to return which instance belongs to the random number in my list. Without using a million if statements?

what I am trying to do, is returnthe instance, which range has the value from a random.randint() in a list.... Example...
class Testing:
def __init__(self, name, value):
self.name = name
self.value = value
randomtest = Testing('First', range(1, 50))
randomtest_2 = Testing('Second', range(50, 100))
selections = []
counter = 0
while counter < 2:
counter =+ 1
selector = random.randint(1, 100)
selections.append(selector)
But I don't want to use a million if statements to determine which index in the selections list it belongs to.. Like this:
if selections[0] in list(randomtest.value):
return True
elif selections[0] in list(randomtest_2.value):
return True
Your help is much appreciated, I am fairly new to programming and my head has just come to a stand still at the moment.
You can use a set for your selections object then check the intersection with set.intersection() method:
ex:
In [84]: a = {1, 2}
In [85]: a.intersection(range(4))
Out[85]: {1, 2}
and in your code:
if selections.intersection(randomtest.value):
return True
You can also define a hase_intersect method for your Testing class, in order to cehck if an iterable object has intersection with your obejct:
class Testing:
def __init__(self, name, value):
self.name = name
self.value = value
def hase_intersect(self, iterable):
iterable = set(iterable)
return any(i in iterable for i in self.value)
And check like this:
if randomtest.hase_intersect(selections):
return True
based on your comment, if you want to check the intersection of a spesific list against a set of objects you have to iterate over the
set of objects and check the intersection using aforementioned methods. But if you want to refuse iterating over the list of objects you should probably use a base claas
with an special method that returns your desire output but still you need to use an iteration to fild the name of all intended instances. Thus, if you certainly want to
create different objects you neend to at least use 1 iteration for this task.

How can I sum (make totals) on multiple object attributes with one loop pass?

I want to sum multiple attributes at a time in a single loop:
class Some(object):
def __init__(self, acounter, bcounter):
self.acounter = acounter
self.bcounter = bcounter
someList = [Some(x, x) for x in range(10)]
Can I do something simpler and faster than it?
atotal = sum([x.acounter for x in someList])
btotal = sum([x.bcounter for x in someList])
First off - sum doesn't need a list - you can use a generator expression instead:
atotal = sum(x.acounter for x in someList)
You could write a helper function to do the search of the list once but look up each attribute in turn per item, eg:
def multisum(iterable, *attributes, **kwargs):
sums = dict.fromkeys(attributes, kwargs.get('start', 0))
for it in iterable:
for attr in attributes:
sums[attr] += getattr(it, attr)
return sums
counts = multisum(someList, 'acounter', 'bcounter')
# {'bcounter': 45, 'acounter': 45}
Another alternative (which may not be faster) is to overload the addition operator for your class:
class Some(object):
def __init__(self, acounter, bcounter):
self.acounter = acounter
self.bcounter = bcounter
def __add__(self, other):
if isinstance(other, self.__class__):
return Some(self.acounter+other.acounter, self.bcounter+other.bcounter)
elif isinstance(other, int):
return self
else:
raise TypeError("useful message")
__radd__ = __add__
somelist = [Some(x, x) for x in range(10)]
combined = sum(somelist)
print combined.acounter
print combined.bcounter
This way sum returns a Some object.
I doubt that this is really faster, but you can do it like thus:
First define padd (for "pair add") via:
def padd(p1,p2):
return (p1[0]+p2[0],p1[1]+p2[1])
For example, padd((1,4), (5,10)) = (6,14)
Then use reduce:
atotal, btotal = reduce(padd, ((x.acounter,x.bcounter) for x in someList))
in Python 3 you need to import reduce from functools but IIRC it can be used directly in Python 2.
On edit: For more than 2 attributes you can replace padd by vadd ("vector add") which can handle tuples of arbitrary dimensions:
def vadd(v1,v2):
return tuple(x+y for x,y in zip(v1,v2))
For just 2 attributes it is probably more efficient to hard-wire in the dimension since there is less function-call overhead.
Use this line to accumulate all of the attributes that you wish to sum.
>>> A = ((s.acounter,s.bcounter) for s in someList)
Then use this trick from https://stackoverflow.com/a/19343/47078 to make separate lists of each attribute by themselves.
>>> [sum(x) for x in zip(*A)]
[45, 45]
You can obviously combine the lines, but I thought breaking it apart would be easier to follow here.
And based on this answer, you can make it much more readable by defining an unzip(iterable) method.
def unzip(iterable):
return zip(*iterable)
[sum(x) for x in unzip((s.acounter,s.bcounter) for s in someList)]

Is there a method that returns the current item of a sequence?

I have a list of class objects and I'm using itertools.cycle() to continually loop through it.
class Letter:
def __init__(self,name):
self.name = name
self.att = 0
self.att1 = 0
Now I create the list of class objects
letterList = [Letter('a'),Letter('b'),Letter('c'),Letter('d')]
Then I make a sequence with itertools.cycle() like so:
seqList = itertools.cycle(letterList)
Anytime I want to go to the next item in the sequence and assign a value to one of the items attributes:
next(seqList).att = 1
But what if I want to assign another value to a different attribute? Is there another iterator method that will allow me to call the current item in the sequence like:
thisItem(seqList).att1 = 7
You can assign next() to a variable and access that variable.
this_one = next(seqList)
this_one.attr = value
If you just plan to infinitely loop over the same items, you can use a for loop (a break step is useful for getting out eventually though!):
for item in itertools.cycle(seqList):
item.attr1 = value1
item.attr2 = value2
if condition_met:
break
In most practical situations you simply use a variable, but just for fun, let's create a wrapper that would "remember" the last item (or N last items) for the given iterable:
from collections import deque
class recorded:
def __init__(self, it, size=1):
self.it = it
self.buf = deque(maxlen=size)
def __iter__(self):
return self
def next(self):
self.buf.append(next(self.it))
return self.buf[-1]
def last(self, n=0):
return self.buf[-1-n]
Now you can write:
it = recorded(itertools.cycle(letterList))
it.next()
it.last().something = 11
it.last().somethingElse = 111
or even:
it = recorded(itertools.cycle(letterList), 2)
it.next()
it.last().something = 11
it.next()
it.last(1).something = penultimate
The solution I found was:
next(seqList).att = 1
next(seqList)
next(seqList)
next(seqList)
next(seqList).att1 = 7
It's not pretty or elegant and it won't work very well for a larger set but it works for this situation and is very simple.

Categories

Resources