Few weeks ago I asked a question on increasing the speed of a function written in Python. At that time, TryPyPy brought to my attention the possibility of using Cython for doing so. He also kindly gave an example of how I could Cythonize that code snippet. I want to do the same with the code below to see how fast I can make it by declaring variable types. I have a couple of questions related to that. I have seen the Tutorial on the cython.org, but I still have some questions. They are closely related:
I don't know any C. What parts do I need to learn, to use Cython to declare variable types?
What is the C type corresponding to python lists and tuples? For example, I can use double in Cython for float in Python. What do I do for lists? In general, where do I find the corresponding C type for a given Python type.
Any example of how I could Cythonize the code below would be really helpful. I have inserted comments in the code that give information about the variable type.
class Some_class(object):
** Other attributes and functions **
def update_awareness_status(self, this_var, timePd):
'''Inputs: this_var (type: float)
timePd (type: int)
Output: None'''
max_number = len(self.possibilities)
# self.possibilities is a list of tuples.
# Each tuple is a pair of person objects.
k = int(math.ceil(0.3 * max_number))
actual_number = random.choice(range(k))
chosen_possibilities = random.sample(self.possibilities,
actual_number)
if len(chosen_possibilities) > 0:
# chosen_possibilities is a list of tuples, each tuple is a pair
# of person objects. I have included the code for the Person class
# below.
for p1,p2 in chosen_possibilities:
# awareness_status is a tuple (float, int)
if p1.awareness_status[1] < p2.awareness_status[1]:
if p1.value > p2.awareness_status[0]:
p1.awareness_status = (this_var, timePd)
else:
p1.awareness_status = p2.awareness_status
elif p1.awareness_status[1] > p2.awareness_status[1]:
if p2.value > p1.awareness_status[0]:
p2.awareness_status = (price, timePd)
else:
p2.awareness_status = p1.awareness_status
else:
pass
class Person(object):
def __init__(self,id, value):
self.value = value
self.id = id
self.max_val = 50000
## Initial awareness status.
self.awarenessStatus = (self.max_val, -1)
As a general note, you can see exactly what C code Cython generates for every source line by running the cython command with the -a "annotate" option. See the Cython documentation for examples. This is extremely helpful when trying to find bottlenecks in a function's body.
Also, there's the concept of "early binding for speed" when Cython-ing your code. A Python object (like instances of your Person class below) use general Python code for attribute access, which is slow when in an inner loop. I suspect that if you change the Person class to a cdef class, then you will see some speedup. Also, you need to type the p1 and p2 objects in the inner loop.
Since your code has lots of Python calls (random.sample for example), you likely won't get huge speedups unless you find a way to put those lines into C, which takes a good amount of effort.
You can type things as a tuple or a list, but it doesn't often mean much of a speedup. Better to use C arrays when possible; something you'll have to look up.
I get a factor of 1.6 speedup with the trivial modifications below. Note that I had to change some things here and there to get it to compile.
ctypedef int ITYPE_t
cdef class CyPerson:
# These attributes are placed in the extension type's C-struct, so C-level
# access is _much_ faster.
cdef ITYPE_t value, id, max_val
cdef tuple awareness_status
def __init__(self, ITYPE_t id, ITYPE_t value):
# The __init__ function is much the same as before.
self.value = value
self.id = id
self.max_val = 50000
## Initial awareness status.
self.awareness_status = (self.max_val, -1)
NPERSONS = 10000
import math
import random
class Some_class(object):
def __init__(self):
ri = lambda: random.randint(0, 10)
self.possibilities = [(CyPerson(ri(), ri()), CyPerson(ri(), ri())) for i in range(NPERSONS)]
def update_awareness_status(self, this_var, timePd):
'''Inputs: this_var (type: float)
timePd (type: int)
Output: None'''
cdef CyPerson p1, p2
price = 10
max_number = len(self.possibilities)
# self.possibilities is a list of tuples.
# Each tuple is a pair of person objects.
k = int(math.ceil(0.3 * max_number))
actual_number = random.choice(range(k))
chosen_possibilities = random.sample(self.possibilities,
actual_number)
if len(chosen_possibilities) > 0:
# chosen_possibilities is a list of tuples, each tuple is a pair
# of person objects. I have included the code for the Person class
# below.
for persons in chosen_possibilities:
p1, p2 = persons
# awareness_status is a tuple (float, int)
if p1.awareness_status[1] < p2.awareness_status[1]:
if p1.value > p2.awareness_status[0]:
p1.awareness_status = (this_var, timePd)
else:
p1.awareness_status = p2.awareness_status
elif p1.awareness_status[1] > p2.awareness_status[1]:
if p2.value > p1.awareness_status[0]:
p2.awareness_status = (price, timePd)
else:
p2.awareness_status = p1.awareness_status
C does not directly know the concept of lists.
The basic data types are int (char, short, long), float/double (all of which have pretty straightforward mappings to python) and pointers.
If the concept of pointers is new to you, have a look at: Wikipedia:Pointers
Pointers can then be used as tuple/array replacements in some cases. Pointers of chars are the base for all strings.
Say you have an array of integers, you would then store it in as a continuous chunk of memory with a start address, you define the type (int) and that it’s a pointer (*):
cdef int * array;
Now you can access each element of the array like this:
array[0] = 1
However, memory has to be allocated (e.g. using malloc) and advanced indexing will not work (e.g. array[-1] will be random data in memory, this also hold for indexes exceeding the width of the reserved space).
More complex types don't directly map to C, but often there is a C way to do something that might not require the python types (e.g. a for loop does not need a range array/iterator).
As you noticed yourself, writing good cython code requires more detailed knowledge of C, so heading forward to a tutorial is probably the best next step.
Related
How can I pass an integer by reference in Python?
I want to modify the value of a variable that I am passing to the function. I have read that everything in Python is pass by value, but there has to be an easy trick. For example, in Java you could pass the reference types of Integer, Long, etc.
How can I pass an integer into a function by reference?
What are the best practices?
It doesn't quite work that way in Python. Python passes references to objects. Inside your function you have an object -- You're free to mutate that object (if possible). However, integers are immutable. One workaround is to pass the integer in a container which can be mutated:
def change(x):
x[0] = 3
x = [1]
change(x)
print x
This is ugly/clumsy at best, but you're not going to do any better in Python. The reason is because in Python, assignment (=) takes whatever object is the result of the right hand side and binds it to whatever is on the left hand side *(or passes it to the appropriate function).
Understanding this, we can see why there is no way to change the value of an immutable object inside a function -- you can't change any of its attributes because it's immutable, and you can't just assign the "variable" a new value because then you're actually creating a new object (which is distinct from the old one) and giving it the name that the old object had in the local namespace.
Usually the workaround is to simply return the object that you want:
def multiply_by_2(x):
return 2*x
x = 1
x = multiply_by_2(x)
*In the first example case above, 3 actually gets passed to x.__setitem__.
Most cases where you would need to pass by reference are where you need to return more than one value back to the caller. A "best practice" is to use multiple return values, which is much easier to do in Python than in languages like Java.
Here's a simple example:
def RectToPolar(x, y):
r = (x ** 2 + y ** 2) ** 0.5
theta = math.atan2(y, x)
return r, theta # return 2 things at once
r, theta = RectToPolar(3, 4) # assign 2 things at once
Not exactly passing a value directly, but using it as if it was passed.
x = 7
def my_method():
nonlocal x
x += 1
my_method()
print(x) # 8
Caveats:
nonlocal was introduced in python 3
If the enclosing scope is the global one, use global instead of nonlocal.
Maybe it's not pythonic way, but you can do this
import ctypes
def incr(a):
a += 1
x = ctypes.c_int(1) # create c-var
incr(ctypes.ctypes.byref(x)) # passing by ref
Really, the best practice is to step back and ask whether you really need to do this. Why do you want to modify the value of a variable that you're passing in to the function?
If you need to do it for a quick hack, the quickest way is to pass a list holding the integer, and stick a [0] around every use of it, as mgilson's answer demonstrates.
If you need to do it for something more significant, write a class that has an int as an attribute, so you can just set it. Of course this forces you to come up with a good name for the class, and for the attribute—if you can't think of anything, go back and read the sentence again a few times, and then use the list.
More generally, if you're trying to port some Java idiom directly to Python, you're doing it wrong. Even when there is something directly corresponding (as with static/#staticmethod), you still don't want to use it in most Python programs just because you'd use it in Java.
Maybe slightly more self-documenting than the list-of-length-1 trick is the old empty type trick:
def inc_i(v):
v.i += 1
x = type('', (), {})()
x.i = 7
inc_i(x)
print(x.i)
A numpy single-element array is mutable and yet for most purposes, it can be evaluated as if it was a numerical python variable. Therefore, it's a more convenient by-reference number container than a single-element list.
import numpy as np
def triple_var_by_ref(x):
x[0]=x[0]*3
a=np.array([2])
triple_var_by_ref(a)
print(a+1)
output:
7
The correct answer, is to use a class and put the value inside the class, this lets you pass by reference exactly as you desire.
class Thing:
def __init__(self,a):
self.a = a
def dosomething(ref)
ref.a += 1
t = Thing(3)
dosomething(t)
print("T is now",t.a)
In Python, every value is a reference (a pointer to an object), just like non-primitives in Java. Also, like Java, Python only has pass by value. So, semantically, they are pretty much the same.
Since you mention Java in your question, I would like to see how you achieve what you want in Java. If you can show it in Java, I can show you how to do it exactly equivalently in Python.
class PassByReference:
def Change(self, var):
self.a = var
print(self.a)
s=PassByReference()
s.Change(5)
class Obj:
def __init__(self,a):
self.value = a
def sum(self, a):
self.value += a
a = Obj(1)
b = a
a.sum(1)
print(a.value, b.value)// 2 2
In Python, everything is passed by value, but if you want to modify some state, you can change the value of an integer inside a list or object that's passed to a method.
integers are immutable in python and once they are created we cannot change their value by using assignment operator to a variable we are making it to point to some other address not the previous address.
In python a function can return multiple values we can make use of it:
def swap(a,b):
return b,a
a,b=22,55
a,b=swap(a,b)
print(a,b)
To change the reference a variable is pointing to we can wrap immutable data types(int, long, float, complex, str, bytes, truple, frozenset) inside of mutable data types (bytearray, list, set, dict).
#var is an instance of dictionary type
def change(var,key,new_value):
var[key]=new_value
var =dict()
var['a']=33
change(var,'a',2625)
print(var['a'])
Very often I process single elements of tuples like this:
size, duration, name = some_external_function()
size = int(size)
duration = float(duration)
name = name.strip().lower()
If some_external_function would return some equally typed tuple I could use map in order to have a (more functional) closed expression:
size, duration, name = map(magic, some_external_function())
Is there something like an element wise map? Something I could run like this:
size, duration, name = map2((int, float, strip), some_external_function())
Update: I know I can use comprehension together with zip, e.g.
size, duration, name = [f(v) for f, v in zip(
(int, float, str.strip), some_external_function())]
-- I'm looking for a 'pythonic' (best: built-in) solution!
To the Python developers:
What about
(size)int, (duration)float, (name)str.strip = some_external_function()
?
If I see this in any upcoming Python version, I'll send you a beer :)
Quite simply: use a function and args unpacking...
def transform(size, duration, name):
return int(size), float(duration), name.strip().lower()
# if you don't know what the `*` does then follow the link above...
size, name, duration = transform(*some_external_function())
Dead simple, perfectly readable and testable.
Map does not really apply here. It comes in handy when you want to apply a simple function over all elements of a list, such as map(float, list_ints).
There isn't one explicit built-in function to do this. However, a way to simplify your approach and avoid n separate calls to the functions to be applied, could be to define an iterable containing the functions, and apply them to the returned non-unpacked tuple from the function on a generator comprehension and then unpack them:
funcs = int, float, lambda x: x.strip().lower()
t = 1., 2, 'Some String ' # example returned tuple
size, duration, name = (f(i) for f,i in zip(funcs, t))
Or perhaps a little cleaner:
def transform(t, funcs):
return (f(i) for f,i in zip(funcs, t))
size, duration, name = transform(t, funcs)
size
# 1
duration
# 2.0
name
# 'some string'
class SomeExternalData:
def __init__(self, size: int, duration: float, name: str):
self.size = size
self.duration = duration
self.name = name.strip().lower()
#classmethod
def from_strings(cls, size, duration, name):
return cls(int(size), float(duration), name)
data = SomeExternalData.from_strings(*some_external_function())
It's far from a one-liner, but it's the most declarative, readable, reusable and maintainable approach to this problem IMO. Model your data explicitly instead of treating individual values ad hoc.
AFAIK there is no built-in solution so we can write generic function ourselves and reuse it afterwards
def map2(functions, arguments): # or some other name
return (function(argument) for function, argument in zip(functions, arguments)) # we can also return `tuple` here for example
The possible problem can be that number of arguments can be less than number of functions or vice versa, but in your case it shouldn't be a problem.
After that
size, duration, name = map2((int, float, str.strip), some_external_function())
We can go further with functools.partial and give a name to our "transformer" like
from functools import partial
...
transform = partial(map2, (int, float, str.strip))
and reuse it in other places as well.
Based on Bruno's transform, which I think is the best answer to the problem, I wanted to see if I could make a generic transform function that did not need a hardcoded set of formatters, but could take any number of elements, given a matching number of formatters.
(This is really overkill, unless you need a large number of such magic mappers or if you need to generate them dynamically.)
Here I am using Python 3.6's guaranteed dictionary order to "unpack" the formatters in their declared order and separate them from inputs variadic.
def transform(*inputs, **tranformer):
return [f(val) for val, f in zip(inputs, tranformer.values())]
size, duration, name = transform(*some_external_function(), f1=int, f2=float, f3=str.lower)
And to make the process even more generic and allow predefined transform functions you can use operator.partial.
from functools import partial
def prep(f_tranformer, *format_funcs):
formatters = {"f%d"%ix : func for ix, func in enumerate(format_funcs)}
return partial(transform, **formatters)
transform2 = prep(transform, int, float, str.lower)
which you can use as:
size, duration, name = transform2(*some_external_function())
I'll second bruno's answer as being my preferred choice. I guess it will depend on how often you are calling this function will determine how much value it is in refactoring such a hindrance. If you were going to be calling that external function multiple times, you could also consider decorating it:
from functools import wraps
def type_wrangler(func):
def wrangler():
n,s,d = func()
return str(n), int(s), float(d)
return wrangler
def external_func():
return 'a_name', '10', '5.6'
f = type_wrangler(external_func)
print(f())
I am working with 2 data sets on the order of ~ 100,000 values. These 2 data sets are simply lists. Each item in the list is a small class.
class Datum(object):
def __init__(self, value, dtype, source, index1=None, index2=None):
self.value = value
self.dtype = dtype
self.source = source
self.index1 = index1
self.index2 = index2
For each datum in one list, there is a matching datum in the other list that has the same dtype, source, index1, and index2, which I use to sort the two data sets such that they align. I then do various work with the matching data points' values, which are always floats.
Currently, if I want to determine the relative values of the floats in one data set, I do something like this.
minimum = min([x.value for x in data])
for datum in data:
datum.value -= minimum
However, it would be nice to have my custom class inherit from float, and be able to act like this.
minimum = min(data)
data = [x - minimum for x in data]
I tried the following.
class Datum(float):
def __new__(cls, value, dtype, source, index1=None, index2=None):
new = float.__new__(cls, value)
new.dtype = dtype
new.source = source
new.index1 = index1
new.index2 = index2
return new
However, doing
data = [x - minimum for x in data]
removes all of the extra attributes (dtype, source, index1, index2).
How should I set up a class that functions like a float, but holds onto the extra data that I instantiate it with?
UPDATE: I do many types of mathematical operations beyond subtraction, so rewriting all of the methods that work with a float would be very troublesome, and frankly I'm not sure I could rewrite them properly.
I suggest subclassing float and using a couple decorators to "capture" the float output from any method (except for __new__ of course) and returning a Datum object instead of a float object.
First we write the method decorator (which really isn't being used as a decorator below, it's just a function that modifies the output of another function, AKA a wrapper function):
def mydecorator(f,cls):
#f is the method being modified, cls is its class (in this case, Datum)
def func_wrapper(*args,**kwargs):
#*args and **kwargs are all the arguments that were passed to f
newvalue = f(*args,**kwargs)
#newvalue now contains the output float would normally produce
##Now get cls instance provided as part of args (we need one
##if we're going to reattach instance information later):
try:
self = args[0]
##Now check to make sure new value is an instance of some numerical
##type, but NOT a bool or a cls type (which might lead to recursion)
##Including ints so things like modulo and round will work right
if (isinstance(newvalue,float) or isinstance(newvalue,int)) and not isinstance(newvalue,bool) and type(newvalue) != cls:
##If newvalue is a float or int, now we make a new cls instance using the
##newvalue for value and using the previous self instance information (arg[0])
##for the other fields
return cls(newvalue,self.dtype,self.source,self.index1,self.index2)
#IndexError raised if no args provided, AttributeError raised of self isn't a cls instance
except (IndexError, AttributeError):
pass
##If newvalue isn't numerical, or we don't have a self, just return what
##float would normally return
return newvalue
#the function has now been modified and we return the modified version
#to be used instead of the original version, f
return func_wrapper
The first decorator only applies to a method to which it is attached. But we want it to decorate all (actually, almost all) the methods inherited from float (well, those that appear in the float's __dict__, anyway). This second decorator will apply our first decorator to all of the methods in the float subclass except for those listed as exceptions (see this answer):
def for_all_methods_in_float(decorator,*exceptions):
def decorate(cls):
for attr in float.__dict__:
if callable(getattr(float, attr)) and not attr in exceptions:
setattr(cls, attr, decorator(getattr(float, attr),cls))
return cls
return decorate
Now we write the subclass much the same as you had before, but decorated, and excluding __new__ from decoration (I guess we could also exclude __init__ but __init__ doesn't return anything, anyway):
#for_all_methods_in_float(mydecorator,'__new__')
class Datum(float):
def __new__(klass, value, dtype="dtype", source="source", index1="index1", index2="index2"):
return super(Datum,klass).__new__(klass,value)
def __init__(self, value, dtype="dtype", source="source", index1="index1", index2="index2"):
self.value = value
self.dtype = dtype
self.source = source
self.index1 = index1
self.index2 = index2
super(Datum,self).__init__()
Here are our testing procedures; iteration seems to work correctly:
d1 = Datum(1.5)
d2 = Datum(3.2)
d3 = d1+d2
assert d3.source == 'source'
L=[d1,d2,d3]
d4=max(L)
assert d4.source == 'source'
L = [i for i in L]
assert L[0].source == 'source'
assert type(L[0]) == Datum
minimum = min(L)
assert [x - minimum for x in L][0].source == 'source'
Notes:
I am using Python 3. Not certain if that will make a difference for you.
This approach effectively overrides EVERY method of float other than the exceptions, even the ones for which the result isn't modified. There may be side effects to this (subclassing a built-in and then overriding all of its methods), e.g. a performance hit or something; I really don't know.
This will also decorate nested classes.
This same approach could also be implemented using a metaclass.
The problem is when you do :
x - minimum
in terms of types you are doing either :
datum - float, or datum - integer
Either way python doesn't know how to do either of them, so what it does is look at parent classes of the arguments if it can. since datum is a type of float, it can easily use float - and the calculation ends up being
float - float
which will obviously result in a 'float' - python has no way of knowing how to construct your datum object unless you tell it.
To solve this you either need to implement the mathematical operators so that python knows how to do datum - float or come up with a different design.
Assuming that 'dtype', 'source', index1 & index2 need to stay the same after a calculation - then as an example your class needs :
def __sub__(self, other):
return datum(value-other, self.dtype, self.source, self.index1, self.index2)
this should work - not tested
and this will now allow you to do this
d = datum(23.0, dtype="float", source="me", index1=1)
e = d - 16
print e.value, e.dtype, e.source, e.index1, e.index2
which should result in :
7.0 float me 1 None
How to create a list of a specific type of object but empty? Is it possible? I want to create an array of objects (the type is called Ghosts) which later will contain different types that inherit from that one class called Ghosts. It's all very simple in C++ but i'm not sure how to do that in python. I tried something like this:
self.arrayOfGhosts = [[Ghost() for x in xrange(100)] for x in xrange(100)]
but it's already initialised by objects, and I don't need it, is there a way to initialise it by 0 but have an list of type Ghost?
As you see I'm very new to python. Any help will be highly appreciated.
Python is a dynamic language so there is no concept of array of type.
You create an empty generic list with:
self.arrayOfGhosts = []
You don't care about the capacity of the list as it's dynamically allocated as well.
It's up to you to fill it with as many Ghost instances as you wish with:
self.arrayOfGhosts.append(Ghost())
The above is really enough, however:
If you really want to enforce this list to accept only Ghost and inheriting classes instances, you can create a custom list type like this:
class GhostList(list):
def __init__(self, iterable=None):
"""Override initializer which can accept iterable"""
super(GhostList, self).__init__()
if iterable:
for item in iterable:
self.append(item)
def append(self, item):
if isinstance(item, Ghost):
super(GhostList, self).append(item)
else:
raise ValueError('Ghosts allowed only')
def insert(self, index, item):
if isinstance(item, Ghost):
super(GhostList, self).insert(index, item)
else:
raise ValueError('Ghosts allowed only')
def __add__(self, item):
if isinstance(item, Ghost):
super(GhostList, self).__add__(item)
else:
raise ValueError('Ghosts allowed only')
def __iadd__(self, item):
if isinstance(item, Ghost):
super(GhostList, self).__iadd__(item)
else:
raise ValueError('Ghosts allowed only')
Then for two-dimensional list you use this class like:
self.arrayOfGhosts = []
self.arrayOfGhosts.append(GhostList())
self.arrayOfGhosts[0].append(Ghost())
Those are lists, not arrays. Python is a duck-typed language. Lists are heterogenously-typed anyway. For example. your list can contain an int, followed by str, followed by list, or whatever suits your fancy. You cannot restrict the type with stock classes, and that's against the philosophy of the language.
Just create an empty list, and add later.
self.arrayOfGhosts = []
Two-dimensional lists are simple. Just nest lists.
l = [[1, 2, 3], [4, 5, 6]]
l[0] # [1, 2, 3]
l[1][2] # 6
If you really want placeholders, just do something like the following.
[[None] * 100 for i in range(100)]
Python doesn't have arrays, unless you mean array.array, which is for C-ish types anyways. Arrays are the wrong level of abstraction in Python most of the time.
P.S. If you're using xrange, then you must be using Python 2. Unless you need very specific libraries, please stop, and use Python 3. See why.
P.P.S. You initialize with NULL, not 0 in C++. Never use 0 to mean NULL.
P.P.P.S. See PEP 8, the canonical Python style guide.
Lists in Python can grow as needed, they are not fixed in length like you might be used to in C or C++.
Therefore, there is no need to "initialize" a list in Python. Just create it when you need it, and then add to it as you like.
You absolutely don't need a "zeroed list" of your Ghost objects, simply do this:
scary_farm = [] # This is an empty list.
ghosts = []
# .. much later down in your code
mean_ghost = Ghost(scary_level=10, voice='Booooo!')
ghosts.append(mean_ghost)
casper = Ghost(scary_level=-1, voice="I'm the friendly ghost. Hee hee!")
ghosts.append(casper)
# ... later on
scary_farm.append(ghosts) # Now you have your 2-D list
for item in scary_farm:
for ghost in item:
print('{0.voice}'.format(ghost))
Note you also don't need a list of indexes when stepping through a list or any collection in Python. In C/C++ you might be used to:
for(i = 0; i < 10; i++)
{
cout << scary_farm[i] << endl;
}
But this is not required in Python as collection types can be iterated over directly.
I need to implement Dijkstra's Algorithm in Python. However, I have to use a 2D array to hold three pieces of information - predecessor, length and unvisited/visited.
I know in C a Struct can be used, though I am stuck on how I can do a similar thing in Python, I am told it's possible but I have no idea to be honest
Create a class for it.
class XXX(object):
def __init__(self, predecessor, length, visited):
self.predecessor = predecessor
self.length = length
self.visited = visited
Or use collections.namedtuple, which is particular cool for holding struct-like compound types without own behaviour but named members: XXX = collections.namedtuple('XXX', 'predecessor length visited').
Create one with XXX(predecessor, length, visited).
As mentioned above, you can use an instance of an object.
This author has a pretty convincing python implementation of Dijkstras in python.
#
# This file contains the Python code from Program 16.16 of
# "Data Structures and Algorithms
# with Object-Oriented Design Patterns in Python"
# by Bruno R. Preiss.
#
# Copyright (c) 2003 by Bruno R. Preiss, P.Eng. All rights reserved.
#
# http://www.brpreiss.com/books/opus7/programs/pgm16_16.txt
#
class Algorithms(object):
def DijkstrasAlgorithm(g, s):
n = g.numberOfVertices
table = Array(n)
for v in xrange(n):
table[v] = Algorithms.Entry()
table[s].distance = 0
queue = BinaryHeap(g.numberOfEdges)
queue.enqueue(Association(0, g[s]))
while not queue.isEmpty:
assoc = queue.dequeueMin()
v0 = assoc.value
if not table[v0.number].known:
table[v0.number].known = True
for e in v0.emanatingEdges:
v1 = e.mateOf(v0)
d = table[v0.number].distance + e.weight
if table[v1.number].distance > d:
table[v1.number].distance = d
table[v1.number].predecessor = v0.number
queue.enqueue(Association(d, v1))
result = DigraphAsLists(n)
for v in xrange(n):
result.addVertex(v, table[v].distance)
for v in xrange(n):
if v != s:
result.addEdge(v, table[v].predecessor)
return result
DijkstrasAlgorithm = staticmethod(DijkstrasAlgorithm)
Notice those pieces of information are 'held' in the object he is constructing by calling Algorithms.Entry(). Entry is a class and is defined like this:
class Entry(object):
"""
Data structure used in Dijkstra's and Prim's algorithms.
"""
def __init__(self):
"""
(Algorithms.Entry) -> None
Constructor.
"""
self.known = False
self.distance = sys.maxint
self.predecessor = sys.maxint
The self.known, self.distance... are those pieces of information. He does not set these explicit in the constructor (init) but sets them later. In Python you can access attributes with dot notation. for examle: myObject= Entry(). the myObject.known, myObject.distance... they are all public.
Encapsulate that information in a Python object and you should be fine.
Or you can simply use tuples or dictionaries inside your 2d array:
width=10
height=10
my2darray = []
for x in range(width):
my2darray[x]=[]
for x in range(width):
for y in range(height):
#here you set the tuple
my2darray[x][y] = (n,l,v)
#or you can use a dict..
my2darray[x][y] = dict(node=foo,length=12,visited=False)
Python is object oriented language. So think of it like moving from Structs in C to Classes of C++. You can use the same class structure in Python as well.