I have defined a function as such:
def quicksort(points):
if len(points) < 2: return points
smaller,equal,larger = [], [], []
pivot_angle = find_polar_angle(random.randint(0, len(points) - 1))
for pt in points:
pt_angle = find_polar_angle(pt)
if pt_angle < pivot_angle:
smaller.append(pt)
elif pt_angle == pivot_angle:
equal.append(pt)
else:
larger.append(pt)
return quicksort(smaller) + sorted(equal, key = find_dist) + quicksort(larger)
Now, I want to change my code - which btw is an implementation of the Graham Scan Algorithm - into an object oriented code. So I went ahead and declared a class in a file MyClasses.py:
from MyFunctions import find_anchor, find_polar_angle, find_dist, find_det, quicksort, graham_scan
class Cluster:
def __init__(self):
self.members = []
self.hull = []
self.anchor = None
self.find_anchor = find_anchor
self.find_polar_angle = find_polar_angle
self.find_dist = find_dist
self.find_det = find_det
self.quicksort = quicksort
self.graham_scan = graham_scan
But of course I have to change my functions as well. I don't want to list all the functions here, that's why I stay with the quicksort function as an example. This is where I struggle a lot, since I don't know the python syntax well enough to be sure about what I am doing here. This is my revised form of quicksort:
def quicksort(self, points):
if len(points) < 2: return points
smaller,equal,larger = [], [], []
pivot_angle = self.find_polar_angle(self, random.randint(0, len(self.members) - 1))
for pt in points:
pt_angle = self.find_polar_angle(self, pt)
if pt_angle < pivot_angle:
smaller.append(pt)
elif pt_angle == pivot_angle:
equal.append(pt)
else:
larger.append(pt)
return self.quicksort(self, smaller) + sorted(self, equal, key = self.find_dist) + self.quicksort(self, larger)
Here's the thing: This function is recursive! So I need it to take smaller, equal and larger as arguments. Later, another function graham_scan is going to call this function as such:
self.members = self.quicksort(self, self.members)
I know there are probably many mistakes in here. That's why I'm asking: Is this last expression a valid expression? I mean I am changing a class-variable (self.members) but I do so not by directly changing it, but by assigning it the return value of quicksort.
Anyways, help is very much appreciated!
To make an existing function as a new property of a new class, try this:
def quicksort():
pass # your custom logic
class Cluster:
def __init__(self):
self.members = []
self.quicksort = quicksort
# more properties
Python has quite a different syntax to C++ or Java.
To say about the second question, all the variables used in quicksort function body are only available in that function only.
About second question. All members of classes are PUBLIC in python. By convention you can add "_" and "__" in front of the names for protected and private respectfully. BUT this does NOT prevent you from accessing them, it just means that you (or whoever reading the code) should not misuse them.
Although, __variable must be accessed with following syntax outside of class:
class Square:
def __init__(self, x):
self.__x = x
def get_surface(self):
return self.__x **2
>>> square1 = Square(5)
>>> print(square1.get_surface())
>>> 25
>>> square1._Square__x = 10
>>> print(square1.get_surface())
>>> 100
>>> square1.__x
>>> **AttributeError: 'Square' object has no attribute '__x'**
Or it will raise AttributeError. Hope this helps
Related
As a way of practicing python I'm trying to write a little program that creates sudoku puzzles. I've found multiple questions similar to my issue but none seem to exactly relate.
#!usr/bin/python3
from random import randint
class Puzzle :
def __init__(self, **puzzle):
puzzle = [[0 for x in range(9)]for y in range(9)]
def createEasy(self):
count = 0
while(count < 32):
i = randint(0,8)
j = randint(8,9)
k = randint(1,9)
if (self.puzzle[i][j] != 0):
self.puzzle[i][j] = k
count += 1
def createMedium(self):
count = 0
while(count < 30):
i = randint(0,8)
j = randint(8,9)
k = randint(1,9)
if (self.puzzle[i][j] != 0):
self.puzzle[i][j] = k
count += 1
def createHard(self):
count = 0
while(count < 26):
i = randint(0,8)
j = randint(8,9)
k = randint(1,9)
if (self.puzzle[i][j] != 0):
self.puzzle[i][j] = k
count += 1
def main():
print("Welcome to sudoku!!!")
answer = input( "what level of difficultly do you want today?")
if (answer == "easy"):
self.createEasy()
for x in Puzzle.puzzle:
for y in x:
print(y)
print('\n')
Puzzle.main()
Most answers I found either had to do with functions not being defined in the right order or not putting "self" in the parameter list of all the functions. One answer even said to get rid of "self" parameter in the init function but that didn't help either. I also found this answer though I don't think it relates either. NameError: name 'self' is not defined The only thing I can think of is that I need to declare the list called puzzle elsewhere since it's suppose to be a class variable but from python code I've I don't think that's true not to I'm not sure since it's 2d and writing puzzle = [][] is wrong.
Sorry here's the whole output with error.
Welcome to sudoku!!!
what level of difficultly do you want today?easy
Traceback (most recent call last):
File "sudoku_maker.py", line 49, in <module>
Puzzle.main()
File "sudoku_maker.py", line 43, in main
self.createEasy(self)
NameError: name 'self' is not defined
It seems like you want main() to be a class method or a static method rather than an instance method. Class methods are methods that are not bound to an object but to a class. In that case, you need to define it clearly.
https://docs.python.org/3.5/library/functions.html#classmethod
https://docs.python.org/3.5/library/functions.html#staticmethod
This answer clearly explains the difference between class methods and static methods.
What is the difference between #staticmethod and #classmethod in Python?
One more way of solving your problem is :
Make main() as an instance method by passing self as an argument.
main(self)
Create an object of Puzzle.
puzzle = Puzzle()
Call the object's main method.
puzzle.main()
The error disappears if you make the following changes:
Add self as a parameter of the main() function.
Create an instance of the class: p = Puzzle() and call p.main() then.
Write self.puzzle in the __init__ function instead of just puzzle.
(Then there are different errors though not related to this one)
First of all, in __init__ method when you declare puzzle attribute, you forgot the self, so it is not declared:
def __init__(self, **puzzle):
self.puzzle = [[0 for x in range(9)] for y in range(9)]
You also forgot de self when declaring the main function. And, inside of this one you got an error too, when you call Puzzle.puzzle, it should be with the self instance:
def main(self):
print("Welcome to sudoku!!!")
answer = input( "what level of difficultly do you want today? ")
if (answer == "easy"):
self.createEasy()
for x in self.puzzle:
for y in x:
print(y)
print('\n')
And finally, when you call the function. You need to create the instance of Puzzle first, but you are using Puzzle.main, so your not initializing the object, so the self instance will not exist.
You have to do it like this:
Puzzle().main()
However, there's another error when using randint(a, b), because this function generate a random int between a and b, but including the limits, so when you call it in createEasy, the 9 should not be in the limits.
I am trying to write a simple workflow/pipeline object in python where one can chain many functions together and execute them in the correct order. So, eventually I end up with a graph where the outputs from one function gets piped as input to another function and I wanted to be able to map these variables between functions. One way I thought I can do this is as follows:
class Node1(object):
def __init__(self):
self.inputs = {}
self.inputs['a'] = None
self.inputs['b'] = None
self.outputs = {}
self.outputs['result'] = None
def add_input(self, key, value):
self.inputs[key] = value
def run(self):
self.outputs['result'] = 42
class Node2(object):
def __init__(self):
self.inputs = {}
self.inputs['num1'] = None
self.outputs = {}
self.outputs['num2'] = None
def add_input(self, key, value):
self.inputs[key] = value
def run(self):
self.outputs['num2'] = self.inputs['num1'] * 5
Now one can do something like:
n1 = Node1()
n1.inputs['a'] = 5
n1.inputs['b'] = 15
n2 = Node2()
n2.inputs['num1'] = n1.outputs['num2']
n1.run()
n2.run()
Now, the problem with this approach is that n1.outputs['num2'] is only computed after the run() function is called on the n1 object. As far as I am aware, I cannot use references in python, so this code fails as it tries to multiple None * 5. A fix is:
n1.run()
n2.inputs['num1'] = n1.outputs['num2']
n2.run()
However, this is annoying as it makes specifying the workflow quite difficult as the connections have to be made after bits of the workflow is run.
Can anyone suggest a good solution for this problem? In C++, I could simply use a reference but I am not sure what to do in this case in python.
You cannot store links to simple values (integers, strings) but you can store them to containers (dict, list).
So you could change your logic to be:
n1 = Node1()
n2 = Node1()
n2.connect_input('num1', n1.outputs, 'num2')
Where you have the following method:
def connect_input(self, input_name, outputs, output_name):
self.inputs[input_name] = [outputs, output_name]
But you would then need to modify your run methods to use the following format:
def run(self):
outputs, key = self.inputs['num1']
self.outputs['num2'] = outputs[key] * 5
I am trying to write a simple workflow/pipeline object in python where one can chain many functions together and execute them in the correct order.
Take a look at RxPy.
Observable.just({'a': 5, 'b': 15}) \
.map(lambda x: x['a'] + x['b']) \
.map(lambda x: x * 5) \
.subscribe(lambda x: print x)
There are lot of operators that let describe quite complicated pipelines.
I want to create a number that you can set a maximum and/or minimum value to. So it'd work like this:
>>> n = myNum(5, minimum=0, maximum=10)
>>> n += 10
>>> print(n)
10
>>> n = myNum(-12, minimum=3)
>>> print(n)
3
The problem is that however I try to implement it seems to become very tedius and long despite the fact that it seems like such a simple concept. Is there an elegant way to do this without, say, overriding every single magic method having to do with numbers?
You should rather do something like that
n = min(max(5,10),0)
and
n = min(-12,3)
From your comment, you can make a convenient function :
def between_min_max(value, min_val, max_val):
return min(max(value, max_val), min_val)
and use it later in your code :
min_val = 0
max_val = 10
n = between_min_max(5,min_val,max_val)
# and you can reuse min_val, max_val later
This might be overkill. You could try creating your own class and then overloading operators on your class. You can create the class mynum:
class mynum:
def __init__ (self, val, minval, maxval):
self.val = val
self.minval = minval
self.maxval = maxval
and declare your numbers in your code as instances of mynum:
n = mynum(5, 0, 10) # for instance
Then you can overload operators on your class, so that it behaves the way that you want it to. For adding, put this inside of your mynum class definition:
def __add__(self, operand): # overload things like n + 10
self.val += operand
if self.val > self.maxval: # replace checks with max(min(...)...) if you like
self.val = self.maxval
elif self.val < self.minval:
self.val = self.minval
return self.val
This post has some good info on a starting point for this. The down side is that this method would require that you overload every operator that could possibly give you an invalid value for your mynum instance.
I have some Python code in below written in Python 2.7 and I have problem with calling a function form inside another function.
class CSP:
def __init__(self, matrix):
self.X = []
self.D = []
self.C = []
self.matrix = util.copyMatrix(matrix)
self.counter = 0
# Matrix to Vector
vector = [item for line in self.matrix for item in line]
chars = map(str, vector)
result = ['*' if item == '0' else item for item in chars]
def solve(self):
""" Returns the result matrix.
The sudoku matrix is self.matrix.
Use util.printMatrix in purpose of debugging if needed. """
"*** YOUR CODE HERE ***"
def init(self,result):
for i in range(9):
for j in range(1,10):
var = var_char[i]+str(j)
self.X.append(var)
domain = set([1,2,3,4,5,6,7,8,9])
self.D.append(domain)
gamelist = result
for i in range(len(gamelist)):
if(re.match("\d+",gamelist[i])):
self.D[i] = set([int(gamelist[i])])
self.set_constraints()
#########################################################################
def set_constraints(self):
for x in self.X:
for y in self.X:
if((x[0] == y[0] and x[1] != y[1]) or (x[1] == y[1] and x[0] != y[0])):
flag = True
for c in self.C:
if(x in c and y in c):
flag = False
if(flag):
self.C.append(set([x,y]))
for a in [0,3,6]:
for b in [0,3,6]:
self.set_cube_constraints(a,b)
How to call init() function in solve() and also call self.set_constraint() inside init() function?
Within function solve(), init() is a function, not a method. Therefore it can only be called in the same manner that any other unbound function can be called: by passing the correct number of arguments to it. This would work:
init(self, results)
Note that you need to explicitly pass a reference to the object in self because init() is not a method. Within solve() self refers to the CSP instance, so this should work.
However, set_constraints() is also a normal function, so you can not call it from init() with self.set_constraints(), but set_constraints(self) should work. Note that you need to declare function set_constraints() before init() otherwise you will get a "referenced before assignment" error.
Having said all that, this is just awful. Why not make init() and set_constraints() proper methods of the class?
set_constraints is not a part of the class and therefore cannot be called with self.
If you put it one level up (remove one indentation level of it) then your code should work better.
I can see that this is some kind of coding exercise and you are told to write code in one particular place. I think you may be overcomplicating the answer because what you are coding here looks very messy by design and you should probably split out your functionality a lot more if this should be considerered clean code.
in my Python code I have the following issue: i have to copy the same object many times and then pass each copy to a function that modifies it. I tried with copy.deepcopy, but it's really computationally expensive, then i tried with itertools.repeat(), but it was a bad idea because after that i've to modify the object. So i wrote a simple method that copy an object simply returning a new object with the same attributes:
def myCopy(myObj):
return MyClass(myObj.x, myObj.y)
The problem is that this is really unefficient too: i've to make it abaout 6000 times and it takes more than 10 seconds! So, does exist a better way to do that?
The object to copy and modify is table, that is created like that:
def initialState(self):
table = []
[table.append(Events()) for _ in xrange(self.numSlots)]
for ei in xrange(self.numEvents - 1):
ei += 1
enr = self.exams[ei]
k = random.randint(0, self.numSlots - 1)
table[k].Insert(ei, enr)
x = EtState(table)
return x
class Event:
def __init__(self, i, enrollment, contribution = None):
self.ei = i
self.enrollment = enrollment
self.contribution = contribution
class Events:
def __init__(self):
self.count = 0
self.EventList = []
def getEvent(self, i):
return self.EventList[i].ei
def getEnrollment(self, i):
return self.EventList[i].enrollment
def Insert(self, ei, enroll = 1, contribution = None):
self.EventList.append(Event(ei, enroll, contribution))
self.count += 1
def eventIn(self, ei):
for x in xrange(self.count):
if(self.EventList[x].ei == ei):
self.EventList[x].enrollment += 1
return True
return False
More Pythonic way would be to create function(s) that modify the object, but don't modify the original object, just return its modified form. But from this code you posted, it is not clear what are you acutally trying to do, you should make a more simple (generic) example of what are you trying to do.
Since Object in Python means anything, class, instance, dict, list, tuple, 'a', etc..
to copy object is kind of not clear...
You mean copy instance of a Class if I understood it correctly
So write a function that takes one instance of that class, in that function create another instance and copy all atributes you need..