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]
Related
So I have created a class Calculate where I will define two functions plus(self,x) and avg_over_totalnum(self) that will modify a list __init__(self, items).
plus(self, x) will add either x or the members of x to the list self.items.
Here x is one of the following: (1) a number, (2) a list, or (3) a tuple. If x is a number, it is added to the list directly. If x is a list or a tuple, its members are individually added to the list.
For instance if self.items == [5]
if x == 45, plus(self, x) will return [5,45]
if x == [4,5], the output will be [5,4,5]
avg_over_totalnum(self) will compute and return the mean of the data maintained in the
collection
Here is my attempt at the code so far, which doesn't work at all...
class Calculate:
def __init__(self, items):
self.items = list(items)
def plus(self,x):
if x in 123456789:
return self.items + x
else:
return self.items.append(x)
def avg_over_totalnum(self):
return (sum(self.items))/(len(self.items))
What changes should I make in my code??
Your plus method is a bit weird. It doesn't modify self.items in-place, so self.items don't get updated with x. Also, your if-statement is checking if x is in an integer, which doesn't make sense. Change plus with the function below:
def plus(self,x):
if isinstance(x,(list,tuple)):
self.items.extend(list(x))
else:
self.items.append(x)
return self.items
Also to avoid ZeroDivisionError:
def avg_over_totalnum(self):
return (sum(self.items))/(len(self.items)) if self.items else 0
Then it works fine.
c = Calculate([5])
print(c.plus(4)) # [5, 4]
print(c.plus([3,2])) # [5, 4, 3, 2]
print(c.avg_over_totalnum()) # 3.5
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]
I have the class parameter below which should return the index of 2 numbers within the 'nums' list that sums up to the target.
When I tried to test the class using 9 as the target by writing 'Solution(nums,9)', Python returned the 'TypeError: object() takes no parameters' error. Can anyone advise me on what I did wrong in my script?
nums = [2, 7, 11, 15]
class Solution(object):
def twoSum(self, nums, target):
nums_1 = nums
for i in range(len(nums)):
for a in range(len(nums_1)):
if i != a:
if nums[i] + nums_1[a] == target:
return(sorted([i, a]))
Solution(nums,9)
Traceback (most recent call last):
TypeError: object() takes no parameters
You can't use it like that, because your class have default __init__(which your class get by default, since you didn't define it), and it doesn't take any parameters unless you define it to take it.
Use the following:
sol = Solution()
sorted_stuff = sol.twoSum(nums, 9)
print(sorted_stuff)
You have missed the __init__() method while defining your Solution class. Its not always compulsory, but since you are creating an instance of the class by calling Solution() with some arguments, the __init__ method must be implemented. So the implementation can be:
_nums = [2, 7, 11, 15]
class Solution(object):
def __init(nums, target):
self.nums = nums
self.target = target
def twoSum(self, nums=None, target=None):
if not nums:
nums = self.nums
if not target:
target= self.target
nums_1 = nums
for i in range(len(nums)):
for a in range(len(nums_1)):
if i != a:
if nums[i] + nums_1[a] == target:
return(sorted([i, a]))
s = Solution(_nums,9)
s.twoSum()
Also you can do:
s = Solution()
s.twoSum(_nums,9)
This gives you the freedom to either have the args defined during the class initialization or calling the actual method with the args.
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
The original context of this bug is a piece of code too large to post in a question like this. I had to whittle this code down to a minimal snippet that still exhibits the bug. This is why the code shown below is somewhat bizarre-looking.
In the code below, the class Foo may thought of as a convoluted way to get something like xrange.
class Foo(object):
def __init__(self, n):
self.generator = (x for x in range(n))
def __iter__(self):
for e in self.generator:
yield e
Indeed, Foo seems to behave very much like xrange:
for c in Foo(3):
print c
# 0
# 1
# 2
print list(Foo(3))
# [0, 1, 2]
Now, the subclass Bar of Foo adds only a __len__ method:
class Bar(Foo):
def __len__(self):
return sum(1 for _ in self.generator)
Bar behaves just like Foo when used in a for-loop:
for c in Bar(3):
print c
# 0
# 1
# 2
BUT:
print list(Bar(3))
# []
My guess is that, in the evaluation of list(Bar(3)), the __len__ method of Bar(3) is getting called, thereby using up the generator.
(If this guess is correct, the call to Bar(3).__len__ is unnecessary; after all, list(Foo(3)) produces the correct result even though Foo has no __len__ method.)
This situation is annoying: there's no good reason for list(Foo(3)) and list(Bar(3)) to produce different results.
Is it possible to fix Bar (without, of course, getting rid of its __len__ method) such that list(Bar(3)) returns [0, 1, 2]?
Your problem is that Foo does not behave the same as xrange: xrange gives you a new iterator each time you asks its iter method, while Foo gives you always the same, meaning that once it is exhausted the object is too:
>>> a = Foo(3)
>>> list(a)
[0, 1, 2]
>>> list(a)
[]
>>> a = range(3)
>>> list(a)
[0, 1, 2]
>>> list(a)
[0, 1, 2]
I could easily confirm that the __len__ method is called by list by adding spys to your methods:
class Bar(Foo):
def __len__(self):
print "LEN"
return sum(1 for _ in self.generator)
(and I added a print "ITERATOR" in Foo.__iter__). It yields:
>>> list(Bar(3))
LEN
ITERATOR
[]
I can only imagine two workarounds:
my preferred one: return a new iterator on each call to __iter__ at Foo level to mimic xrange:
class Foo(object):
def __init__(self, n):
self.n = n
def __iter__(self):
print "ITERATOR"
return ( x for x in range(self.n))
class Bar(Foo):
def __len__(self):
print "LEN"
return sum(1 for _ in self.generator)
we get correctly:
>>> list(Bar(3))
ITERATOR
LEN
ITERATOR
[0, 1, 2]
the alternative: change len to not call the iterator and let Foo untouched:
class Bar(Foo):
def __init__(self, n):
self.len = n
super(Bar, self).__init__(n)
def __len__(self):
print "LEN"
return self.len
Here again we get:
>>> list(Bar(3))
LEN
ITERATOR
[0, 1, 2]
but Foo and Bar objects are exhausted once first iterator reaches its end.
But I must admit that I do not know the context of your real classes...
This behaviour might be annoying but it's actually quite understandable. Internally a list is simply an array and an array is a fixed size datastructure. The result of this is that if you have a list that has size n and you want to add an extra item to reach n+1 it will have to create a whole new array and completely copy the old one to the new one. Effectively your list.append(x) is now a O(n) operation instead of the regular O(1).
To prevent this, list() tries to get the size of your input so it can guess what size the array needs to be.
So one solution for this problem is to force it to guess by using iter:
list(iter(Bar(3)))