I am trying to group all Patient objects by their surnames.
My code:
class Patient:
def __init__(self, first_name, surname, age, mobile, postcode):
self.__first_name = first_name
self.__surname = surname
self.__doctor = "None"
self.__age = age
self.__mobile = mobile
self.__postcode = postcode
self.__symptoms = ""
def full_name(self) :
return "{} {}".format(self.__first_name, self.__surname)
def __str__(self):
return f'{self.full_name():^20}|{self.__doctor:^6}|{self.__age:^4}|{self.__mobile:^15}|{self.__postcode:^10}'
patients = [Patient('Sara','Cath', 20, '07012345678','B1 234'),
Patient('Mike','Abe', 37,'07555551234','L2 2AB'),
Patient('Daivd','Barr', 15, '07123456789','C1 ABC'),
Patient('Gerald','Abe', 21, '07012345678','L2 2AB'),
Patient('Sara','Abe', 19, '07012345678','L2 2AB'),
Patient('Jane','Barr', 35, '07123456789','C1 ABC')]
patients.sort(key=lambda y: y.__surname)
print(patients[0])
print(patients[1])
print(patients[2])
print(patients[3])
print(patients[4])
print(patients[5])
print()
newPat = sorted(patients, key=lambda y: y.__surname)
print(newPat[0])
print(newPat[1])
print(newPat[2])
print(newPat[3])
print(newPat[4])
print(newPat[5])
My code has the surname attribute self.__surname = surname
in the __init__
function, the full_name
function and in both sorting functions, but when I try to run it gives me the AttributeError: 'Patient' object has no attribute '__surname'
Error:
File "c:\users\mundane\downloads\pythonfiles\files\untitled0.py", line 25, in <lambda>
patients.sort(key=lambda y: y.__surname)
AttributeError: 'Patient' object has no attribute '__surname'
If I replace each of the four .__surname
with literally anything else - like .xyzsurname
- it works and correctly prints:
Mike Abe | None | 37 | 07555551234 | L2 2AB
Gerald Abe | None | 21 | 07012345678 | L2 2AB
Sara Abe | None | 19 | 07012345678 | L2 2AB
Daivd Barr | None | 15 | 07123456789 | C1 ABC
Jane Barr | None | 35 | 07123456789 | C1 ABC
Sara Cath | None | 20 | 07012345678 | B1 234
Mike Abe | None | 37 | 07555551234 | L2 2AB
Gerald Abe | None | 21 | 07012345678 | L2 2AB
Sara Abe | None | 19 | 07012345678 | L2 2AB
Daivd Barr | None | 15 | 07123456789 | C1 ABC
Jane Barr | None | 35 | 07123456789 | C1 ABC
Sara Cath | None | 20 | 07012345678 | B1 234
Is there anyway for me to keep the double underscore for the attribute by using another way to order a list of objects?
You can use the built in dir()
method to find out what attributes your Patient objects do have. Running that yields:
['_Patient__age',
'_Patient__doctor',
'_Patient__first_name',
'_Patient__mobile',
'_Patient__postcode',
'_Patient__surname',
'_Patient__symptoms',
'__class__',
'__delattr__',
'__dict__',
'__dir__',
'__doc__',
'__eq__',
'__format__',
'__ge__',
'__getattribute__',
'__gt__',
'__hash__',
'__init__',
'__init_subclass__',
'__le__',
'__lt__',
'__module__',
'__ne__',
'__new__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__setattr__',
'__sizeof__',
'__str__',
'__subclasshook__',
'__weakref__',
'full_name']
You can see that because you are using double underscores (meaning that the attributes are not intended to be interacted with outside the class) Python is hiding them as _Patient__surname
. Therefore it will work if you change your sort to patients.sort(key=lambda y: y._Patient__surname)