-1

I am trying to sort a list which is in a private class, i can sort it without getting private but can't in private.

First i open data and split it in main.py, and set a list call StudentDL in main.py and call it to Student.py , if I private Student.py, I can't sort the StudentDL list in main.py .

How can I sort the StudentDL list in main.py or Student.py after private Student.py?

Main.py:

from Student import Student

StudentDL = []
file = open('markdata.dat', 'r')
line = file.readline()

while line != '':
    StudentRec = line.split('_')
    StudentDL.append(Student(int(StudentRec[0]),str(StudentRec[1]),
                            float(StudentRec[2]),
                            float(StudentRec[3])))
    line = file.readline()
file.close()
for e in StudentDL:
    print (e)
for e in sorted(StudentDL, key=lambda c:c.sID):
    print (e)
print('='*20)
for e in sorted(StudentDL, key=lambda c:c.n):
    print (Student.overall(e))

Student.py:

class Student(object):
    numStudent = 0 
    def __init__(self,studentID,name,cwmark,exammark):
        Student.numStudent += 1
        self.__sID = studentID
        self.__n = name
        self.__cwm = cwmark
        self.__exm = exammark
        self.__om = (cwmark*0.4)+(exammark*0.6)

    def __str__(self):
        return '%-15s%-27s%-10.2f%7.2f'%\
            (self.__sID,self.__n,self.__cwm,self.__exm)

    def overall(self):
        return '%-15s%-27s%-12.2f%-7.2f%8.2f'%\
            (self.__sID,self.__n,self.__cwm,self.__exm,self.__om)

    def getoverall(self):
        return float(self.__om)

markdata:

50123456_lam tai man_70.0_60.0_
50223456_li tai man_60.0_90.5_
50323456_wong tai man_34.5_30.0_
50423456_ng tai man_90.5_70.0_
50523456_lau tai man_86.0_92.4_
50623456_chui tai man_70.0_64.5_
50723456_lim tai man_64.5_60.0_
50823456_pok tai man_37.5_35.50_
50923456_kim tai man_92.4_60.0_
50023456_tsang tai man_15.0_20.0_
50999999_chan peter_100.00_80.00_
eyllanesc
  • 235,170
  • 19
  • 170
  • 241

1 Answers1

0

Why do you expect to be able to access private attributes from outside the class? The whole point of private attributes is to prevent that (Python makes it easy to work around it, but you're explicitly violating encapsulation when you do it).

If the variables should be logically readable, with privacy being used primarily to prevent writes, Student can declare @property accessors:

class Student(object):
    numStudent = 0 
    def __init__(self,studentID,name,cwmark,exammark):
        ...

    @property
    def n(self):
        return self.__n

    @property
    def sID(self):
        return self.__sID

If that protection isn't needed though, then just declare your attributes without the leading __ in the first place, and leave them public.

ShadowRanger
  • 143,180
  • 12
  • 188
  • 271
  • I know that my question is so silly .. But my teacher told use to submit the program with private class and have a sort function . The tips he gives is sort it in private class , I am so confuse what to do ... – Wong Yat Cheong Jacky Oct 10 '18 at 00:20
  • @WongYatCheongJacky: Did your teacher perhaps mean to make class instances comparable by defining `__lt__` and [the other rich comparison operators](https://docs.python.org/3/reference/datamodel.html#object.__lt__)? That allows you to define a natural ordering of the class instances, and since `__lt__` is defined on the class, it has access to private members. Similarly, defining `@property` accessors would leave the underlying attributes private, while providing public read-only access (which would allow you to define `key` functions in terms of the properties). – ShadowRanger Oct 10 '18 at 00:26
  • [link](https://dpaste.de/jOrJ) and [link](https://dpaste.de/t0bD) i try to use __lt__ method but show a error on TypeError: __lt__() missing 1 required positional argument: 'other' – Wong Yat Cheong Jacky Oct 10 '18 at 02:26
  • @WongYatCheongJacky: You don't call `__lt__` directly (it's not forbidden, but it's silly to do so, and in the scenario you used it, makes no sense). It's just a function that gets called automatically when you test `studenta < studentb`, and Python's sorting functions use it implicitly as the default comparison when no `key` function is defined (or the object is part of the `key`). If `__lt__` is correctly defined, you just do `for e in sorted(StudentDL):` without passing a `key` function at all, and you'll iterate in sorted order. – ShadowRanger Oct 10 '18 at 03:11