'list' attribute has no attribute <function> - python

I am trying to create a class for Complex numbers that includes functions that operate on lists. I think my basic setup is okay because it works for functions that operate on single elements(like conjugate), but when I try to run functions like conjugateList, I get the error message "'list' object has no attribute 'conjugateList'. I am not sure how to address this problem. Thanks.
class Complex():
def __init__(self, real= 0.0, imaginary= 0.0):
self.real = real
self.imaginary = imaginary
def __str__(self):
if self.imaginary < 0:
printStr = str(self.real) + ' - ' + str(abs(self.imaginary))+ 'i'
else:
printStr = str(self.real) + ' + ' + str(self.imaginary)+ 'i'
return printStr
def conjugate(self):
result = Complex()
result.real = self.real
result.imaginary = (self.imaginary * (-1))
return result
def conjugateList(lstC):
newLst = []
for elem in lstC:
elem = elem.conjugate()
newLst += elem
return newLst

Because the conjugateList method isn't on your list, it's on the Complex object.
Note that this conjugateList method should actually be a staticmethod or — better yet — a function.
You would do:
class Complex():
# The rest of your stuff
#staticmethod
def conjugateList(lstC):
newLst = []
for elem in lstC:
elem = elem.conjugate()
newLst += elem
return newLst
And then,
l1 = [Complex(1,1), Complex(1,2)]
l2 = Complex.conjugateList(l1)

Short of learning purposes for class design, for production you might want to use numpy:
>>> import numpy as np
>>> comps = np.array([complex(1, 1), complex(1, 2)])
>>> comps.dtype
dtype('complex128')
>>> comps.conjugate()
array([ 1.-1.j, 1.-2.j])

Related

What exactly is not iterable here, and how to fix it?

This kind of questions has been asked a lot here, but I still don't know why it happens here. The error massage is:
TypeError: 'P' object is not iterable
and is invoked by for p in self.parents: from __str__
Why P isn't iterable?
class P:
limit = 8
def __init__(self,x=0,y=0,p=None):
self.x = x
self.y = y
self.parents = p
def __str__(self):
s = ''
for p in self.parents:
s += '({},{}->)'.format(p.x,p.y)
s += '({},{}->)'.format(self.x,self.y)
return s + '\n'
def next_move(self):
def valid(x):
return x >= 0 and x < P.limit
x,y = self.x,self.y
a = [-1,1]
b = [-2,2]
ls = [(x+i, y+j) for i in a for j in b if valid(x+i) and valid(y+j)]
ls +=[(x+i, y+j) for i in b for j in a if valid(x+i) and valid(y+j)]
to_return = []
for i in range(len(ls)):
to_return += P(ls[i][0],ls[i][1],self)
return to_return
p = P()
print (p.next_move())
EDIT:
My issue here is not how to remove the error (using append) but how to use next_move() to create a list of new P that are a horse-move (Chess) away from the parent, and also append said parent to the parents attribute in the new object. The answers you gave me help avoid the error, but I don't know how to proceed
Two issues:
Firstly, You are trying to add a P instance to a list via +=. But += for lists roughly corresponds to extend and takes an iterable:
for i in range(len(ls)):
to_return += [P(...)]
# OR
# to_return.append(P(...))
Secondly, when you call the constructor with P(ls[i][0], ls[i][1], self), you are passing self as the p parameter which should be iterable itself. You might want to use P(ls[i][0], ls[i][1], [self]) instead.
You are actually getting this error at the following line:
to_return += P(ls[i][0],ls[i][1],self)
This is because you should be appending to to_return like this
to_return.append(P(ls[i][0],ls[i][1],self))
or, if you have any particular reasons to do so, like this:
to_return += [P(ls[i][0],ls[i][1],self)]
In addition, that self you passed as argument is not iterable either. Then you would have the problem in __str__, if it was to be called.
to_return.append(P(ls[i][0], ls[i][1], [self]))
Finally, I believe you meant __repr__ instead of __str__, so that you print:
[(0,0->)(1,2->)
, (0,0->)(2,1->)
]
Try this:
class P:
limit = 8
def __init__(self, x=0, y=0, p=None):
self.x = x
self.y = y
self.parents = p
def __str__(self):
s = ''
for p in self.parents:
s += '({},{}->)'.format(p.x, p.y)
s += '({},{}->)'.format(self.x, self.y)
return s + '\n'
def next_move(self):
def valid(x):
return 0 <= x < P.limit
x, y = self.x, self.y
a = [-1, 1]
b = [-2, 2]
ls = [(x + i, y + j) for i in a for j in b if valid(x + i) and valid(y + j)]
ls += [(x + i, y + j) for i in b for j in a if valid(x + i) and valid(y + j)]
to_return = []
for i in range(len(ls)):
to_return.append(P(ls[i][0], ls[i][1], self))
return to_return
p = P()
print(p.next_move())
See changes in Line 27
Because to_return is a list, so we can't use + operator. We can use append function for list.

Instances of class polynomial

How can I get coefficients to list from three different ways of creating new instances of class Polynomial?
class Polynomial(object)
def __init__(self,*args)
self.coeffs=[]
...
pol1 = Polynomial([1,-3,0,2])
pol2 = Polynomial(1,-3,0,2)
pol3 = Polynomial(x0=1,x3=2­,x1=-3)
I am expecting for example: pol2 = Polynomial(1,-3,0,2), output is 2x^3-3x+1. But I need to get coefficients to list to work with them.
Assuming, that one of the three ways is always used, you can do the following (without any validation):
class Polynomial(object):
def __init__(self, *args, **kwargs):
if args and isinstance(args[0], list): # Polynomial([1,-3,0,2])
self.coeffs=args[0]
elif args: # Polynomial(1,-3,0,2)
self.coeffs=args
else: # Polynomial(x0=1,x3=2­,x1=-3)
self.coeffs=[kwargs.get(x, 0) for x in ('x0', 'x1', 'x2', 'x3')]
def __str__(self):
s = ''
for i, x in reversed(list(enumerate(self.coeffs))):
if x:
if x > 0:
s += '+'
s += str(x)
if i > 0:
s += 'x'
if i > 1:
s += '^' + str(i)
return '0' if not s else s.lstrip('+')
pol1 = Polynomial([1,-3,0,2])
pol2 = Polynomial(1,-3,0,2)
pol3 = Polynomial(x0=1, x1=-3, x3=2)
print(pol1) # 2x^3-3x+1
print(pol2) # 2x^3-3x+1
print(pol3) # 2x^3-3x+1
In addition to schwobaseggl's response, I'd add this kind of checking:
if type(args[0]) == list:
self.coeffs=args
# ...
else:
self.coeffs=[kwargs.get(x, 0) for x in ['x'+i for i in range(len(kwargs))]]

Mutable str class extension

I've written the following extension of the class str (built-in) in order to do the following operation: Suppose I have the string "Ciao", by doing "Ciao" - "a" I want as a result the string "Cio". Here it is the code that do this and it works fine:
class my_str(str):
def __sub__(self, other):
p = list(other)
l = ""
for el in self:
if (el in p) == False:
l += el
return my_str(l)
if __name__ == "__main__":
s = my_str("Ciao")
p = my_str("a")
t = s - p
print(t) # 'Cio'
print(s) # 'Ciao'
Now, suppose that I'd like the function __sub__ to directly update the object s, in such a way that when I type print(s) after having execute s - p the output would be "Cio". How do I have to modify the class my_str?
You can use
from collections import UserString
class Test(UserString):
def __add__(self, other):
self.data = self.data + other
The UserString class is meant for subclassing the built-in string, and gives you the actual content as a self.data field.

__repr__ with 2 lists with multiple items in the List

hopefully quick answer! Any direction of help would be greatly appreciated. I am trying to prepare for my final exam.
This is how I would be calling the class:
>>> Q = priorityQueue()
>>> Q.insert("text",10)
>>> Q.insert("hello", 18)
>>> Q
text 10, hello 18
So I have a class like:
class priorityQueue():
def __init__(self):
self.items = []
self.priorities = []
def insert(self, x, p):
self.items.append(x)
self.priorities.append(p)
#This is where I dont understand how to get it to return how it should.
def __repr__(self):
new = []
for x in range(len(self.items)):
new.append(str(self.items[x])+ " " +str(self.priorities[x]))
return [str(x) for x in new]
This will give me an error like:
TypeError: __repr__ returned non-string (type list)
Thanks Stack!
The __repr__ function must return a string, but you're returning a list.
Maybe you want to change the return line to return '\n'.join(new).
Try:
def __repr__(self):
new = []
for x in range(len(self.items)):
new.append(str(self.items[x])+ " " +str(self.priorities[x]))
return ','.join(new)
Basically you need to return the output in the desired output, which is a comma separated string.

list with infinite elments

I need to operate on two separate infinite list of numbers, but could not find a way to generate, store and operate on it in python.
Can any one please suggest me a way to handle infinite Arithmetic Progession or any series and how to operate on them considering the fact the minimal use of memory and time.
Thanks every one for their suggestions in advance.
You are looking for a python generator instead:
def infinitenumbers():
count = 0
while True:
yield count
count += 1
The itertools package comes with a pre-built count generator.
>>> import itertools
>>> c = itertools.count()
>>> next(c)
0
>>> next(c)
1
>>> for i in itertools.islice(c, 5):
... print i
...
2
3
4
5
6
This is where the iterator comes in. You can't have an infinite list of numbers, but you can have an infinite iterator.
import itertools
arithmetic_progression = itertools.count(start,step) #from the python docs
The docs for Python2 can be found here
I have another python3 solution (read SICP chapter 3.5)
class Stream:
def __init__(self, head, tail):
self.head = head
self.tail = tail
self.memory = None
self.isDone = False
def car(self):
return self.head
def cdr(self):
if self.isDone:
return self.memory
self.memory = self.tail()
self.isDone = True
return self.memory
def __getitem__(self, pullFrom):
if pullFrom < 1 or self.memory == []:
return []
return [self.car()] + self.cdr()[pullFrom - 1]
def __repr__(self):
return "[" + repr(self.car()) + " x " + repr(self.tail) + "]"
def map(self, func):
if self.memory == []:
return []
return Stream(func(self.car()), lambda: Stream.map(self.cdr(), func))
def from_list(lst):
if lst == []:
return []
return Stream(lst[0], lambda:
Stream.from_list(lst[1:]))
def filter(self, pred):
if self.memory == []:
return []
elif pred(self.car()):
return Stream(self.car(), lambda: Stream.filter(self.cdr(), pred))
else:
return self.cdr().filter(pred)
def sieve(self):
return Stream(self.car(), lambda: self.cdr().filter(lambda n: n % self.car() > 0).sieve())
def foreach(self, action, pull = None):
if pull is None:
action(self.car())
self.cdr().foreach(action, pull)
elif pull <= 0:
return
else:
action(self.car())
self.cdr().foreach(action, pull-1)and run:
a = Stream(0, lambda: a.map((lambda x: x + 1)))
print(a[10])
which returns:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] .
But streams are lazily evaluated, so:
>>> a = Stream(0, lambda: a.map((lambda x: x + 1)))
>>> print(a)
prints:
[0 x [...]]
To create an object that acts like a "mutable" infinite list, you can overload the __getitem__ and __setitem__ methods in a class:
class infinite_list():
def __init__(self, func):
self.func = func
self.assigned_items = {}
def __getitem__(self, key):
if key in self.assigned_items:
return self.assigned_items[key]
else:
return self.func(key)
def __setitem__(self, key , value):
self.assigned_items[key] = value
Then, you can initialize the "infinite list" with a lambda expression and modify an item in the list:
infinite_thing = infinite_list(lambda a: a*2)
print(infinite_thing[1]) #prints "2"
infinite_thing[1] = infinite_thing[2]
print(infinite_thing[1]) #prints "4"
Similarly, it is possible to create an "infinite dictionary" that provides a default value for each missing key.
Perhaps the natural way to generate an infinite series is using a generator:
def arith(a, d):
while True:
yield a
a += d
This can be used like so:
print list(itertools.islice(arith(10, 2), 100))
My solution is:
from hofs import *
def cons_stream(head,tail):
return [head,tail,False,False]
def stream_cdr(strm):
if strm[2]:
return strm[3]
strm[3] = strm[1]()
strm[2] = True
return strm[3]
def show_stream(stream, num = 10):
if empty(stream):
return []
if num == 0:
return []
return adjoin(stream[0], show_stream(stream_cdr(stream), num - 1))
def add_streams(a , b):
if empty(a):
return b
if empty(b):
return a
return cons_stream(a[0] + b[0] , lambda : add_streams( stream_cdr(a), stream_cdr(b)))
def stream_filter( pred , stream ):
if empty(stream):
return []
if pred(stream[0]):
return cons_stream(stream[0], lambda : stream_filter(pred, stream_cdr(stream)))
else:
return stream_filter( pred , stream_cdr( stream ))
def sieve(stream):
return cons_stream(stream[0] , lambda : sieve(stream_filter(lambda x : x % stream[0] > 0 , stream_cdr(stream))))
ones = cons_stream(1, lambda : ones)
integers = cons_stream(1, lambda : add_streams(ones, integers))
primes = sieve(stream_cdr(integers))
print(show_stream(primes))
Copy the Python code above.
When I tried it, i got [2, 3, 5, 7, 11, 13, 17, 19, 23, 29] which is 10 of an infinite list of primes.
You need hofs.py to be
def empty(data):
return data == []
def adjoin(value,data):
result = [value]
result.extend(data)
return result
def map(func, data):
if empty(data):
return []
else:
return adjoin(func(data[0]), map(func, data[1:]))
def keep(pred, data):
if empty(data):
return []
elif pred(data[0]):
return adjoin( data[0] , keep(pred, data[1:]))
else:
return keep(pred, data[1:])
I assume you want a list of infinite numbers within a range. I have a similar problem, and here is my solution:
c = 0
step = 0.0001 # the difference between the numbers
limit = 100 # The upper limit
myInfList = []
while c <= limit:
myInfList.append(c)
c = c + step
print(myInfList)

Categories