python too many self in class

丶灬走出姿态 提交于 2021-02-19 06:19:06

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!