I would like to implement the str method to nicely format the string representation of the matrix: one line per row, two characters per number (%2d) and a space between numbers. For example:
m = Matrix([[1,0,0],[0,1,0],[0,0,1]])
print(m)
1 0 0
0 1 0
0 0 1
I've tried this:
class Matrix:
def __init__(self, rows):
self.rows = rows
def __str__(self):
for element in self.rows:
for i in element:
print(i, end=" ")
print()
But my output becomes
1 2 3
4 5 6
7 8 9
None
How would I solve this? Because the none shouldn't be there.
The __str__ method has to return a string, not print it.
What you are seeing is:
The prints inside of __str__.
The return value of __str__, which is None.
To correct it, build a string in __str__ and return it.
class Matrix:
def __init__(self, rows):
self.rows = rows
def read(self):
for element in self.rows:
for i in element:
print(i, end=" ")
print('\n')
m = Matrix([[1,0,0],[0,1,0],[0,0,1]])
m.read()
You Should use something like this. Creating a new function to represent your data is good practice than trying to use the __str__ method to do your job. because you might need to handle other edge cases explicitly
Output:
1 0 0
0 1 0
0 0 1
Note: This way you can remove None at the end as well
because The first is inside function and the second is outside function. When a function doesn't return anything, it implicitly returns None.
Maybe you could do it like this?
class Matrix:
def __init__(self, rows):
self.rows = np.array(rows)
def __str__(self):
return "\n".join(np.array2string(row)[1:-1] for row in self.rows)
m = Matrix([[1,0,0],[0,1,0],[0,0,1]])
print(m)
Notice that we here convert rows to to a 2d numpy array first. If you want to avoid numpy for some reason, you can do this.
class Matrix:
def __init__(self, rows):
self.rows = rows
def __str__(self):
return '\n'.join(' '.join(map(str, row)) for row in self.rows)
m = Matrix([[1,0,0],[0,1,0],[0,0,1]])
print(m)
Related
I'm writing an Iterator class that generate all possible ID numbers.
the issue is that I need it to print all 9 digit numbers including the ones that starts with 0 for example: 000000001 000000002 ect.
I need the output as a number and not a string, is there a way to do it?
my code:
class IDIterator:
def __init__(self):
self._id = range(000000000, 1000000000)
self._next_id = 000000000
def __iter__(self):
return self
def __next__(self):
self._next_id += 1
if self._next_id == 999999999:
raise StopIteration
return self._next_id
ID = iter(IDIterator())
print(next(ID))
print(next(ID))
print(next(ID))
output = 1
2
3
..
Python has a built in string function which will perform the left-padding of zeros
>>> before = 1
>>> after = str(before).zfill(9)
000000001
>>> type(after)
<class 'str'>
If you need the ID returned as an integer number with leading zeros preserved, I don't believe there's a way to do what you're looking for--the primitive Python type simply does not support this type of representation. Another strategy would be to store the ID's as normal integers and format with leading zeros when you need to display something to the user.
def format_id(string, length=9):
return str(string).zfill(length)
Is there a way to make __repr__() return a 2d list so that it prints row by row in Python?
My attempt is below. I can't see how I can insert new lines, like in print("..", end="\n").
class Board:
def __init__(self, rows = 6, cols=7, fill=0):
self.rows = rows
self.cold = cols
self.symbol = fill
self.board = [[fill] * cols for row in range(rows)]
def __repr__(self):
return str([self.board[i] for i in range(len(self.board))])
board = Board()
print(board)
You really shouldn't be using __repr__() for this use – let's call it .format() instead, maybe?
Either way, you'll want to generate lines out of the characters with no separator (''.join(...)), then join those lines with '\n':
def format(self):
return '\n'.join([''.join(str(c) for c in row) for row in self.board])
I've been struggling in creating the vigenere table in python
That should be the result:
So basically I have the entire alphabet on the first line, and the alphabet shifted by one letter on the second one etc.
That's my code so far:
class CypherTable:
def __init__(self):
self.matrix = [[chr(i) for i in range(ord('a'),ord('z')+1)] for i in range(5)]
def __str__(self):
for i in range(len(self.matrix)):
print self.matrix[i]
return ""
table = CypherTable()
print(table)
I managed to print letters from a to z a number of times but I don't know how to modify each interaction in order to shift the first letter by one.
I'm used to work in java where you first define the array length and then populate it, but since python has a faster syntax I can't figure out what's the best way to do it.
A simpler way is to use the string module:
from string import ascii_uppercase as l
class CypherTable:
def __init__(self):
self.final_table = [l[i:]+l[:i] for i in range(len(l))]
for i in CypherTable().final_table:
print(i)
Output:
ABCDEFGHIJKLMNOPQRSTUVWXYZ
BCDEFGHIJKLMNOPQRSTUVWXYZA
CDEFGHIJKLMNOPQRSTUVWXYZAB
DEFGHIJKLMNOPQRSTUVWXYZABC
EFGHIJKLMNOPQRSTUVWXYZABCD
FGHIJKLMNOPQRSTUVWXYZABCDE
GHIJKLMNOPQRSTUVWXYZABCDEF
HIJKLMNOPQRSTUVWXYZABCDEFG
IJKLMNOPQRSTUVWXYZABCDEFGH
JKLMNOPQRSTUVWXYZABCDEFGHI
KLMNOPQRSTUVWXYZABCDEFGHIJ
LMNOPQRSTUVWXYZABCDEFGHIJK
MNOPQRSTUVWXYZABCDEFGHIJKL
NOPQRSTUVWXYZABCDEFGHIJKLM
OPQRSTUVWXYZABCDEFGHIJKLMN
PQRSTUVWXYZABCDEFGHIJKLMNO
QRSTUVWXYZABCDEFGHIJKLMNOP
RSTUVWXYZABCDEFGHIJKLMNOPQ
STUVWXYZABCDEFGHIJKLMNOPQR
TUVWXYZABCDEFGHIJKLMNOPQRS
UVWXYZABCDEFGHIJKLMNOPQRST
VWXYZABCDEFGHIJKLMNOPQRSTU
WXYZABCDEFGHIJKLMNOPQRSTUV
XYZABCDEFGHIJKLMNOPQRSTUVW
YZABCDEFGHIJKLMNOPQRSTUVWX
ZABCDEFGHIJKLMNOPQRSTUVWXY
To be even cleaner, particularly if you will not be declaring any other methods in the class, you can use #classmethod:
from string import ascii_uppercase as l
class CypherTable:
final_table = [l[i:]+l[:i] for i in range(len(l))]
#classmethod
def show_board(cls):
for i in cls.final_table:
print(i)
CypherTable.show_board()
Regarding your recent comment, you can try this:
from string import ascii_uppercase as l
class CypherTable:
def __init__(self):
self.final_table = [l[i:]+l[:i] for i in range(len(l))]
def cross(self, b, a):
val1 = self.final_table[0].index(a)
new_letter = [i for i in self.final_table if i[0] == b][0][val1]
return new_letter
c = CypherTable()
print(c.cross('P', 'C'))
Output:
'R'
Here's your code with a minimum amount of changes. You can use modulo to loop from 26 back to 0. Note that __str__ should return a string and shouldn't print anything:
class CypherTable:
def __init__(self):
self.matrix = [[chr(ord('A') + (i + j) % 26) for i in range(26)] for j in range(5)]
def __str__(self):
return "\n".join('|'.join(row) for row in self.matrix)
table = CypherTable()
print(table)
It outputs:
A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z
B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|A
C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|A|B
D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|A|B|C
E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|A|B|C|D
I have a problem with below design. I am looking for a vectorized solution for below circular reference problem. Value (calculated by func1) uses the content from number (calculated by func2), number gets increased by Value afterwards and everything will be produced in a dataframe via build().
class test(object):
def __init__(self, bool, start=100):
self.start = start
self.bool = bool
self.value = self.func1()
self.number = self.func2()
def func1(self):
if bool==True:
value = **`here value from func2`**/ 2
else:
value = 0
return value
def func2(self):
number = start + self.value
return number
def build(self):
df = pd.DataFrame()
df['bool'] = self.bool
df['value']= self.value
df['number'] = self.number
so in the end the dataframe should look like this:
bool = pd.Series([False, True, False, True, False,.....])
bool value number
Index
0 False 0 100
1 True 50 100
2 False 0 150
3 True 75 150
4 False 0 225
my question is: how can I create this with classes and separate methods for value and number without iteration? The problem is that value depends on numberand vice versa (circular reference).
EDIT: although not modeled in this way here the number could be a cash account and value a certain number of shares that can be bought depending on the account size. account size then increases/decreases based on what happened to the shares. The main difficulty how to define the formula used for number (the account). you have a starting value but then in needs to increase depending on the future. but if you write like:
number = start + self.value ((which are the proceeds/results of other columns))
It does not work in the first row because the self.value does not yet exist. therefore I used the term circular reference.
Based on what you describe, I think you are trying to implement some sorts of class which construct the list "dynamically". While I think it is better to separate the task into two: one is form the DataFrame; second is to update it.
Below is my implementation of the class to form the DataFrame based on a Bool array and the values.
class test(object):
def __init__(self, _bool, v, start=100):
self._bool = _bool
self.v = v
self.df = pd.DataFrame()
self.vout = []
self.start = start
self.contruct()
def contruct(self):
i=0
for b in self._bool:
if b:
self.vout.append(self.v[i])
i += 1
else:
self.vout.append(0)
def build(self):
self.df['bool']=self._bool
self.df['value']= self.vout
self.df['sum'] = self.df['value'].cumsum() + self.start
return self.df
_bool = pd.Series([False, True, False, True, False])
_v = [50, 75]
a = test(_bool, _v)
df= a.build()
print df
Out[48]:
bool value sum
0 False 0 100
1 True 50 150
2 False 0 150
3 True 75 225
4 False 0 225
FYI, when you define the attribute, you shouldn't use bool as it is python reversed namespace and will cause confusion to interpreter as well as to people who read you code.
(I'm not too great at python, so forgive me if this is a stupid question)
So I want to create a data structure that represents this -
word1 word2
word3 1 2
word4 3 4
Right now I've tried doing something like this -
self.table = [][]
but this is giving me an invalid syntax error(I guess because I haven't initialized the arrays?). However, even if I were to use this I wouldn't be able to use it because I don't know how large my x and y dimension is(it seems like there would be an array out of index exception).
Should I be using a double dictionary? What should I be using?
Maybe you can try initializing your table with
self.table = {r : { c : 0 for c in ['word1', 'word2']} for r in ['word3', 'word4']}
and then you can access each position by
self.table['word3']['word1'] = 2
Python doesn't have a ready-made instruction to create a bi-dimensional matrix, but it's easy to do that using list comprehensions:
matrix = [[0] * cols for i in range(rows)]
then you can access the matrix with, for example
matrix[row][col] += 42
assuming rows=10 and cols=20 then the row index must go from 0 to 9 and the col index from 0 to 19. You can also use negative indexes to mean counting from the end; for example
matrix[-1][-1] = 99
will set the last cell to 99
If you are not opposed to using an external library, you might check out
Pandas Data Frames
The idea is to create a dictionary, which maps the strings to the indeces. In the following there's a little class which overloads the '[ ]'-operator:
class ArrayStrIdx:
""" 2D Array with string as Indeces
Usage Example::
AA = ArrayStrIdx()
AA["word1", "word3"] = 99
print(AA["word2", "word5"])
"""
cols ="word1 word2"
rows ="word3 word4 word5"
dd = [[10,11,12],[20,21,22]] # data
def __init__(self):
""" Constructor builds dicts for indexes"""
self.ri = dict([(w,i) for i,w in enumerate(self.rows.split())])
self.ci = dict([(w,i) for i,w in enumerate(self.cols.split())])
def _parsekey(self, key):
""" Convert index key to indeces for ``self.dd`` """
w0, w1 = key[0], key[1]
return self.ci[w0], self.ri[w1]
def __getitem__(self, key):
""" overload [] operator - get() method"""
i0, i1 = self._parsekey(key)
return self.dd[i0][i1]
def __setitem__(self, key, value):
""" overload [] operator - set() method """
i0, i1 = self._parsekey(key)
self.dd[i0][i1] = value
Update: Expanded answer to allow something like AA["word1", "word3"] = 23.