问题
I'm learning Python OOP and trying to convert a Java class to a Python class
See page 15 in this PDF for Java code google doc link
class QuickFindUF:
"""docstring for QuickFindUF"""
def __init__(self, n):
self.id = []
for e in range(n):
self.id.append(e)
def connected(self,p,q):
return self.id[p]==self.id[q]
def union(self,p,q):
self.pid = self.id[p]
self.qid = self.id[q]
for i in range(len(self.id)):
if(self.id[i]==self.pid):
self.id[i]=self.qid
quf = QuickFindUF(9)
quf.union(3,4)
print quf.connected(3,4)
There are 16 self
keywords in this class. Is there a better way to write this class?
回答1:
Yea, you don't want to assign these variables to self
, these are local variables:
def union(self,p,q):
self.pid = self.id[p]
self.qid = self.id[q]
for i in range(len(self.id)):
if(self.id[i]==self.pid):
self.id[i]=self.qid
Should be:
def union(self,p,q):
pid = self.id[p]
qid = self.id[q]
for i in range(len(self.id)):
if self.id[i] == pid:
self.id[i] = qid
You only use self
when referring to instance variables, not to any variable inside of a method.
回答2:
You could use some shortcuts:
class QuickFindUF:
"""docstring for QuickFindUF"""
def __init__(self, n):
self.id = range(n)
def connected(self,p,q):
_id = self.id
return _id[p]==_id[q]
def union(self,p,q):
_id = self.id
pid = _id[p]
qid = _id[q]
for (k, _i) in enumerate(_id):
if (_i == pid):
_id[k]=qid
Note the simplification in __init__
, as pointed by @katrielalex, and the use of enumerate
instead of looping on range(len(self.id))
.
Using shortcuts can be a bit more efficient (as you save a call to __getattr__
), but should not impair readability.
回答3:
Make use of list(range())
and enumerate
like so:
class QuickFindUF:
def __init__(self, n):
self.id = list(range(n))
def connected(self, i, j):
return self.id[i] == self.id[j]
def union(self, i, j):
x = self.id[i]
y = self.id[j]
for index, elem in enumerate(self.id):
if elem == x:
self.id[index] = y
But even better: Don't forget that Python is multi-paradigm. If methods have generic aspects, then outsource these to pure functions:
def map_each_x_to_y(array, x, y):
for i, elem in enumerate(array):
if elem == x:
array[i] = y
return array
def map_ith_values_to_jth(array, i, j):
x = array[i]
y = array[j]
return map_each_x_to_y(array, x, y)
This more declarative style might seem verbose, but it makes the desired behaviour of the union
method's intent easier to understand:
def union(self, i, j):
self.id = map_ith_values_to_jth(self.id, i, j)
And makes your code more re-usable for other things.
来源:https://stackoverflow.com/questions/11943652/python-too-many-self-in-class